mirror of
https://github.com/juanfont/headscale.git
synced 2026-01-11 11:50:30 +01:00
integration: add run ID isolation for concurrent test execution
Add run ID-based isolation to container naming and network setup to
enable multiple integration tests to run concurrently on the same
Docker daemon without conflicts.
Changes:
- hsic: Add run ID prefix to headscale container names and use dynamic
port allocation for metrics endpoint (port 0 lets kernel assign)
- tsic: Add run ID prefix to tailscale container names
- dsic: Add run ID prefix to DERP container names
- scenario: Use run ID-aware test suite container name for network setup
Container naming now follows: {type}-{runIDShort}-{identifier}-{hash}
Example: ts-mdjtzx-1-74-fgdyls, hs-mdjtzx-pingallbyip-abc123
The run ID is obtained from HEADSCALE_INTEGRATION_RUN_ID environment
variable via dockertestutil.GetIntegrationRunID().
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user