diff options
| author | Kristoffer Dalby <kristoffer@tailscale.com> | 2026-03-12 11:15:04 +0000 |
|---|---|---|
| committer | Kristoffer Dalby <kristoffer@tailscale.com> | 2026-03-12 11:15:04 +0000 |
| commit | 9c5607138a850cd2eeac099aa22ae71c15699c38 (patch) | |
| tree | 77870ccd86c7423e11de3f2e854e44dc46426f7c /control/controlclient/direct_test.go | |
| parent | 6fd492b7c814adb9e746ababfd56277f2cc40b30 (diff) | |
| download | tailscale-kradalby/disable-logtail-per-instance.tar.xz tailscale-kradalby/disable-logtail-per-instance.zip | |
logtail,control/controlclient,ipn/ipnlocal: add tests for per-instance DisableLogTailkradalby/disable-logtail-per-instance
Add test coverage for the per-instance DisableLogTail feature:
- TestEnableDisableRoundTrip: verify logtail.Enable/Disable toggle
the global atomic bool correctly through multiple round-trips.
- TestHandleDebugMessageDisableLogTail: verify handleDebugMessage
fires the OnDisableLogTail callback, does NOT call
envknob.SetNoLogsNoSupport, handles nil callback without panic,
and does not fire the callback when DisableLogTail is false.
- TestNoLogsNoSupportCombinesSources: verify LocalBackend.NoLogsNoSupport
returns true when either the envknob or noLogsFromControl is set.
- TestFlowLogsConflictCheck: verify that when logging is disabled
and a netmap with CapabilityDataPlaneAuditLogs arrives,
WantRunning is set to false with the correct error message
(different for control-disabled vs user-disabled).
- TestStartLockedClearsControlDisableLogTail: verify that Start
clears noLogsFromControl and re-enables logtail.
- TestProfileSwitchHeadscaleToTailscale: verify the full lifecycle
of switching from a control server that disabled logging to one
that requires flow logs.
- TestGlobalNoLogsPreventReEnable: verify that when the global
envknob is set, Start does NOT re-enable logtail, and the
conflict check fires with the user-explicit error message.
Diffstat (limited to 'control/controlclient/direct_test.go')
| -rw-r--r-- | control/controlclient/direct_test.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/control/controlclient/direct_test.go b/control/controlclient/direct_test.go index d10b346ae..90500e9cf 100644 --- a/control/controlclient/direct_test.go +++ b/control/controlclient/direct_test.go @@ -4,15 +4,19 @@ package controlclient import ( + "context" "encoding/json" "net/http" "net/http/httptest" "net/netip" + "sync/atomic" "testing" "time" + "tailscale.com/envknob" "tailscale.com/hostinfo" "tailscale.com/ipn/ipnstate" + "tailscale.com/logtail" "tailscale.com/net/netmon" "tailscale.com/net/tsdial" "tailscale.com/tailcfg" @@ -181,3 +185,81 @@ func TestTsmpPing(t *testing.T) { t.Fatal(err) } } + +func TestHandleDebugMessageDisableLogTail(t *testing.T) { + // This test mutates package-level logtail state and must not run in + // parallel with tests that depend on logtail being enabled. + t.Cleanup(func() { logtail.Enable() }) + + t.Run("callback_fires", func(t *testing.T) { + logtail.Enable() // reset from any prior subtest + + var called atomic.Bool + c := &Direct{ + logf: t.Logf, + onDisableLogTail: func() { called.Store(true) }, + } + + err := c.handleDebugMessage(context.Background(), &tailcfg.Debug{DisableLogTail: true}) + if err != nil { + t.Fatalf("handleDebugMessage: %v", err) + } + + if !called.Load() { + t.Error("onDisableLogTail callback was not called") + } + }) + + t.Run("envknob_not_set", func(t *testing.T) { + logtail.Enable() // reset + t.Setenv("TS_NO_LOGS_NO_SUPPORT", "") + + c := &Direct{ + logf: t.Logf, + onDisableLogTail: func() {}, + } + + err := c.handleDebugMessage(context.Background(), &tailcfg.Debug{DisableLogTail: true}) + if err != nil { + t.Fatalf("handleDebugMessage: %v", err) + } + + if envknob.NoLogsNoSupport() { + t.Error("envknob.NoLogsNoSupport() should be false; handleDebugMessage must not call envknob.SetNoLogsNoSupport()") + } + }) + + t.Run("nil_callback_no_panic", func(t *testing.T) { + logtail.Enable() // reset + + c := &Direct{ + logf: t.Logf, + onDisableLogTail: nil, + } + + err := c.handleDebugMessage(context.Background(), &tailcfg.Debug{DisableLogTail: true}) + if err != nil { + t.Fatalf("handleDebugMessage: %v", err) + } + // No panic means success. + }) + + t.Run("false_does_not_fire", func(t *testing.T) { + logtail.Enable() // reset + + var called atomic.Bool + c := &Direct{ + logf: t.Logf, + onDisableLogTail: func() { called.Store(true) }, + } + + err := c.handleDebugMessage(context.Background(), &tailcfg.Debug{DisableLogTail: false}) + if err != nil { + t.Fatalf("handleDebugMessage: %v", err) + } + + if called.Load() { + t.Error("onDisableLogTail should not be called when DisableLogTail is false") + } + }) +} |
