From 2bbed95c2a9a24fa51e8a87758d9ccabec44c96b Mon Sep 17 00:00:00 2001 From: Naeel Date: Sun, 26 Apr 2026 10:54:24 +0300 Subject: [PATCH] layer1: prepare managed namespace watchers --- .../2026-04-26-namespace-manager-step44.md | 20 +++++++++++++++++++ pkg/buildermgr/ns_watcher.go | 4 ++-- pkg/executor/multitenant/ns_watcher.go | 4 ++-- pkg/router/ns_watcher.go | 4 ++-- pkg/utils/namespace_manager.go | 6 ++++++ pkg/utils/namespace_manager_test.go | 19 ++++++++++++++++++ 6 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 doc/thinking/2026-04-26-namespace-manager-step44.md diff --git a/doc/thinking/2026-04-26-namespace-manager-step44.md b/doc/thinking/2026-04-26-namespace-manager-step44.md new file mode 100644 index 00000000..d16602e7 --- /dev/null +++ b/doc/thinking/2026-04-26-namespace-manager-step44.md @@ -0,0 +1,20 @@ +# 2026-04-26 — NamespaceManager rewrite, step 44 + +## Цель шага + +Убрать последний дублирующийся orchestration-код из `StartNSWatcher()` в трёх компонентах. + +## Что меняем + +1. В `utils` добавляем `PrepareManagedNamespaceWatcher()`. +2. Helper: + - создаёт `NamespaceManager`; + - делает bootstrap+dispatch; + - собирает общие event handlers. +3. `buildermgr`, `router`, `executor/multitenant` используют этот helper. + +## Что НЕ меняем + +- не меняем subscriber logic; +- не меняем managed namespace watcher startup helper; +- не меняем removal strategy по умолчанию. \ No newline at end of file diff --git a/pkg/buildermgr/ns_watcher.go b/pkg/buildermgr/ns_watcher.go index 844ae9bc..94f2d7fa 100644 --- a/pkg/buildermgr/ns_watcher.go +++ b/pkg/buildermgr/ns_watcher.go @@ -26,9 +26,9 @@ func StartNSWatcher( pkgw *packageWatcher, mgr manager.Interface, ) { - nsManager, err := utils.NewWatcherNamespaceManager(ctx, utils.DefaultNSResolver().Snapshot(), utils.NamespaceSourceEnv, time.Now().UTC(), NewNamespaceSubscriber(envw, pkgw, mgr)) + _, handlers, err := utils.PrepareManagedNamespaceWatcher(ctx, logger, "buildermgr.NSWatcher", utils.DefaultNSResolver().Snapshot(), utils.NamespaceRemovalStrategyTrackOnly, NewNamespaceSubscriber(envw, pkgw, mgr)) if err != nil { logger.Error("buildermgr.NSWatcher: BootstrapAndDispatch failed", zap.Error(err)) } - utils.StartManagedNamespaceWatcher(ctx, logger, "buildermgr.NSWatcher", kubeClient, mgr, utils.NewNamespaceWatcherEventHandlers(ctx, logger, "buildermgr.NSWatcher", nsManager, utils.NamespaceRemovalStrategyTrackOnly)) + utils.StartManagedNamespaceWatcher(ctx, logger, "buildermgr.NSWatcher", kubeClient, mgr, handlers) } diff --git a/pkg/executor/multitenant/ns_watcher.go b/pkg/executor/multitenant/ns_watcher.go index 79c1539a..d5dc0d41 100644 --- a/pkg/executor/multitenant/ns_watcher.go +++ b/pkg/executor/multitenant/ns_watcher.go @@ -88,11 +88,11 @@ func StartNSWatcher( executorTypes map[fv1.ExecutorType]executortype.ExecutorType, mgr manager.Interface, ) { - nsManager, err := utils.NewWatcherNamespaceManager(ctx, utils.DefaultNSResolver().Snapshot(), utils.NamespaceSourceEnv, time.Now().UTC(), NewNamespaceSubscriber(logger, kubernetesClient, executorTypes, mgr)) + _, handlers, err := utils.PrepareManagedNamespaceWatcher(ctx, logger, "multitenant.NSWatcher", utils.DefaultNSResolver().Snapshot(), utils.NamespaceRemovalStrategyTrackOnly, NewNamespaceSubscriber(logger, kubernetesClient, executorTypes, mgr)) if err != nil { logger.Error("multitenant.NSWatcher: BootstrapAndDispatch failed", zap.Error(err)) } - utils.StartManagedNamespaceWatcher(ctx, logger, "multitenant.NSWatcher", kubernetesClient, mgr, utils.NewNamespaceWatcherEventHandlers(ctx, logger, "multitenant.NSWatcher", nsManager, utils.NamespaceRemovalStrategyTrackOnly)) + utils.StartManagedNamespaceWatcher(ctx, logger, "multitenant.NSWatcher", kubernetesClient, mgr, handlers) } // registerNamespace calls AddNamespace on every executor type for the given namespace. diff --git a/pkg/router/ns_watcher.go b/pkg/router/ns_watcher.go index 35f903fc..8162cddb 100644 --- a/pkg/router/ns_watcher.go +++ b/pkg/router/ns_watcher.go @@ -26,9 +26,9 @@ func StartNSWatcher( ts *HTTPTriggerSet, mgr manager.Interface, ) { - nsManager, err := utils.NewWatcherNamespaceManager(ctx, utils.DefaultNSResolver().Snapshot(), utils.NamespaceSourceEnv, time.Now().UTC(), NewNamespaceSubscriber(ts, mgr)) + _, handlers, err := utils.PrepareManagedNamespaceWatcher(ctx, logger, "router.NSWatcher", utils.DefaultNSResolver().Snapshot(), utils.NamespaceRemovalStrategyTrackOnly, NewNamespaceSubscriber(ts, mgr)) if err != nil { logger.Error("router.NSWatcher: BootstrapAndDispatch failed", zap.Error(err)) } - utils.StartManagedNamespaceWatcher(ctx, logger, "router.NSWatcher", kubeClient, mgr, utils.NewNamespaceWatcherEventHandlers(ctx, logger, "router.NSWatcher", nsManager, utils.NamespaceRemovalStrategyTrackOnly)) + utils.StartManagedNamespaceWatcher(ctx, logger, "router.NSWatcher", kubeClient, mgr, handlers) } diff --git a/pkg/utils/namespace_manager.go b/pkg/utils/namespace_manager.go index 36a49c90..5188bcca 100644 --- a/pkg/utils/namespace_manager.go +++ b/pkg/utils/namespace_manager.go @@ -109,6 +109,12 @@ func NewWatcherNamespaceManager(ctx context.Context, namespaces []string, source return manager, err } +func PrepareManagedNamespaceWatcher(ctx context.Context, logger *zap.Logger, component string, namespaces []string, removalStrategy NamespaceRemovalStrategy, subscriber NamespaceSubscriber) (NamespaceManager, k8sCache.ResourceEventHandlerFuncs, error) { + manager, err := NewWatcherNamespaceManager(ctx, namespaces, NamespaceSourceEnv, time.Now().UTC(), subscriber) + handlers := NewNamespaceWatcherEventHandlers(ctx, logger, component, manager, removalStrategy) + return manager, handlers, err +} + func NamespaceBecameUnmanaged(oldNamespace *corev1.Namespace, newNamespace *corev1.Namespace) bool { if oldNamespace == nil || newNamespace == nil { return false diff --git a/pkg/utils/namespace_manager_test.go b/pkg/utils/namespace_manager_test.go index d9207f9a..f90149e8 100644 --- a/pkg/utils/namespace_manager_test.go +++ b/pkg/utils/namespace_manager_test.go @@ -429,6 +429,25 @@ func TestNewNamespaceWatcherEventHandlers(t *testing.T) { } } +func TestPrepareManagedNamespaceWatcher(t *testing.T) { + router := &testNamespaceSubscriber{name: "router"} + logger := zap.NewNop() + manager, handlers, err := PrepareManagedNamespaceWatcher(context.Background(), logger, "router.NSWatcher", []string{"tenant-a"}, NamespaceRemovalStrategyTrackOnly, router) + if err != nil { + t.Fatalf("expected watcher preparation success: %v", err) + } + if !reflect.DeepEqual([]string{"tenant-a"}, manager.Snapshot()) { + t.Fatalf("expected watcher manager snapshot to contain bootstrapped namespace") + } + namespace := &corev1.Namespace{} + namespace.Name = "tenant-a" + namespace.Labels = map[string]string{ManagedNamespaceLabelKey: ManagedNamespaceLabelValue} + handlers.UpdateFunc(namespace, namespace) + if router.addCalls != 1 || router.resyncCalls != 1 { + t.Fatalf("expected bootstrap add and handler resync calls") + } +} + func TestNamespaceManagerDispatchAdd(t *testing.T) { manager := NewNamespaceManager() manager.Upsert(NamespaceEvent{Type: NamespaceEventAdd, Name: "tenant-a", Source: NamespaceSourceWatcher})