Skip to content

Commit 42f50fd

Browse files
easyCZroboquat
authored andcommitted
[baseserver] Allow zero port to automatically assign port
1 parent 7ba0e6c commit 42f50fd

File tree

5 files changed

+45
-16
lines changed

5 files changed

+45
-16
lines changed

components/common-go/baseserver/options.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func WithHostname(hostname string) Option {
5151
func WithHTTPPort(port int) Option {
5252
return func(cfg *config) error {
5353
if port < 0 {
54-
return fmt.Errorf("http port must be greater than 0, got: %d", port)
54+
return fmt.Errorf("http must not be negative, got: %d", port)
5555
}
5656

5757
cfg.httpPort = port
@@ -62,7 +62,7 @@ func WithHTTPPort(port int) Option {
6262
func WithGRPCPort(port int) Option {
6363
return func(cfg *config) error {
6464
if port < 0 {
65-
return fmt.Errorf("grpc port must be greater than 0, got: %d", port)
65+
return fmt.Errorf("grpc port must not be negative, got: %d", port)
6666
}
6767

6868
cfg.grpcPort = port

components/common-go/baseserver/options_test.go

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,28 @@ func TestOptions(t *testing.T) {
4141
}, cfg)
4242
}
4343

44-
func TestWithTTPPort_ErrorsWithNegativePort(t *testing.T) {
45-
_, err := evaluateOptions(defaultConfig(), WithHTTPPort(-1))
46-
require.Error(t, err)
44+
func TestWithTTPPort(t *testing.T) {
45+
t.Run("negative", func(t *testing.T) {
46+
_, err := evaluateOptions(defaultConfig(), WithHTTPPort(-1))
47+
require.Error(t, err)
48+
})
49+
50+
t.Run("zero", func(t *testing.T) {
51+
_, err := evaluateOptions(defaultConfig(), WithHTTPPort(0))
52+
require.NoError(t, err)
53+
})
4754
}
4855

49-
func TestWithGRPCPort_ErrorsWithNegativePort(t *testing.T) {
50-
_, err := evaluateOptions(defaultConfig(), WithGRPCPort(-1))
51-
require.Error(t, err)
56+
func TestWithGRPCPort(t *testing.T) {
57+
t.Run("negative", func(t *testing.T) {
58+
_, err := evaluateOptions(defaultConfig(), WithGRPCPort(-1))
59+
require.Error(t, err)
60+
})
61+
62+
t.Run("zero", func(t *testing.T) {
63+
_, err := evaluateOptions(defaultConfig(), WithGRPCPort(0))
64+
require.NoError(t, err)
65+
})
5266
}
5367

5468
func TestLogger_ErrorsWithNilLogger(t *testing.T) {

components/common-go/baseserver/server.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,25 @@ func (s *Server) Logger() *logrus.Entry {
133133
return s.cfg.logger
134134
}
135135

136+
// HTTPAddress returns address of the HTTP Server
137+
// HTTPAddress() is only available once the server has been started.
136138
func (s *Server) HTTPAddress() string {
139+
if s.httpListener == nil {
140+
return ""
141+
}
137142
protocol := "http"
138-
return fmt.Sprintf("%s://%s:%d", protocol, s.cfg.hostname, s.cfg.httpPort)
143+
addr := s.httpListener.Addr().(*net.TCPAddr)
144+
return fmt.Sprintf("%s://%s:%d", protocol, addr.IP, addr.Port)
139145
}
140146

147+
// GRPCAddress returns address of the gRPC Server
148+
// GRPCAddress() is only available once the server has been started.
141149
func (s *Server) GRPCAddress() string {
142-
protocol := "http"
143-
return fmt.Sprintf("%s://%s:%d", protocol, s.cfg.hostname, s.cfg.grpcPort)
150+
if s.grpcListener == nil {
151+
return ""
152+
}
153+
addr := s.grpcListener.Addr().(*net.TCPAddr)
154+
return fmt.Sprintf("%s:%d", addr.IP, addr.Port)
144155
}
145156

146157
func (s *Server) HTTPMux() *http.ServeMux {

components/common-go/baseserver/server_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@ import (
1616

1717
func TestServer_StartStop(t *testing.T) {
1818
// We don't use the helper NewForTests, because we want to control stopping ourselves.
19-
srv, err := baseserver.New("server_test")
19+
srv, err := baseserver.New("server_test", baseserver.WithHTTPPort(8765), baseserver.WithGRPCPort(8766))
2020
require.NoError(t, err)
2121

2222
go func() {
2323
require.NoError(t, srv.ListenAndServe())
2424
}()
2525

2626
baseserver.WaitForServerToBeReachable(t, srv, 3*time.Second)
27+
require.Equal(t, "http://:::8765", srv.HTTPAddress())
28+
require.Equal(t, ":::8766", srv.GRPCAddress())
2729
require.NoError(t, srv.Close())
2830
}
2931

@@ -36,8 +38,8 @@ func TestServer_ServesReady(t *testing.T) {
3638

3739
baseserver.WaitForServerToBeReachable(t, srv, 3*time.Second)
3840

39-
readyUR := fmt.Sprintf("%s/ready", srv.HTTPAddress())
40-
resp, err := http.Get(readyUR)
41+
readyURL := fmt.Sprintf("%s/ready", srv.HTTPAddress())
42+
resp, err := http.Get(readyURL)
4143
require.NoError(t, err)
4244
require.Equal(t, http.StatusOK, resp.StatusCode)
4345
}

components/common-go/baseserver/testing.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ func NewForTests(t *testing.T, opts ...Option) *Server {
1818
t.Helper()
1919

2020
defaultTestOpts := []Option{
21+
WithGRPCPort(0),
22+
WithHTTPPort(0),
2123
WithCloseTimeout(1 * time.Second),
2224
}
2325

@@ -44,13 +46,13 @@ func WaitForServerToBeReachable(t *testing.T, srv *Server, timeout time.Duration
4446
Timeout: tick,
4547
}
4648

47-
healthURL := fmt.Sprintf("%s/ready", srv.HTTPAddress())
48-
4949
for {
5050
select {
5151
case <-ctx.Done():
5252
require.Failf(t, "server did not become reachable in %s", timeout.String())
5353
case <-ticker.C:
54+
// We retrieve the URL on each tick, because the HTTPAddress is only available once the server is listening.
55+
healthURL := fmt.Sprintf("%s/ready", srv.HTTPAddress())
5456
_, err := client.Get(healthURL)
5557
if err != nil {
5658
continue

0 commit comments

Comments
 (0)