From c2a6b5b5880356657bde0fe1b029567f04036f76 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Tue, 7 Jan 2025 02:32:15 +0100 Subject: [PATCH 1/2] Wait till a connection to the CA host/port can be made --- test/integration/requestid_test.go | 38 +++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/test/integration/requestid_test.go b/test/integration/requestid_test.go index 54fd2eb07..e89ca5b7a 100644 --- a/test/integration/requestid_test.go +++ b/test/integration/requestid_test.go @@ -50,6 +50,8 @@ func reservePort(t *testing.T) (host, port string) { } func Test_reflectRequestID(t *testing.T) { + ctx := context.Background() + dir := t.TempDir() m, err := minica.New(minica.WithName("Step E2E")) require.NoError(t, err) @@ -133,8 +135,11 @@ func Test_reflectRequestID(t *testing.T) { require.ErrorIs(t, err, http.ErrServerClosed) }() + // require the CA server to be available within 10 seconds, + // failing the test if it doesn't. + requireCAServerToBeAvailable(t, net.JoinHostPort("localhost", port), 10*time.Second) + // require OK health response as the baseline - ctx := context.Background() healthResponse, err := caClient.HealthWithContext(ctx) require.NoError(t, err) if assert.NotNil(t, healthResponse) { @@ -262,8 +267,8 @@ func newAuthorizingServer(t *testing.T, mca *minica.CA) *httptest.Server { srv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if assert.Equal(t, "signRequestID", r.Header.Get("X-Request-Id")) { - json.NewEncoder(w).Encode(struct{ Allow bool }{Allow: true}) - w.WriteHeader(http.StatusOK) + err := json.NewEncoder(w).Encode(struct{ Allow bool }{Allow: true}) + require.NoError(t, err) return } @@ -287,3 +292,30 @@ func newAuthorizingServer(t *testing.T, mca *minica.CA) *httptest.Server { return srv } + +func requireCAServerToBeAvailable(t *testing.T, address string, timeout time.Duration) { + t.Helper() + + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + + for !canConnect(ctx, address) { + select { + case <-ctx.Done(): + require.FailNow(t, fmt.Sprintf("CA server failed to start at https://%s within %s", address, timeout.String())) + case <-time.After(100 * time.Millisecond): + } + } +} + +func canConnect(ctx context.Context, address string) bool { + d := net.Dialer{Timeout: 5 * time.Second} + conn, err := d.DialContext(ctx, "tcp", address) + if err != nil { + return false + } + + conn.Close() + + return true +} From b3fb92756fe66cdd6b19267c4718b8eb59cf9850 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Tue, 7 Jan 2025 11:57:55 +0100 Subject: [PATCH 2/2] Add comment to `requireCAServerToBeAvailable` --- test/integration/requestid_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/integration/requestid_test.go b/test/integration/requestid_test.go index e89ca5b7a..8801dc455 100644 --- a/test/integration/requestid_test.go +++ b/test/integration/requestid_test.go @@ -293,6 +293,9 @@ func newAuthorizingServer(t *testing.T, mca *minica.CA) *httptest.Server { return srv } +// requireCAServerToBeAvailable tries to connect to address to check a server +// is available. It will retry the connection every ~100ms, until timeout occurs. +// If no connection can be made, the test is failed. func requireCAServerToBeAvailable(t *testing.T, address string, timeout time.Duration) { t.Helper() @@ -309,7 +312,7 @@ func requireCAServerToBeAvailable(t *testing.T, address string, timeout time.Dur } func canConnect(ctx context.Context, address string) bool { - d := net.Dialer{Timeout: 5 * time.Second} + d := net.Dialer{} conn, err := d.DialContext(ctx, "tcp", address) if err != nil { return false