Skip to content

Commit 153b949

Browse files
committed
feat(dsl): have dsl pass port for mock server instead of mock server
In order to be friendly with Docker and Jenkins pipelines by exposing specified ports the Pact struct will have an optional field for mock service ports. The default action is to use the exact same function to find a free port. But if the field `AllowedMockServicePorts` is passed then it will limit the ports to those specified Breaking Changes: - Changed signature of `daemon.NewService()`. It no longer returns a port as it is now determined before `daemon.NewService()` is called. - Changed signature of `client.StartServer()` to accept port. Previously it got the port from the return of `daemon.NewService()` but the DSL desides the port now
1 parent e5ab27b commit 153b949

13 files changed

+302
-43
lines changed

daemon/daemon.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,7 @@ func (d Daemon) Shutdown() {
9999
func (d Daemon) StartServer(request types.MockServer, reply *types.MockServer) error {
100100
log.Println("[DEBUG] daemon - starting mock server with args:", request.Args)
101101
server := &types.MockServer{}
102-
port, svc := d.pactMockSvcManager.NewService(request.Args)
103-
server.Port = port
102+
svc := d.pactMockSvcManager.NewService(request.Args)
104103
server.Status = -1
105104
cmd := svc.Start()
106105
server.Pid = cmd.Process.Pid
@@ -124,7 +123,7 @@ func (d Daemon) VerifyProvider(request types.VerifyRequest, reply *types.Command
124123
}
125124

126125
var out bytes.Buffer
127-
_, svc := d.verificationSvcManager.NewService(request.Args)
126+
svc := d.verificationSvcManager.NewService(request.Args)
128127
cmd, err := svc.Run(&out)
129128

130129
if err == nil && cmd.ProcessState != nil && cmd.ProcessState.Success() {

daemon/mock_service.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ package daemon
22

33
import (
44
"fmt"
5-
"log"
65
"path/filepath"
76

87
"github.com/kardianos/osext"
9-
"github.com/pact-foundation/pact-go/utils"
108
)
119

1210
// MockService is a wrapper for the Pact Mock Service.
@@ -15,19 +13,14 @@ type MockService struct {
1513
}
1614

1715
// NewService creates a new MockService with default settings.
18-
func (m *MockService) NewService(args []string) (int, Service) {
19-
port, _ := utils.GetFreePort()
20-
log.Println("[DEBUG] starting mock service on port:", port)
21-
16+
func (m *MockService) NewService(args []string) Service {
2217
m.Args = []string{
2318
"service",
24-
"--port",
25-
fmt.Sprintf("%d", port),
2619
}
2720
m.Args = append(m.Args, args...)
2821

2922
m.Command = getMockServiceCommandPath()
30-
return port, m
23+
return m
3124
}
3225

3326
func getMockServiceCommandPath() string {

daemon/mock_service_test.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,13 @@ import "testing"
44

55
func TestMockService_NewService(t *testing.T) {
66
s := &MockService{}
7-
port, svc := s.NewService([]string{"--foo"})
8-
9-
if port <= 0 {
10-
t.Fatalf("Expected non-zero port but got: %d", port)
11-
}
7+
svc := s.NewService([]string{"--foo"})
128

139
if svc == nil {
1410
t.Fatalf("Expected a non-nil object but got nil")
1511
}
1612

17-
if s.Args[3] != "--foo" {
13+
if s.Args[1] != "--foo" {
1814
t.Fatalf("Expected '--foo' argument to be passed")
1915
}
2016
}

daemon/service.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ type Service interface {
1313
List() map[int]*exec.Cmd
1414
Start() *exec.Cmd
1515
Run(io.Writer) (*exec.Cmd, error)
16-
NewService(args []string) (int, Service)
16+
NewService(args []string) Service
1717
}

daemon/service_mock.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,6 @@ func (s *ServiceMock) Start() *exec.Cmd {
6666
}
6767

6868
// NewService creates a new MockService with default settings.
69-
func (s *ServiceMock) NewService(args []string) (int, Service) {
70-
return s.ServicePort, s
69+
func (s *ServiceMock) NewService(args []string) Service {
70+
return s
7171
}

daemon/verification_service.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ type VerificationService struct {
2424
// --broker-password
2525
// --publish_verification_results
2626
// --provider_app_version
27-
func (m *VerificationService) NewService(args []string) (int, Service) {
27+
func (m *VerificationService) NewService(args []string) Service {
2828
log.Printf("[DEBUG] starting verification service with args: %v\n", args)
2929

3030
m.Args = args
3131
m.Command = getVerifierCommandPath()
32-
return -1, m
32+
return m
3333
}
3434

3535
func getVerifierCommandPath() string {

daemon/verification_service_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@ import "testing"
44

55
func TestVerificationService_NewService(t *testing.T) {
66
s := &VerificationService{}
7-
port, svc := s.NewService([]string{"--foo bar"})
8-
9-
if port != -1 {
10-
t.Fatalf("Expected port to be -1 but got: %d", port)
11-
}
7+
svc := s.NewService([]string{"--foo bar"})
128

139
if svc == nil {
1410
t.Fatalf("Expected a non-nil object but got nil")

dsl/client.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,20 +90,22 @@ var waitForPort = func(port int, network string, address string, message string)
9090
}
9191

9292
// StartServer starts a remote Pact Mock Server.
93-
func (p *PactClient) StartServer(args []string) *types.MockServer {
93+
func (p *PactClient) StartServer(args []string, port int) *types.MockServer {
9494
log.Println("[DEBUG] client: starting a server")
9595
var res types.MockServer
9696
client, err := getHTTPClient(p.Port, p.getNetworkInterface(), p.Address)
9797
if err == nil {
98+
args = append(args, []string{"--port", strconv.Itoa(port)}...)
9899
err = client.Call(commandStartServer, types.MockServer{Args: args}, &res)
100+
res.Port = port
99101
if err != nil {
100102
log.Println("[ERROR] rpc:", err.Error())
101103
}
102104
}
103105

104106
if err == nil {
105-
waitForPort(res.Port, p.getNetworkInterface(), p.Address, fmt.Sprintf(`Timed out waiting for Mock Server to
106-
start on port %d - are you sure it's running?`, res.Port))
107+
waitForPort(port, p.getNetworkInterface(), p.Address, fmt.Sprintf(`Timed out waiting for Mock Server to
108+
start on port %d - are you sure it's running?`, port))
107109
}
108110

109111
return &res

dsl/client_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func TestClient_List(t *testing.T) {
130130
func TestClient_ListFail(t *testing.T) {
131131
timeoutDuration = 50 * time.Millisecond
132132
client := &PactClient{ /* don't supply port */ }
133-
client.StartServer([]string{})
133+
client.StartServer([]string{}, 0)
134134
list := client.ListServers()
135135

136136
if len(list.Servers) != 0 {
@@ -146,7 +146,8 @@ func TestClient_StartServer(t *testing.T) {
146146
defer waitForDaemonToShutdown(port, t)
147147
client := &PactClient{Port: port}
148148

149-
client.StartServer([]string{})
149+
mport, _ := utils.GetFreePort()
150+
client.StartServer([]string{}, mport)
150151
if svc.ServiceStartCount != 1 {
151152
t.Fatalf("Expected 1 server to have been started, got %d", svc.ServiceStartCount)
152153
}
@@ -189,7 +190,7 @@ func TestClient_RPCErrors(t *testing.T) {
189190
return client.StopServer(&types.MockServer{})
190191
},
191192
&types.MockServer{}: func() interface{} {
192-
return client.StartServer([]string{})
193+
return client.StartServer([]string{}, 0)
193194
},
194195
&types.PactListResponse{}: func() interface{} {
195196
return client.ListServers()
@@ -297,7 +298,7 @@ func TestClient_StartServerFail(t *testing.T) {
297298
timeoutDuration = 50 * time.Millisecond
298299

299300
client := &PactClient{ /* don't supply port */ }
300-
server := client.StartServer([]string{})
301+
server := client.StartServer([]string{}, 0)
301302
if server.Port != 0 {
302303
t.Fatalf("Expected server to be empty %v", server)
303304
}

dsl/pact.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/hashicorp/logutils"
1414
"github.com/pact-foundation/pact-go/types"
15+
"github.com/pact-foundation/pact-go/utils"
1516
)
1617

1718
// Pact is the container structure to run the Consumer Pact test cases.
@@ -69,6 +70,10 @@ type Pact struct {
6970
// Examples include 'tcp', 'tcp4', 'tcp6'
7071
// Defaults to 'tcp'
7172
Network string
73+
74+
// Ports MockServer can be deployed to, can be CSV or Range with a dash
75+
// Example "1234", "12324,5667", "1234-5667"
76+
AllowedMockServerPorts string
7277
}
7378

7479
// AddInteraction creates a new Pact interaction, initialising all
@@ -114,6 +119,19 @@ func (p *Pact) Setup(startMockServer bool) *Pact {
114119
p.pactClient = client
115120
}
116121

122+
// Need to predefine due to scoping
123+
var port int
124+
var perr error
125+
if p.AllowedMockServerPorts != "" {
126+
port, perr = utils.FindPortInRange(p.AllowedMockServerPorts)
127+
} else {
128+
port, perr = utils.GetFreePort()
129+
}
130+
if perr != nil {
131+
log.Println("[ERROR] unable to find free port, mockserver will fail to start")
132+
}
133+
log.Println("[DEBUG] starting mock service on port:", port)
134+
117135
if p.Server == nil && startMockServer {
118136
args := []string{
119137
"--pact-specification-version",
@@ -128,7 +146,7 @@ func (p *Pact) Setup(startMockServer bool) *Pact {
128146
p.Provider,
129147
}
130148

131-
p.Server = p.pactClient.StartServer(args)
149+
p.Server = p.pactClient.StartServer(args, port)
132150
}
133151

134152
return p

0 commit comments

Comments
 (0)