diff --git a/integration/dsic/dsic.go b/integration/dsic/dsic.go index 755d2298..d8a77575 100644 --- a/integration/dsic/dsic.go +++ b/integration/dsic/dsic.go @@ -147,7 +147,18 @@ func New( return nil, err } - hostname := fmt.Sprintf("derp-%s-%s", strings.ReplaceAll(version, ".", "-"), hash) + // Include run ID in hostname for easier identification of which test run owns this container + runID := dockertestutil.GetIntegrationRunID() + + var hostname string + + if runID != "" { + // Use last 6 chars of run ID (the random hash part) for brevity + runIDShort := runID[len(runID)-6:] + hostname = fmt.Sprintf("derp-%s-%s-%s", runIDShort, strings.ReplaceAll(version, ".", "-"), hash) + } else { + hostname = fmt.Sprintf("derp-%s-%s", strings.ReplaceAll(version, ".", "-"), hash) + } tlsCert, tlsKey, err := integrationutil.CreateCertificate(hostname) if err != nil { return nil, fmt.Errorf("failed to create certificates for headscale test: %w", err) diff --git a/integration/hsic/hsic.go b/integration/hsic/hsic.go index 2754b317..9e8e5656 100644 --- a/integration/hsic/hsic.go +++ b/integration/hsic/hsic.go @@ -74,6 +74,7 @@ type HeadscaleInContainer struct { // optional config port int extraPorts []string + hostMetricsPort string // Dynamically assigned host port for metrics/pprof access caCerts [][]byte hostPortBindings map[string][]string aclPolicy *policyv2.Policy @@ -330,7 +331,18 @@ func New( return nil, err } - hostname := "hs-" + hash + // Include run ID in hostname for easier identification of which test run owns this container + runID := dockertestutil.GetIntegrationRunID() + + var hostname string + + if runID != "" { + // Use last 6 chars of run ID (the random hash part) for brevity + runIDShort := runID[len(runID)-6:] + hostname = fmt.Sprintf("hs-%s-%s", runIDShort, hash) + } else { + hostname = "hs-" + hash + } hsic := &HeadscaleInContainer{ hostname: hostname, @@ -438,13 +450,13 @@ func New( Env: env, } - // Bind metrics port to predictable host port + // Bind metrics port to dynamic host port (kernel assigns free port) if runOptions.PortBindings == nil { runOptions.PortBindings = map[docker.Port][]docker.PortBinding{} } runOptions.PortBindings["9090/tcp"] = []docker.PortBinding{ - {HostPort: "49090"}, + {HostPort: "0"}, // Let kernel assign a free port } if len(hsic.hostPortBindings) > 0 { @@ -540,9 +552,14 @@ func New( hsic.container = container + // Get the dynamically assigned host port for metrics/pprof + hsic.hostMetricsPort = container.GetHostPort("9090/tcp") + log.Printf( - "Ports for %s: metrics/pprof=49090\n", + "Headscale %s metrics available at http://localhost:%s/metrics (debug at http://localhost:%s/debug/)\n", hsic.hostname, + hsic.hostMetricsPort, + hsic.hostMetricsPort, ) // Write the CA certificates to the container @@ -932,6 +949,13 @@ func (t *HeadscaleInContainer) GetPort() string { return strconv.Itoa(t.port) } +// GetHostMetricsPort returns the dynamically assigned host port for metrics/pprof access. +// This port can be used by operators to access metrics at http://localhost:{port}/metrics +// and debug endpoints at http://localhost:{port}/debug/ while tests are running. +func (t *HeadscaleInContainer) GetHostMetricsPort() string { + return t.hostMetricsPort +} + // GetHealthEndpoint returns a health endpoint for the HeadscaleInContainer // instance. func (t *HeadscaleInContainer) GetHealthEndpoint() string { diff --git a/integration/scenario.go b/integration/scenario.go index 041cc771..cc3cf968 100644 --- a/integration/scenario.go +++ b/integration/scenario.go @@ -247,9 +247,14 @@ func (s *Scenario) AddNetwork(name string) (*dockertest.Network, error) { // We run the test suite in a docker container that calls a couple of endpoints for // readiness checks, this ensures that we can run the tests with individual networks - // and have the client reach the different containers - // TODO(kradalby): Can the test-suite be renamed so we can have multiple? - err = dockertestutil.AddContainerToNetwork(s.pool, network, "headscale-test-suite") + // and have the client reach the different containers. + // The container name includes the run ID to support multiple concurrent test runs. + testSuiteName := "headscale-test-suite" + if runID := dockertestutil.GetIntegrationRunID(); runID != "" { + testSuiteName = "headscale-test-suite-" + runID + } + + err = dockertestutil.AddContainerToNetwork(s.pool, network, testSuiteName) if err != nil { return nil, fmt.Errorf("failed to add test suite container to network: %w", err) } diff --git a/integration/tsic/tsic.go b/integration/tsic/tsic.go index 790a1638..fb07896b 100644 --- a/integration/tsic/tsic.go +++ b/integration/tsic/tsic.go @@ -307,7 +307,18 @@ func New( return nil, err } - hostname := fmt.Sprintf("ts-%s-%s", strings.ReplaceAll(version, ".", "-"), hash) + // Include run ID in hostname for easier identification of which test run owns this container + runID := dockertestutil.GetIntegrationRunID() + + var hostname string + + if runID != "" { + // Use last 6 chars of run ID (the random hash part) for brevity + runIDShort := runID[len(runID)-6:] + hostname = fmt.Sprintf("ts-%s-%s-%s", runIDShort, strings.ReplaceAll(version, ".", "-"), hash) + } else { + hostname = fmt.Sprintf("ts-%s-%s", strings.ReplaceAll(version, ".", "-"), hash) + } tsic := &TailscaleInContainer{ version: version,