From d01a3fa7d2b6d96c15a6087cc585d1935f22e6db Mon Sep 17 00:00:00 2001 From: Stepan Paksashvili Date: Fri, 10 Apr 2026 17:15:42 +0300 Subject: [PATCH 1/4] [feat] idempotent kubernetes hooks enabling Signed-off-by: Stepan Paksashvili --- pkg/hook/controller/hook_controller.go | 14 ++++++++++++++ .../kubernetes_bindings_controller.go | 19 ++++++++++++++++++- .../kube_events_manager.go | 12 +++++------- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/pkg/hook/controller/hook_controller.go b/pkg/hook/controller/hook_controller.go index 05070e91..28c8886c 100644 --- a/pkg/hook/controller/hook_controller.go +++ b/pkg/hook/controller/hook_controller.go @@ -265,6 +265,20 @@ func (hc *HookController) UpdateMonitor(monitorId string, kind, apiVersion strin return nil } +func (hc *HookController) EnableKubernetesBindings() ([]BindingExecutionInfo, error) { + if hc.KubernetesController != nil { + return hc.KubernetesController.EnableKubernetesBindings() + } + + return nil, nil +} + +func (hc *HookController) DisableKubernetesBindings() { + if hc.KubernetesController != nil { + hc.KubernetesController.DisableKubernetesBindings() + } +} + func (hc *HookController) EnableScheduleBindings() { if hc.ScheduleController != nil { hc.ScheduleController.EnableScheduleBindings() diff --git a/pkg/hook/controller/kubernetes_bindings_controller.go b/pkg/hook/controller/kubernetes_bindings_controller.go index 6280d8e9..b4cb17d9 100644 --- a/pkg/hook/controller/kubernetes_bindings_controller.go +++ b/pkg/hook/controller/kubernetes_bindings_controller.go @@ -8,7 +8,7 @@ import ( "github.com/deckhouse/deckhouse/pkg/log" - pkg "github.com/flant/shell-operator/pkg" + "github.com/flant/shell-operator/pkg" bctx "github.com/flant/shell-operator/pkg/hook/binding_context" htypes "github.com/flant/shell-operator/pkg/hook/types" kubeeventsmanager "github.com/flant/shell-operator/pkg/kube_events_manager" @@ -27,6 +27,7 @@ type KubernetesBindingsController interface { WithKubernetesBindings([]htypes.OnKubernetesEventConfig) WithKubeEventsManager(kubeeventsmanager.KubeEventsSource) EnableKubernetesBindings() ([]BindingExecutionInfo, error) + DisableKubernetesBindings() UpdateMonitor(monitorId string, kind, apiVersion string) error UnlockEvents() UnlockEventsFor(monitorID string) @@ -82,6 +83,12 @@ func (c *kubernetesBindingsController) WithKubeEventsManager(kubeEventsManager k func (c *kubernetesBindingsController) EnableKubernetesBindings() ([]BindingExecutionInfo, error) { res := make([]BindingExecutionInfo, 0) + c.l.Lock() + if len(c.BindingMonitorLinks) > 0 { + return res, nil + } + c.l.Unlock() + for _, config := range c.KubernetesBindings { err := c.kubeEventsManager.AddMonitor(config.Monitor) if err != nil { @@ -182,6 +189,16 @@ func (c *kubernetesBindingsController) StopMonitors() { }) } +func (c *kubernetesBindingsController) DisableKubernetesBindings() { + c.l.Lock() + defer c.l.Unlock() + + for _, binding := range c.BindingMonitorLinks { + _ = c.kubeEventsManager.StopMonitor(binding.MonitorId) + delete(c.BindingMonitorLinks, binding.MonitorId) + } +} + func (c *kubernetesBindingsController) CanHandleEvent(kubeEvent kemtypes.KubeEvent) bool { var canHandleEvent bool diff --git a/pkg/kube_events_manager/kube_events_manager.go b/pkg/kube_events_manager/kube_events_manager.go index 9023acd4..5019c765 100644 --- a/pkg/kube_events_manager/kube_events_manager.go +++ b/pkg/kube_events_manager/kube_events_manager.go @@ -11,7 +11,7 @@ import ( metricsstorage "github.com/deckhouse/deckhouse/pkg/metrics-storage" klient "github.com/flant/kube-client/client" - pkg "github.com/flant/shell-operator/pkg" + "github.com/flant/shell-operator/pkg" kemtypes "github.com/flant/shell-operator/pkg/kube_events_manager/types" ) @@ -92,9 +92,8 @@ func (mgr *kubeEventsManager) WithMetricStorage(mstor metricsstorage.Storage) { // TODO cleanup informers in case of error // TODO use Context to stop informers func (mgr *kubeEventsManager) AddMonitor(monitorConfig *MonitorConfig) error { - log.Debug("Add MONITOR", - slog.String(pkg.LogKeyConfig, fmt.Sprintf("%+v", monitorConfig))) - monitor := NewMonitor( + mgr.logger.Debug("add kubernetes monitor", slog.String(pkg.LogKeyConfig, fmt.Sprintf("%+v", monitorConfig))) + mon := NewMonitor( mgr.ctx, mgr.KubeClient, mgr.metricStorage, @@ -107,13 +106,12 @@ func (mgr *kubeEventsManager) AddMonitor(monitorConfig *MonitorConfig) error { mgr.logger.Named("monitor"), ) - err := monitor.CreateInformers() - if err != nil { + if err := mon.CreateInformers(); err != nil { return err } mgr.m.Lock() - mgr.Monitors[monitorConfig.Metadata.MonitorId] = monitor + mgr.Monitors[monitorConfig.Metadata.MonitorId] = mon mgr.m.Unlock() return nil From baf22944357cf668b3d671ef2c5ba21c22f7ed24 Mon Sep 17 00:00:00 2001 From: Stepan Paksashvili Date: Fri, 10 Apr 2026 18:07:59 +0300 Subject: [PATCH 2/4] [feat] idempotent kubernetes hooks enabling Signed-off-by: Stepan Paksashvili --- .../kubernetes_bindings_controller.go | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/pkg/hook/controller/kubernetes_bindings_controller.go b/pkg/hook/controller/kubernetes_bindings_controller.go index b4cb17d9..4bd8b782 100644 --- a/pkg/hook/controller/kubernetes_bindings_controller.go +++ b/pkg/hook/controller/kubernetes_bindings_controller.go @@ -83,13 +83,11 @@ func (c *kubernetesBindingsController) WithKubeEventsManager(kubeEventsManager k func (c *kubernetesBindingsController) EnableKubernetesBindings() ([]BindingExecutionInfo, error) { res := make([]BindingExecutionInfo, 0) - c.l.Lock() - if len(c.BindingMonitorLinks) > 0 { - return res, nil - } - c.l.Unlock() - for _, config := range c.KubernetesBindings { + if _, found := c.getBindingMonitorLinksById(config.Monitor.Metadata.MonitorId); found { + continue + } + err := c.kubeEventsManager.AddMonitor(config.Monitor) if err != nil { return nil, fmt.Errorf("run monitor: %s", err) @@ -191,11 +189,15 @@ func (c *kubernetesBindingsController) StopMonitors() { func (c *kubernetesBindingsController) DisableKubernetesBindings() { c.l.Lock() - defer c.l.Unlock() + ids := make([]string, 0, len(c.BindingMonitorLinks)) + for id := range c.BindingMonitorLinks { + ids = append(ids, id) + } + c.BindingMonitorLinks = make(map[string]*KubernetesBindingToMonitorLink) + c.l.Unlock() - for _, binding := range c.BindingMonitorLinks { - _ = c.kubeEventsManager.StopMonitor(binding.MonitorId) - delete(c.BindingMonitorLinks, binding.MonitorId) + for _, id := range ids { + _ = c.kubeEventsManager.StopMonitor(id) } } From 5becf9b830c4477ff2681091f783ab6ea5555812 Mon Sep 17 00:00:00 2001 From: Stepan Paksashvili Date: Fri, 10 Apr 2026 18:16:16 +0300 Subject: [PATCH 3/4] [feat] idempotent kubernetes hooks enabling Signed-off-by: Stepan Paksashvili --- pkg/hook/controller/hook_controller.go | 6 --- .../kubernetes_bindings_controller.go | 40 ++++++++----------- test/hook/context/generator.go | 2 +- 3 files changed, 18 insertions(+), 30 deletions(-) diff --git a/pkg/hook/controller/hook_controller.go b/pkg/hook/controller/hook_controller.go index 28c8886c..56837f44 100644 --- a/pkg/hook/controller/hook_controller.go +++ b/pkg/hook/controller/hook_controller.go @@ -252,12 +252,6 @@ func (hc *HookController) UnlockKubernetesEventsFor(monitorID string) { } } -func (hc *HookController) StopMonitors() { - if hc.KubernetesController != nil { - hc.KubernetesController.StopMonitors() - } -} - func (hc *HookController) UpdateMonitor(monitorId string, kind, apiVersion string) error { if hc.KubernetesController != nil { return hc.KubernetesController.UpdateMonitor(monitorId, kind, apiVersion) diff --git a/pkg/hook/controller/kubernetes_bindings_controller.go b/pkg/hook/controller/kubernetes_bindings_controller.go index 4bd8b782..f031c799 100644 --- a/pkg/hook/controller/kubernetes_bindings_controller.go +++ b/pkg/hook/controller/kubernetes_bindings_controller.go @@ -31,7 +31,6 @@ type KubernetesBindingsController interface { UpdateMonitor(monitorId string, kind, apiVersion string) error UnlockEvents() UnlockEventsFor(monitorID string) - StopMonitors() CanHandleEvent(kubeEvent kemtypes.KubeEvent) bool HandleEvent(ctx context.Context, kubeEvent kemtypes.KubeEvent) BindingExecutionInfo BindingNames() []string @@ -83,22 +82,26 @@ func (c *kubernetesBindingsController) WithKubeEventsManager(kubeEventsManager k func (c *kubernetesBindingsController) EnableKubernetesBindings() ([]BindingExecutionInfo, error) { res := make([]BindingExecutionInfo, 0) + c.l.Lock() + alreadyEnabled := len(c.BindingMonitorLinks) == len(c.KubernetesBindings) + c.l.Unlock() + if alreadyEnabled { + return res, nil + } + for _, config := range c.KubernetesBindings { - if _, found := c.getBindingMonitorLinksById(config.Monitor.Metadata.MonitorId); found { - continue + if _, found := c.getBindingMonitorLinksById(config.Monitor.Metadata.MonitorId); !found { + if err := c.kubeEventsManager.AddMonitor(config.Monitor); err != nil { + return nil, fmt.Errorf("run monitor: %s", err) + } + c.setBindingMonitorLinks(config.Monitor.Metadata.MonitorId, &KubernetesBindingToMonitorLink{ + MonitorId: config.Monitor.Metadata.MonitorId, + BindingConfig: config, + }) + // Start monitor's informers to fill the cache. + c.kubeEventsManager.StartMonitor(config.Monitor.Metadata.MonitorId) } - err := c.kubeEventsManager.AddMonitor(config.Monitor) - if err != nil { - return nil, fmt.Errorf("run monitor: %s", err) - } - c.setBindingMonitorLinks(config.Monitor.Metadata.MonitorId, &KubernetesBindingToMonitorLink{ - MonitorId: config.Monitor.Metadata.MonitorId, - BindingConfig: config, - }) - // Start monitor's informers to fill the cache. - c.kubeEventsManager.StartMonitor(config.Monitor.Metadata.MonitorId) - synchronizationInfo := c.HandleEvent(context.TODO(), kemtypes.KubeEvent{ MonitorId: config.Monitor.Metadata.MonitorId, Type: kemtypes.TypeSynchronization, @@ -178,15 +181,6 @@ func (c *kubernetesBindingsController) UnlockEventsFor(monitorID string) { m.EnableKubeEventCb() } -// StopMonitors stops all monitors for the hook. -// TODO handle error! -func (c *kubernetesBindingsController) StopMonitors() { - c.iterateBindingMonitorLinks(func(monitorID string) bool { - _ = c.kubeEventsManager.StopMonitor(monitorID) - return false - }) -} - func (c *kubernetesBindingsController) DisableKubernetesBindings() { c.l.Lock() ids := make([]string, 0, len(c.BindingMonitorLinks)) diff --git a/test/hook/context/generator.go b/test/hook/context/generator.go index 3feaabe7..254ebd86 100644 --- a/test/hook/context/generator.go +++ b/test/hook/context/generator.go @@ -195,6 +195,6 @@ func (b *BindingContextController) RunBindingWithAllSnapshots(binding types.Bind func (b *BindingContextController) Stop() { if b.HookCtrl != nil { - b.HookCtrl.StopMonitors() + b.HookCtrl.DisableKubernetesBindings() } } From 59251a2b68e632edf36e0425c3aa846dfc4cab42 Mon Sep 17 00:00:00 2001 From: Stepan Paksashvili Date: Fri, 10 Apr 2026 18:21:41 +0300 Subject: [PATCH 4/4] [feat] idempotent kubernetes hooks enabling Signed-off-by: Stepan Paksashvili --- pkg/hook/controller/kubernetes_bindings_controller.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/hook/controller/kubernetes_bindings_controller.go b/pkg/hook/controller/kubernetes_bindings_controller.go index f031c799..80c966d5 100644 --- a/pkg/hook/controller/kubernetes_bindings_controller.go +++ b/pkg/hook/controller/kubernetes_bindings_controller.go @@ -82,9 +82,9 @@ func (c *kubernetesBindingsController) WithKubeEventsManager(kubeEventsManager k func (c *kubernetesBindingsController) EnableKubernetesBindings() ([]BindingExecutionInfo, error) { res := make([]BindingExecutionInfo, 0) - c.l.Lock() + c.l.RLock() alreadyEnabled := len(c.BindingMonitorLinks) == len(c.KubernetesBindings) - c.l.Unlock() + c.l.RUnlock() if alreadyEnabled { return res, nil }