From 603327a6c798e1b85bd36746ba408f08159d0b60 Mon Sep 17 00:00:00 2001 From: Stepan Paksashvili Date: Thu, 11 Dec 2025 18:58:59 +0300 Subject: [PATCH 1/8] [fix] module enabling gap Signed-off-by: Stepan Paksashvili --- .../kube_config_manager.go | 140 +++++++++--------- 1 file changed, 73 insertions(+), 67 deletions(-) diff --git a/pkg/kube_config_manager/kube_config_manager.go b/pkg/kube_config_manager/kube_config_manager.go index 5bb3ed6f7..7af03ee70 100644 --- a/pkg/kube_config_manager/kube_config_manager.go +++ b/pkg/kube_config_manager/kube_config_manager.go @@ -53,7 +53,7 @@ func NewKubeConfigManager(ctx context.Context, bk backend.ConfigHandler, runtime if err != nil { return err } - //nolint: revive,staticcheck // basic type is enough here + // nolint: revive,staticcheck // basic type is enough here cctx = context.WithValue(cctx, "kube-config-manager-debug", val) return nil }, @@ -241,84 +241,90 @@ func (kcm *KubeConfigManager) handleConfigEvent(obj config.Event) { } default: - // some module values - modulesChanged := []string{} - modulesStateChanged := []string{} - moduleMaintenanceChanged := make(map[string]utils.Maintenance) - - // module update kcm.m.Lock() defer kcm.m.Unlock() + moduleName := obj.Key moduleCfg := obj.Config.Modules[obj.Key] - if obj.Op == config.EventDelete { - kcm.logger.Info("Module section deleted", slog.String("moduleName", moduleName)) - modulesChanged = append(modulesChanged, moduleName) - if kcm.currentConfig.Modules[moduleName].GetEnabled() != "" && kcm.currentConfig.Modules[moduleName].GetEnabled() != "n/d" { - modulesStateChanged = append(modulesStateChanged, moduleName) - } - if kcm.currentConfig.Modules[moduleName].GetMaintenanceState() == utils.NoResourceReconciliation { - moduleMaintenanceChanged[moduleName] = utils.Managed - } + switch obj.Op { + case config.EventDelete: + kcm.handleDeleteEvent(moduleName, moduleCfg) + default: + kcm.handleUpdateEvent(moduleName, moduleCfg) + } + } +} - moduleCfg.Reset() - moduleCfg.Checksum = moduleCfg.ModuleConfig.Checksum() - kcm.currentConfig.Modules[obj.Key] = moduleCfg - kcm.configEventCh <- config.KubeConfigEvent{ - Type: config.KubeConfigChanged, - ModuleValuesChanged: modulesChanged, - ModuleEnabledStateChanged: modulesStateChanged, - ModuleMaintenanceChanged: moduleMaintenanceChanged, - } - return +func (kcm *KubeConfigManager) handleDeleteEvent(moduleName string, cfg *config.ModuleKubeConfig) { + var modulesChanged []string + var modulesStateChanged []string + moduleMaintenanceChanged := make(map[string]utils.Maintenance) + + kcm.logger.Info("module section deleted", slog.String("name", moduleName)) + modulesChanged = append(modulesChanged, moduleName) + if kcm.currentConfig.Modules[moduleName].GetEnabled() != "" && kcm.currentConfig.Modules[moduleName].GetEnabled() != "n/d" { + modulesStateChanged = append(modulesStateChanged, moduleName) + } + + if kcm.currentConfig.Modules[moduleName].GetMaintenanceState() == utils.NoResourceReconciliation { + moduleMaintenanceChanged[moduleName] = utils.Managed + } + + cfg.Reset() + cfg.Checksum = cfg.ModuleConfig.Checksum() + kcm.currentConfig.Modules[moduleName] = cfg + + kcm.configEventCh <- config.KubeConfigEvent{ + Type: config.KubeConfigChanged, + ModuleValuesChanged: modulesChanged, + ModuleEnabledStateChanged: modulesStateChanged, + ModuleMaintenanceChanged: moduleMaintenanceChanged, + } +} + +func (kcm *KubeConfigManager) handleUpdateEvent(moduleName string, cfg *config.ModuleKubeConfig) { + var modulesChanged []string + var modulesStateChanged []string + moduleMaintenanceChanged := make(map[string]utils.Maintenance) + + var changed bool + + if currentCfg, has := kcm.currentConfig.Modules[moduleName]; has { + if currentCfg.Checksum != cfg.Checksum { + changed = true + modulesChanged = append(modulesChanged, moduleName) } - // Module section is changed if a new checksum doesn't equal to saved one and isn't in known checksums, or the module new state doesn't equal to the previous one. - if kcm.knownChecksums.HasEqualChecksum(moduleName, moduleCfg.Checksum) { - // Remove known checksum, do not fire event on self-update. - kcm.knownChecksums.Remove(moduleName, moduleCfg.Checksum) - } else { - if currModuleCfg, has := kcm.currentConfig.Modules[moduleName]; has { - if currModuleCfg.Checksum != moduleCfg.Checksum { - modulesChanged = append(modulesChanged, moduleName) - } - if kcm.currentConfig.Modules[moduleName].GetEnabled() != moduleCfg.GetEnabled() { - modulesStateChanged = append(modulesStateChanged, moduleName) - } + if currentCfg.GetEnabled() != currentCfg.GetEnabled() { + changed = true + modulesStateChanged = append(modulesStateChanged, moduleName) + } - if kcm.currentConfig.Modules[moduleName].GetMaintenanceState() != moduleCfg.GetMaintenanceState() { - moduleMaintenanceChanged[moduleName] = moduleCfg.GetMaintenanceState() - } - kcm.logger.Info("Module section changed. Enabled flag transition.", - slog.String("moduleName", moduleName), - slog.String("previous", kcm.currentConfig.Modules[moduleName].GetEnabled()), - slog.String("current", moduleCfg.GetEnabled()), - slog.String("maintenanceFlag", moduleCfg.GetMaintenanceState().String())) - } else { - modulesChanged = append(modulesChanged, moduleName) - if moduleCfg.GetEnabled() != "" && moduleCfg.GetEnabled() != "n/d" { - modulesStateChanged = append(modulesStateChanged, moduleName) - } + if currentCfg.GetMaintenanceState() != currentCfg.GetMaintenanceState() { + changed = true + moduleMaintenanceChanged[moduleName] = currentCfg.GetMaintenanceState() + } + } else { + changed = true - if moduleCfg.GetMaintenanceState() == utils.NoResourceReconciliation { - moduleMaintenanceChanged[moduleName] = utils.NoResourceReconciliation - } - kcm.logger.Info("Module section added", - slog.String("moduleName", moduleName), - slog.String("enabledFlag", moduleCfg.GetEnabled()), - slog.String("maintenanceFlag", moduleCfg.GetMaintenanceState().String())) - } + modulesChanged = append(modulesChanged, moduleName) + if cfg.GetEnabled() != "" && cfg.GetEnabled() != "n/d" { + modulesStateChanged = append(modulesStateChanged, moduleName) } - if len(modulesChanged)+len(modulesStateChanged)+len(moduleMaintenanceChanged) > 0 { - kcm.currentConfig.Modules[obj.Key] = moduleCfg - kcm.configEventCh <- config.KubeConfigEvent{ - Type: config.KubeConfigChanged, - ModuleValuesChanged: modulesChanged, - ModuleEnabledStateChanged: modulesStateChanged, - ModuleMaintenanceChanged: moduleMaintenanceChanged, - } + if cfg.GetMaintenanceState() == utils.NoResourceReconciliation { + moduleMaintenanceChanged[moduleName] = utils.NoResourceReconciliation + } + } + + if changed { + kcm.currentConfig.Modules[moduleName] = cfg + kcm.configEventCh <- config.KubeConfigEvent{ + Type: config.KubeConfigChanged, + ModuleValuesChanged: modulesChanged, + ModuleEnabledStateChanged: modulesStateChanged, + ModuleMaintenanceChanged: moduleMaintenanceChanged, } } } From 9a5e74c5b422d783930853662c7f747348812ff8 Mon Sep 17 00:00:00 2001 From: Stepan Paksashvili Date: Thu, 11 Dec 2025 20:01:44 +0300 Subject: [PATCH 2/8] [fix] module enabling gap Signed-off-by: Stepan Paksashvili --- pkg/kube_config_manager/kube_config_manager.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/kube_config_manager/kube_config_manager.go b/pkg/kube_config_manager/kube_config_manager.go index 7af03ee70..b0fba9175 100644 --- a/pkg/kube_config_manager/kube_config_manager.go +++ b/pkg/kube_config_manager/kube_config_manager.go @@ -296,12 +296,12 @@ func (kcm *KubeConfigManager) handleUpdateEvent(moduleName string, cfg *config.M modulesChanged = append(modulesChanged, moduleName) } - if currentCfg.GetEnabled() != currentCfg.GetEnabled() { + if currentCfg.GetEnabled() != cfg.GetEnabled() { changed = true modulesStateChanged = append(modulesStateChanged, moduleName) } - if currentCfg.GetMaintenanceState() != currentCfg.GetMaintenanceState() { + if currentCfg.GetMaintenanceState() != cfg.GetMaintenanceState() { changed = true moduleMaintenanceChanged[moduleName] = currentCfg.GetMaintenanceState() } From 01936060d227f682137d8327e37815ad25f058f8 Mon Sep 17 00:00:00 2001 From: Pavel Okhlopkov Date: Thu, 11 Dec 2025 20:15:14 +0300 Subject: [PATCH 3/8] fix Signed-off-by: Pavel Okhlopkov --- .../backend/configmap/configmap.go | 8 ++----- pkg/kube_config_manager/context/context.go | 22 +++++++++++++++++++ .../kube_config_manager.go | 6 +++-- 3 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 pkg/kube_config_manager/context/context.go diff --git a/pkg/kube_config_manager/backend/configmap/configmap.go b/pkg/kube_config_manager/backend/configmap/configmap.go index 74e32d36d..b5fd0ad43 100644 --- a/pkg/kube_config_manager/backend/configmap/configmap.go +++ b/pkg/kube_config_manager/backend/configmap/configmap.go @@ -17,6 +17,7 @@ import ( "k8s.io/client-go/tools/cache" "github.com/flant/addon-operator/pkg/kube_config_manager/config" + kcmcontext "github.com/flant/addon-operator/pkg/kube_config_manager/context" "github.com/flant/addon-operator/pkg/utils" "github.com/flant/kube-client/client" ) @@ -93,12 +94,7 @@ func (b Backend) saveGlobalConfigValues(ctx context.Context, values utils.Values } func (b Backend) isDebugEnabled(ctx context.Context) bool { - debug, ok := ctx.Value("kube-config-manager-debug").(bool) - if !ok { - return false - } - - return debug + return kcmcontext.IsKubeConfigManagerDebug(ctx) } // saveModuleConfigValues updates module section in ConfigMap. diff --git a/pkg/kube_config_manager/context/context.go b/pkg/kube_config_manager/context/context.go new file mode 100644 index 000000000..ff92f1ee1 --- /dev/null +++ b/pkg/kube_config_manager/context/context.go @@ -0,0 +1,22 @@ +package context + +import "context" + +type contextValue string + +const ( + kubeConfigManagerDebug contextValue = "kube-config-manager-debug" +) + +func WithKubeConfigManagerDebug(ctx context.Context, value bool) context.Context { + return context.WithValue(ctx, kubeConfigManagerDebug, value) +} + +func IsKubeConfigManagerDebug(ctx context.Context) bool { + val := ctx.Value(kubeConfigManagerDebug) + if val == nil { + return false + } + debug, ok := val.(bool) + return ok && debug +} diff --git a/pkg/kube_config_manager/kube_config_manager.go b/pkg/kube_config_manager/kube_config_manager.go index b0fba9175..449c0ea02 100644 --- a/pkg/kube_config_manager/kube_config_manager.go +++ b/pkg/kube_config_manager/kube_config_manager.go @@ -12,6 +12,7 @@ import ( "github.com/flant/addon-operator/pkg/kube_config_manager/backend" "github.com/flant/addon-operator/pkg/kube_config_manager/config" + kcmcontext "github.com/flant/addon-operator/pkg/kube_config_manager/context" "github.com/flant/addon-operator/pkg/utils" runtimeConfig "github.com/flant/shell-operator/pkg/config" ) @@ -53,8 +54,9 @@ func NewKubeConfigManager(ctx context.Context, bk backend.ConfigHandler, runtime if err != nil { return err } - // nolint: revive,staticcheck // basic type is enough here - cctx = context.WithValue(cctx, "kube-config-manager-debug", val) + + cctx = kcmcontext.WithKubeConfigManagerDebug(cctx, val) + return nil }, nil, From 14f8c8063e4b971b8add2186378c608e965f37af Mon Sep 17 00:00:00 2001 From: Pavel Okhlopkov Date: Thu, 11 Dec 2025 20:25:09 +0300 Subject: [PATCH 4/8] add comment Signed-off-by: Pavel Okhlopkov --- pkg/kube_config_manager/context/context.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/kube_config_manager/context/context.go b/pkg/kube_config_manager/context/context.go index ff92f1ee1..656aec4aa 100644 --- a/pkg/kube_config_manager/context/context.go +++ b/pkg/kube_config_manager/context/context.go @@ -1,3 +1,5 @@ +// Package context provides context helpers for kube-config-manager. + package context import "context" From 84e525b3d201314e353f7f46487c64e97b6696bd Mon Sep 17 00:00:00 2001 From: Pavel Okhlopkov Date: Thu, 11 Dec 2025 20:35:23 +0300 Subject: [PATCH 5/8] fix Signed-off-by: Pavel Okhlopkov --- pkg/kube_config_manager/context/context.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/kube_config_manager/context/context.go b/pkg/kube_config_manager/context/context.go index 656aec4aa..5106b3b30 100644 --- a/pkg/kube_config_manager/context/context.go +++ b/pkg/kube_config_manager/context/context.go @@ -1,5 +1,4 @@ // Package context provides context helpers for kube-config-manager. - package context import "context" From d5fba348afb638cad6f9ff32b7abc7252b3b5734 Mon Sep 17 00:00:00 2001 From: Pavel Okhlopkov Date: Thu, 11 Dec 2025 20:37:25 +0300 Subject: [PATCH 6/8] bump go Signed-off-by: Pavel Okhlopkov --- .github/workflows/lint.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 40235529e..da6f18bb9 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -11,10 +11,10 @@ jobs: name: Run Go linters runs-on: ubuntu-latest steps: - - name: Set up Go 1.23 + - name: Set up Go 1.25 uses: actions/setup-go@v5 with: - go-version: '1.23' + go-version: '1.25' id: go - name: Check out addon-operator code From 9e08ba3194e16fd722574ae2f068ee78aacf09e9 Mon Sep 17 00:00:00 2001 From: Pavel Okhlopkov Date: Thu, 11 Dec 2025 20:40:21 +0300 Subject: [PATCH 7/8] bump linter Signed-off-by: Pavel Okhlopkov --- .github/workflows/lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index da6f18bb9..d1de79b2c 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -38,7 +38,7 @@ jobs: - name: Run golangci-lint run: | - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b . v2.1.6 + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b . v2.7.2 ./golangci-lint run codespell: From 56aef43638f4bd89241ca4074b7842680b4af4ae Mon Sep 17 00:00:00 2001 From: Pavel Okhlopkov Date: Thu, 11 Dec 2025 20:50:20 +0300 Subject: [PATCH 8/8] lint Signed-off-by: Pavel Okhlopkov --- pkg/kube_config_manager/backend/backend.go | 3 ++- pkg/module_manager/models/hooks/kind/gohook.go | 3 ++- sdk/registry.go | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pkg/kube_config_manager/backend/backend.go b/pkg/kube_config_manager/backend/backend.go index c9382d164..77ab6bca6 100644 --- a/pkg/kube_config_manager/backend/backend.go +++ b/pkg/kube_config_manager/backend/backend.go @@ -16,6 +16,7 @@ type ConfigHandler interface { LoadConfig(ctx context.Context, modulesNames ...string) (*config.KubeConfig, error) // SaveConfigValues saves patches for modules in backend (if supported), overriding the configuration - // Deprecated: saving values in the values source is not recommended and shouldn't be used anymore + // Deprecated: + // saving values in the values source is not recommended and shouldn't be used anymore SaveConfigValues(ctx context.Context, key string, values utils.Values) ( /*checksum*/ string, error) } diff --git a/pkg/module_manager/models/hooks/kind/gohook.go b/pkg/module_manager/models/hooks/kind/gohook.go index 7c9ed58d9..36f1843c5 100644 --- a/pkg/module_manager/models/hooks/kind/gohook.go +++ b/pkg/module_manager/models/hooks/kind/gohook.go @@ -83,7 +83,8 @@ func (h *GoHook) GetHookController() *controller.HookController { } // GetBasicHook returns hook for shell-operator -// Deprecated: don't use it for production purposes. You don't need such a low level for working with hooks +// Deprecated: +// don't use it for production purposes. You don't need such a low level for working with hooks func (h *GoHook) GetBasicHook() sh_hook.Hook { return h.basicHook } diff --git a/sdk/registry.go b/sdk/registry.go index f2509d413..9395aed69 100644 --- a/sdk/registry.go +++ b/sdk/registry.go @@ -60,7 +60,8 @@ func (h *HookRegistry) GetGlobalHooks() []*kind.GoHook { } // Hooks returns all (module and global) hooks -// Deprecated: method exists for backward compatibility, use GetGlobalHooks or GetModuleHooks instead +// Deprecated: +// method exists for backward compatibility, use GetGlobalHooks or GetModuleHooks instead func (h *HookRegistry) Hooks() []*kind.GoHook { res := make([]*kind.GoHook, 0, len(h.globalHooks)+len(h.embeddedModuleHooks))