diff --git a/.github/workflows/ci-test-go.yml b/.github/workflows/ci-test-go.yml index bb3e6b43cf..fea34e62ee 100644 --- a/.github/workflows/ci-test-go.yml +++ b/.github/workflows/ci-test-go.yml @@ -55,7 +55,7 @@ jobs: steps: - name: Setup rootless Docker if: ${{ inputs.rootless-docker }} - uses: docker/setup-docker-action@b60f85385d03ac8acfca6d9996982511d8620a19 # v4 + uses: docker/setup-docker-action@efe9e3891a4f7307e689f2100b33a155b900a608 # v4.5.0 with: rootless: true diff --git a/modules/solace/solace.go b/modules/solace/solace.go index 8d40c411a7..f756f4dc23 100644 --- a/modules/solace/solace.go +++ b/modules/solace/solace.go @@ -43,13 +43,13 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom // Primary wait strategy for Solace to be ready waitStrategies[0] = wait.ForExec([]string{"grep", "-q", "Primary Virtual Router is now active", "/usr/sw/jail/logs/system.log"}). - WithStartupTimeout(1 * time.Minute). + WithStartupTimeout(2 * time.Minute). WithPollInterval(1 * time.Second) // Add port-based wait strategies for each service for i, service := range settings.services { port := fmt.Sprintf("%d/tcp", service.Port) - waitStrategies[i+1] = wait.ForListeningPort(nat.Port(port)) + waitStrategies[i+1] = wait.ForListeningPort(nat.Port(port)).WithStartupTimeout(30 * time.Second) exposedPorts[i] = fmt.Sprintf("%d/tcp", service.Port) } diff --git a/port_forwarding.go b/port_forwarding.go index 9d4ec10f9a..82ced51ff6 100644 --- a/port_forwarding.go +++ b/port_forwarding.go @@ -160,11 +160,11 @@ func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) ( }, } - // after the container is ready, create the SSH tunnel + // before the container is created, create the SSH tunnel // for each exposed port from the host. sshdConnectHook = ContainerLifecycleHooks{ - PostReadies: []ContainerHook{ - func(ctx context.Context, _ Container) error { + PreCreates: []ContainerRequestHook{ + func(ctx context.Context, req ContainerRequest) error { return sshdContainer.exposeHostPort(ctx, req.HostAccessPorts...) }, }, diff --git a/port_forwarding_test.go b/port_forwarding_test.go index cd101cf0fb..d0ec2e823d 100644 --- a/port_forwarding_test.go +++ b/port_forwarding_test.go @@ -15,6 +15,7 @@ import ( "github.com/testcontainers/testcontainers-go" tcexec "github.com/testcontainers/testcontainers-go/exec" "github.com/testcontainers/testcontainers-go/network" + "github.com/testcontainers/testcontainers-go/wait" ) const ( @@ -22,12 +23,31 @@ const ( ) func TestExposeHostPorts(t *testing.T) { - hostPorts := make([]int, 3) + const numberOfPorts = 3 + + servers := make([]*httptest.Server, numberOfPorts) + hostPorts := make([]int, numberOfPorts) + waitStrategies := make([]wait.Strategy, numberOfPorts) + for i := range hostPorts { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, expectedResponse) })) + + servers[i] = server hostPorts[i] = server.Listener.Addr().(*net.TCPAddr).Port + + waitStrategies[i] = wait. + ForExec([]string{"wget", "-q", "-O", "-", fmt.Sprintf("http://%s:%d", testcontainers.HostInternal, hostPorts[i])}). + WithExitCodeMatcher(func(code int) bool { + return code == 0 + }). + WithResponseMatcher(func(body io.Reader) bool { + bs, err := io.ReadAll(body) + require.NoError(t, err) + return string(bs) == expectedResponse + }) + t.Cleanup(server.Close) }