From 84fe3de251eb05302832b038740e08efebd09163 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 27 Oct 2025 12:08:52 +0100 Subject: [PATCH] integration: reduce TestAutoApproveMultiNetwork matrix to 3 tests (#2815) --- integration/hsic/hsic.go | 32 +++++++++++++++++--------------- integration/route_test.go | 21 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/integration/hsic/hsic.go b/integration/hsic/hsic.go index 88fc4da2..775e7937 100644 --- a/integration/hsic/hsic.go +++ b/integration/hsic/hsic.go @@ -1232,26 +1232,26 @@ func (h *HeadscaleInContainer) writePolicy(pol *policyv2.Policy) error { } func (h *HeadscaleInContainer) PID() (int, error) { - cmd := []string{"bash", "-c", `ps aux | grep headscale | grep -v grep | awk '{print $2}'`} - output, err := h.Execute(cmd) + // Use pidof to find the headscale process, which is more reliable than grep + // as it only looks for the actual binary name, not processes that contain + // "headscale" in their command line (like the dlv debugger). + output, err := h.Execute([]string{"pidof", "headscale"}) if err != nil { - return 0, fmt.Errorf("failed to execute command: %w", err) + // pidof returns exit code 1 when no process is found + return 0, os.ErrNotExist } - lines := strings.TrimSpace(output) - if lines == "" { - return 0, os.ErrNotExist // No output means no process found + // pidof returns space-separated PIDs on a single line + pidStrs := strings.Fields(strings.TrimSpace(output)) + if len(pidStrs) == 0 { + return 0, os.ErrNotExist } - pids := make([]int, 0, len(lines)) - for _, line := range strings.Split(lines, "\n") { - line = strings.TrimSpace(line) - if line == "" { - continue - } - pidInt, err := strconv.Atoi(line) + pids := make([]int, 0, len(pidStrs)) + for _, pidStr := range pidStrs { + pidInt, err := strconv.Atoi(pidStr) if err != nil { - return 0, fmt.Errorf("parsing PID: %w", err) + return 0, fmt.Errorf("parsing PID %q: %w", pidStr, err) } // We dont care about the root pid for the container if pidInt == 1 { @@ -1266,7 +1266,9 @@ func (h *HeadscaleInContainer) PID() (int, error) { case 1: return pids[0], nil default: - return 0, errors.New("multiple headscale processes running") + // If we still have multiple PIDs, return the first one as a fallback + // This can happen in edge cases during startup/shutdown + return pids[0], nil } } diff --git a/integration/route_test.go b/integration/route_test.go index 15b66d6b..867aa9b7 100644 --- a/integration/route_test.go +++ b/integration/route_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" xmaps "golang.org/x/exp/maps" + "tailscale.com/envknob" "tailscale.com/ipn/ipnstate" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" @@ -2215,11 +2216,31 @@ func TestAutoApproveMultiNetwork(t *testing.T) { }, } + // Check if we should run the full matrix of tests + // By default, we only run a minimal subset to avoid overwhelming Docker/disk + // Set HEADSCALE_INTEGRATION_FULL_MATRIX=1 to run all combinations + fullMatrix := envknob.Bool("HEADSCALE_INTEGRATION_FULL_MATRIX") + + // Minimal test set: 3 tests covering all key dimensions + // - Both auth methods (authkey, webauth) + // - All 3 approver types (tag, user, group) + // - Both policy modes (database, file) + // - Both advertiseDuringUp values (true, false) + minimalTestSet := map[string]bool{ + "authkey-tag-advertiseduringup-false-pol-database": true, // authkey + database + tag + false + "webauth-user-advertiseduringup-true-pol-file": true, // webauth + file + user + true + "authkey-group-advertiseduringup-false-pol-file": true, // authkey + file + group + false + } + for _, tt := range tests { for _, polMode := range []types.PolicyMode{types.PolicyModeDB, types.PolicyModeFile} { for _, advertiseDuringUp := range []bool{false, true} { name := fmt.Sprintf("%s-advertiseduringup-%t-pol-%s", tt.name, advertiseDuringUp, polMode) t.Run(name, func(t *testing.T) { + // Skip tests not in minimal set unless full matrix is enabled + if !fullMatrix && !minimalTestSet[name] { + t.Skip("Skipping to reduce test matrix size. Set HEADSCALE_INTEGRATION_FULL_MATRIX=1 to run all tests.") + } scenario, err := NewScenario(tt.spec) require.NoErrorf(t, err, "failed to create scenario: %s", err) defer scenario.ShutdownAssertNoPanics(t)