From 71f14728527c10d34364af76ff900aae01eeb31d Mon Sep 17 00:00:00 2001 From: Violet Hynes Date: Thu, 9 Nov 2023 09:23:42 -0500 Subject: [PATCH] VAULT-21325 Use free ports for process manager Agent tests (#23943) --- command/agent/exec/exec_test.go | 47 ++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/command/agent/exec/exec_test.go b/command/agent/exec/exec_test.go index feeded4823..a825037faa 100644 --- a/command/agent/exec/exec_test.go +++ b/command/agent/exec/exec_test.go @@ -8,6 +8,7 @@ import ( "encoding/json" "errors" "fmt" + "net" "net/http" "net/http/httptest" "os" @@ -21,7 +22,6 @@ import ( ctconfig "github.com/hashicorp/consul-template/config" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-retryablehttp" - "github.com/hashicorp/vault/command/agent/config" "github.com/hashicorp/vault/sdk/helper/logging" "github.com/hashicorp/vault/sdk/helper/pointerutil" @@ -112,7 +112,6 @@ func TestExecServer_Run(t *testing.T) { // test app parameters testAppArgs []string testAppStopSignal os.Signal - testAppPort int // simulate a shutdown of agent, which, in turn stops the test app simulateShutdown bool @@ -134,7 +133,6 @@ func TestExecServer_Run(t *testing.T) { }}, testAppArgs: []string{"--stop-after", "10s"}, testAppStopSignal: syscall.SIGTERM, - testAppPort: 34001, expected: map[string]string{ "MY_USER": "app-user", "MY_PASSWORD": "s3cr3t", @@ -154,7 +152,6 @@ func TestExecServer_Run(t *testing.T) { staticSecretRenderInterval: 5 * time.Second, testAppArgs: []string{"--stop-after", "15s", "--sleep-after-stop-signal", "0s"}, testAppStopSignal: syscall.SIGTERM, - testAppPort: 34002, expected: map[string]string{ "MY_USER": "app-user", "MY_PASSWORD": "s3cr3t-two", @@ -171,7 +168,6 @@ func TestExecServer_Run(t *testing.T) { }}, testAppArgs: []string{"--stop-after", "1s"}, testAppStopSignal: syscall.SIGTERM, - testAppPort: 34003, expectedTestDuration: 15 * time.Second, expectedError: &ProcessExitError{0}, }, @@ -184,7 +180,6 @@ func TestExecServer_Run(t *testing.T) { }}, testAppArgs: []string{"--stop-after", "1s", "--exit-code", "5"}, testAppStopSignal: syscall.SIGTERM, - testAppPort: 34004, expectedTestDuration: 15 * time.Second, expectedError: &ProcessExitError{5}, }, @@ -197,7 +192,6 @@ func TestExecServer_Run(t *testing.T) { }}, testAppArgs: []string{"--stop-after", "30s", "--sleep-after-stop-signal", "1s"}, testAppStopSignal: syscall.SIGTERM, - testAppPort: 34005, simulateShutdown: true, simulateShutdownWaitDuration: 3 * time.Second, expectedTestDuration: 15 * time.Second, @@ -212,7 +206,6 @@ func TestExecServer_Run(t *testing.T) { }}, testAppArgs: []string{"--stop-after", "30s", "--sleep-after-stop-signal", "1s", "--use-sigusr1"}, testAppStopSignal: syscall.SIGUSR1, - testAppPort: 34006, simulateShutdown: true, simulateShutdownWaitDuration: 3 * time.Second, expectedTestDuration: 15 * time.Second, @@ -228,7 +221,6 @@ func TestExecServer_Run(t *testing.T) { }}, testAppArgs: []string{"--stop-after", "60s", "--sleep-after-stop-signal", "60s"}, testAppStopSignal: syscall.SIGTERM, - testAppPort: 34007, simulateShutdown: true, simulateShutdownWaitDuration: 32 * time.Second, // the test app should be stopped immediately after 30s expectedTestDuration: 45 * time.Second, @@ -251,10 +243,12 @@ func TestExecServer_Run(t *testing.T) { ctx, cancelContextFunc := context.WithTimeout(context.Background(), testCase.expectedTestDuration) defer cancelContextFunc() + port := findOpenPort(t) + testAppCommand := []string{ testAppBinary, "--port", - strconv.Itoa(testCase.testAppPort), + strconv.Itoa(port), } execServer, err := NewServer(&ServerConfig{ @@ -298,7 +292,7 @@ func TestExecServer_Run(t *testing.T) { // ensure the test app is running after 3 seconds var ( - testAppAddr = fmt.Sprintf("http://localhost:%d", testCase.testAppPort) + testAppAddr = fmt.Sprintf("http://localhost:%d", port) testAppStartedCh = make(chan error) ) if testCase.expectedError == nil { @@ -402,7 +396,6 @@ func TestExecServer_LogFiles(t *testing.T) { }) testCases := map[string]struct { - testAppPort int testAppArgs []string stderrFile string stdoutFile string @@ -410,16 +403,13 @@ func TestExecServer_LogFiles(t *testing.T) { expectedError error }{ "can_log_stderr_to_file": { - testAppPort: 34001, - stderrFile: "vault-exec-test.stderr.log", + stderrFile: "vault-exec-test.stderr.log", }, "can_log_stdout_to_file": { - testAppPort: 34002, stdoutFile: "vault-exec-test.stdout.log", testAppArgs: []string{"-log-to-stdout"}, }, "cant_open_file": { - testAppPort: 34003, stderrFile: "/file/does/not/exist", expectedError: os.ErrNotExist, }, @@ -430,10 +420,11 @@ func TestExecServer_LogFiles(t *testing.T) { fakeVault := fakeVaultServer(t) defer fakeVault.Close() + port := findOpenPort(t) testAppCommand := []string{ testAppBinary, "--port", - strconv.Itoa(testCase.testAppPort), + strconv.Itoa(port), "--stop-after", "60s", } @@ -508,7 +499,7 @@ func TestExecServer_LogFiles(t *testing.T) { // ensure the test app is running after 500ms var ( - testAppAddr = fmt.Sprintf("http://localhost:%d", testCase.testAppPort) + testAppAddr = fmt.Sprintf("http://localhost:%d", port) testAppStartedCh = make(chan error) ) time.AfterFunc(500*time.Millisecond, func() { @@ -567,3 +558,23 @@ func TestExecServer_LogFiles(t *testing.T) { }) } } + +// findOpenPort generates a random open port, using Go's :0 to find a port, +// for us to then use as the test binary's port to use. +// This is a little race-y, as something else could open the port before +// we use it, but we're not the process that needs to open the port, +// and we still need to be able to access it. +// We should be fine so long as we don't make the tests parallel. +func findOpenPort(t *testing.T) int { + t.Helper() + ln, err := net.Listen("tcp", ":0") + if err != nil { + t.Fatal(err) + } + port := ln.Addr().(*net.TCPAddr).Port + err = ln.Close() + if err != nil { + t.Fatal(err) + } + return port +}