From 0d735ae640abc3e0a38dded45c02a967ab18e7fd Mon Sep 17 00:00:00 2001 From: Stepan Paksashvili <81509933+ipaqsa@users.noreply.github.com> Date: Thu, 11 Dec 2025 20:56:11 +0300 Subject: [PATCH] [fix] module enabling (#711) Signed-off-by: Stepan Paksashvili Signed-off-by: Pavel Okhlopkov Co-authored-by: Pavel Okhlopkov --- .github/workflows/lint.yaml | 6 +- pkg/kube_config_manager/backend/backend.go | 3 +- .../backend/configmap/configmap.go | 8 +- pkg/kube_config_manager/context/context.go | 23 +++ .../kube_config_manager.go | 144 +++++++++--------- .../models/hooks/kind/gohook.go | 3 +- sdk/registry.go | 3 +- 7 files changed, 110 insertions(+), 80 deletions(-) create mode 100644 pkg/kube_config_manager/context/context.go diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 40235529e..d1de79b2c 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 @@ -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: 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/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..5106b3b30 --- /dev/null +++ b/pkg/kube_config_manager/context/context.go @@ -0,0 +1,23 @@ +// Package context provides context helpers for kube-config-manager. +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 5bb3ed6f7..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, @@ -241,84 +243,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() != cfg.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() != cfg.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, } } } 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))