From a23a8fad9afa1db2e5339f6eaf90e89f727bb357 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Sat, 11 Jul 2026 19:02:14 +0100 Subject: [PATCH] Addresses #1558 --- internal/api/router.go | 3 + .../api/router_set_monitor_agents_test.go | 58 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 internal/api/router_set_monitor_agents_test.go diff --git a/internal/api/router.go b/internal/api/router.go index 274bb038b..bfaa3bc97 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -1361,6 +1361,9 @@ func (r *Router) SetMonitor(m *monitoring.Monitor) { if r.unifiedAgentHandlers != nil { r.unifiedAgentHandlers.SetMonitor(m) } + if r.kubernetesAgentHandlers != nil { + r.kubernetesAgentHandlers.SetMonitor(m) + } if r.systemSettingsHandler != nil { r.systemSettingsHandler.SetMonitor(m) } diff --git a/internal/api/router_set_monitor_agents_test.go b/internal/api/router_set_monitor_agents_test.go new file mode 100644 index 000000000..b196c52b9 --- /dev/null +++ b/internal/api/router_set_monitor_agents_test.go @@ -0,0 +1,58 @@ +package api + +import ( + "context" + "testing" + + "github.com/rcourtman/pulse-go-rewrite/internal/config" + "github.com/rcourtman/pulse-go-rewrite/internal/monitoring" +) + +// TestRouterSetMonitor_UpdatesAgentHandlers verifies the fix for issue #1558: +// Router.SetMonitor must repoint the kubernetes agent handlers at the new +// monitor, exactly as it does for the docker agent handlers. Without this, +// kubernetes agent reports resolved through the single-tenant fallback keep +// landing in the orphaned pre-reload monitor after a config reload, so the +// cluster flaps in the UI. +func TestRouterSetMonitor_UpdatesAgentHandlers(t *testing.T) { + tempDir := t.TempDir() + cfg := &config.Config{ + DataPath: tempDir, + ConfigPath: tempDir, + } + + monitor1, err := monitoring.New(cfg) + if err != nil { + t.Fatalf("monitoring.New (initial): %v", err) + } + t.Cleanup(func() { monitor1.Stop() }) + + monitor2, err := monitoring.New(cfg) + if err != nil { + t.Fatalf("monitoring.New (reload): %v", err) + } + t.Cleanup(func() { monitor2.Stop() }) + + // No multi-tenant monitor: getMonitor resolves via the defaultMonitor + // fallback, which is exactly the field SetMonitor must refresh. + kubernetesHandlers := NewKubernetesAgentHandlers(nil, monitor1, nil) + dockerHandlers := NewDockerAgentHandlers(nil, monitor1, nil, cfg) + + // Minimal router, as in TestReloadSystemSettings_AppliesWebhookCIDRsToNewMonitor: + // SetMonitor only touches the handlers that are non-nil. + router := &Router{ + config: cfg, + kubernetesAgentHandlers: kubernetesHandlers, + dockerAgentHandlers: dockerHandlers, + } + + router.SetMonitor(monitor2) + + ctx := context.Background() + if got := kubernetesHandlers.getMonitor(ctx); got != monitor2 { + t.Fatal("kubernetes agent handlers still resolve the pre-reload monitor after Router.SetMonitor") + } + if got := dockerHandlers.getMonitor(ctx); got != monitor2 { + t.Fatal("docker agent handlers still resolve the pre-reload monitor after Router.SetMonitor") + } +}