From faf488fcd7f0eff350ccc96c0b0b804655ebfa56 Mon Sep 17 00:00:00 2001 From: Safwan Date: Tue, 14 Jul 2026 14:14:55 +0500 Subject: [PATCH] added support for multiple watch namespaces --- cmd/reloader/main.go | 9 +- .../chart/reloader/templates/_helpers.tpl | 22 ++-- .../chart/reloader/templates/clusterrole.yaml | 1 - .../chart/reloader/templates/deployment.yaml | 22 +++- .../chart/reloader/templates/role.yaml | 2 +- .../chart/reloader/templates/rolebinding.yaml | 2 +- .../kubernetes/chart/reloader/values.yaml | 5 + internal/pkg/config/flags.go | 18 ++-- internal/pkg/config/flags_test.go | 101 ++++++++++++++---- internal/pkg/controller/manager.go | 52 +++------ 10 files changed, 154 insertions(+), 80 deletions(-) diff --git a/cmd/reloader/main.go b/cmd/reloader/main.go index 32535215..781d28c5 100644 --- a/cmd/reloader/main.go +++ b/cmd/reloader/main.go @@ -54,7 +54,8 @@ func newReloaderCommand() *cobra.Command { } func run(cmd *cobra.Command, args []string) error { - if err := config.ApplyFlags(cfg); err != nil { + scopeWarnings, err := config.ApplyFlags(cfg) + if err != nil { return fmt.Errorf("applying flags: %w", err) } @@ -81,9 +82,9 @@ func run(cmd *cobra.Command, args []string) error { log.Info("Starting Reloader") - // Enforce master-parity scope semantics before reconcilers/manager read the - // config: selector and ignore lists are only honored in global mode. - for _, w := range cfg.ApplyNamespaceScope() { + // Namespace-scope semantics are enforced in ApplyFlags; surface any warnings + // it produced now that logging is configured. + for _, w := range scopeWarnings { log.Info(w) } diff --git a/deployments/kubernetes/chart/reloader/templates/_helpers.tpl b/deployments/kubernetes/chart/reloader/templates/_helpers.tpl index 306da2d7..19c65533 100644 --- a/deployments/kubernetes/chart/reloader/templates/_helpers.tpl +++ b/deployments/kubernetes/chart/reloader/templates/_helpers.tpl @@ -89,13 +89,12 @@ Create the namespace selector if it does not watch globally {{- end -}} {{/* -Effective set of namespaces to watch in scoped mode: the release namespace -(always included so the meta-info ConfigMap, HA leases and events keep working) -plus the user-supplied reloader.namespaces, deduped and sorted. +Namespaces to watch in scoped mode: exactly the user-supplied reloader.namespaces, +trimmed, de-duped and sorted. The release namespace is intentionally NOT added here +— Reloader watches only what the user asked for (an empty result means global mode). Returns a JSON-encoded list; consumers use mustFromJson to iterate. */}} {{- define "reloader-watchNamespaces" -}} -{{- $relNs := .Values.namespace | default .Release.Namespace -}} {{- $ns := .Values.reloader.namespaces | default list -}} {{- if kindIs "string" $ns -}} {{- $ns = splitList "," $ns -}} @@ -107,8 +106,7 @@ Returns a JSON-encoded list; consumers use mustFromJson to iterate. {{- $clean = append $clean $t -}} {{- end -}} {{- end -}} -{{- $all := concat (list $relNs) $clean | uniq | sortAlpha -}} -{{- $all | toJson -}} +{{- $clean | uniq | sortAlpha | toJson -}} {{- end -}} {{/* @@ -118,6 +116,18 @@ Comma-joined form of reloader-watchNamespaces, for the --namespaces CLI flag. {{- include "reloader-watchNamespaces" . | mustFromJson | join "," -}} {{- end -}} +{{/* +Namespaces that need namespaced RBAC in scoped mode: the watched namespaces plus +the release namespace, so leader-election leases, the meta-info ConfigMap and +events keep working there even though it is not watched for reloads. +Returns a JSON-encoded list; consumers use mustFromJson to iterate. +*/}} +{{- define "reloader-rbacNamespaces" -}} +{{- $relNs := .Values.namespace | default .Release.Namespace -}} +{{- $watch := include "reloader-watchNamespaces" . | mustFromJson -}} +{{- concat (list $relNs) $watch | uniq | sortAlpha | toJson -}} +{{- end -}} + {{/* The namespaced RBAC rules granted to Reloader in every watched namespace. Shared between the single-namespace Role and the per-namespace scoped Roles so diff --git a/deployments/kubernetes/chart/reloader/templates/clusterrole.yaml b/deployments/kubernetes/chart/reloader/templates/clusterrole.yaml index bd14dfeb..d183cff8 100644 --- a/deployments/kubernetes/chart/reloader/templates/clusterrole.yaml +++ b/deployments/kubernetes/chart/reloader/templates/clusterrole.yaml @@ -56,7 +56,6 @@ rules: {{- if and (.Capabilities.APIVersions.Has "argoproj.io/v1alpha1") (.Values.reloader.isArgoRollouts) }} - apiGroups: - "argoproj.io" - - "" resources: - rollouts verbs: diff --git a/deployments/kubernetes/chart/reloader/templates/deployment.yaml b/deployments/kubernetes/chart/reloader/templates/deployment.yaml index b3ac972e..17549358 100644 --- a/deployments/kubernetes/chart/reloader/templates/deployment.yaml +++ b/deployments/kubernetes/chart/reloader/templates/deployment.yaml @@ -241,7 +241,7 @@ spec: - "--namespaces-to-ignore={{ .Values.reloader.ignoreNamespaces }}" {{- end }} {{- if (include "reloader-namespaceSelector" .) }} - - "--namespace-selector=\"{{ include "reloader-namespaceSelector" . }}\"" + - "--namespace-selector={{ include "reloader-namespaceSelector" . }}" {{- end }} {{- if .Values.reloader.resourceLabelSelector }} - "--resource-label-selector={{ .Values.reloader.resourceLabelSelector }}" @@ -275,6 +275,26 @@ spec: {{- if .Values.reloader.custom_annotations.configmap_auto }} - "--configmap-auto-annotation" - "{{ .Values.reloader.custom_annotations.configmap_auto }}" + {{- end }} + {{- if .Values.reloader.custom_annotations.configmap_exclude }} + - "--configmap-exclude-annotation" + - "{{ .Values.reloader.custom_annotations.configmap_exclude }}" + {{- end }} + {{- if .Values.reloader.custom_annotations.secret_exclude }} + - "--secret-exclude-annotation" + - "{{ .Values.reloader.custom_annotations.secret_exclude }}" + {{- end }} + {{- if .Values.reloader.custom_annotations.secretproviderclass }} + - "--secretproviderclass-annotation" + - "{{ .Values.reloader.custom_annotations.secretproviderclass }}" + {{- end }} + {{- if .Values.reloader.custom_annotations.secretproviderclass_auto }} + - "--secretproviderclass-auto-annotation" + - "{{ .Values.reloader.custom_annotations.secretproviderclass_auto }}" + {{- end }} + {{- if .Values.reloader.custom_annotations.secretproviderclass_exclude }} + - "--secretproviderclass-exclude-annotation" + - "{{ .Values.reloader.custom_annotations.secretproviderclass_exclude }}" {{- end }} {{- if .Values.reloader.custom_annotations.search }} - "--auto-search-annotation" diff --git a/deployments/kubernetes/chart/reloader/templates/role.yaml b/deployments/kubernetes/chart/reloader/templates/role.yaml index 28c535d6..b7b5cd92 100644 --- a/deployments/kubernetes/chart/reloader/templates/role.yaml +++ b/deployments/kubernetes/chart/reloader/templates/role.yaml @@ -7,7 +7,7 @@ {{- $apiVersion = "rbac.authorization.k8s.io/v1beta1" }} {{- end }} {{- if .Values.reloader.namespaces }} -{{- range $ns := (include "reloader-watchNamespaces" . | mustFromJson) }} +{{- range $ns := (include "reloader-rbacNamespaces" . | mustFromJson) }} apiVersion: {{ $apiVersion }} kind: Role metadata: diff --git a/deployments/kubernetes/chart/reloader/templates/rolebinding.yaml b/deployments/kubernetes/chart/reloader/templates/rolebinding.yaml index 7d73b182..187c90dd 100644 --- a/deployments/kubernetes/chart/reloader/templates/rolebinding.yaml +++ b/deployments/kubernetes/chart/reloader/templates/rolebinding.yaml @@ -4,7 +4,7 @@ {{- $apiVersion = "rbac.authorization.k8s.io/v1beta1" }} {{- end }} {{- if .Values.reloader.namespaces }} -{{- range $ns := (include "reloader-watchNamespaces" . | mustFromJson) }} +{{- range $ns := (include "reloader-rbacNamespaces" . | mustFromJson) }} apiVersion: {{ $apiVersion }} kind: RoleBinding metadata: diff --git a/deployments/kubernetes/chart/reloader/values.yaml b/deployments/kubernetes/chart/reloader/values.yaml index 15a22bcf..f236bdf7 100644 --- a/deployments/kubernetes/chart/reloader/values.yaml +++ b/deployments/kubernetes/chart/reloader/values.yaml @@ -223,6 +223,11 @@ reloader: # custom_annotations: # configmap: "my.company.com/configmap" # secret: "my.company.com/secret" + # configmap_exclude: "my.company.com/configmap-exclude" + # secret_exclude: "my.company.com/secret-exclude" + # secretproviderclass: "my.company.com/secretproviderclass" + # secretproviderclass_auto: "my.company.com/secretproviderclass-auto" + # secretproviderclass_exclude: "my.company.com/secretproviderclass-exclude" # ignore: "my.company.com/reloader-ignore" custom_annotations: {} diff --git a/internal/pkg/config/flags.go b/internal/pkg/config/flags.go index 969ffb59..6680abca 100644 --- a/internal/pkg/config/flags.go +++ b/internal/pkg/config/flags.go @@ -264,9 +264,11 @@ func BindFlags(fs *pflag.FlagSet, cfg *Config) { _ = v.BindEnv("alert-proxy", "ALERT_PROXY", "ALERT_WEBHOOK_PROXY") } -// ApplyFlags applies flag values from viper to the config struct. -// Call this after parsing flags. -func ApplyFlags(cfg *Config) error { +// ApplyFlags applies flag values from viper to the config struct. Call this +// after parsing flags. It returns any human-readable warnings produced while +// finalizing namespace scope (see ApplyNamespaceScope) so the caller can log +// them once a logger is available. +func ApplyFlags(cfg *Config) ([]string, error) { // Boolean flags cfg.AutoReloadAll = v.GetBool("auto-reload-all") cfg.SyncAfterRestart = v.GetBool("sync-after-restart") @@ -365,7 +367,7 @@ func ApplyFlags(cfg *Config) error { joinedNS := strings.Join(nsSelectors, ",") selector, err := labels.Parse(joinedNS) if err != nil { - return fmt.Errorf("invalid selector %q: %w", joinedNS, err) + return nil, fmt.Errorf("invalid selector %q: %w", joinedNS, err) } cfg.NamespaceSelectors = []labels.Selector{selector} } @@ -373,7 +375,7 @@ func ApplyFlags(cfg *Config) error { joinedRes := strings.Join(resSelectors, ",") selector, err := labels.Parse(joinedRes) if err != nil { - return fmt.Errorf("invalid selector %q: %w", joinedRes, err) + return nil, fmt.Errorf("invalid selector %q: %w", joinedRes, err) } cfg.ResourceSelectors = []labels.Selector{selector} } @@ -389,7 +391,11 @@ func ApplyFlags(cfg *Config) error { cfg.LeaderElection.RetryPeriod = 2 * time.Second } - return nil + // Enforce namespace-scope semantics here so the finalized config is + // self-consistent for every caller: selector/ignore lists are only honored + // in global mode. Warnings are returned for the caller to log once logging + // is set up. + return cfg.ApplyNamespaceScope(), nil } // parseBoolString parses a string as a boolean, defaulting to false. diff --git a/internal/pkg/config/flags_test.go b/internal/pkg/config/flags_test.go index c7e6b975..233a6527 100644 --- a/internal/pkg/config/flags_test.go +++ b/internal/pkg/config/flags_test.go @@ -92,7 +92,7 @@ func TestBindFlags_DefaultValues(t *testing.T) { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } @@ -126,7 +126,7 @@ func TestBindFlags_CustomValues(t *testing.T) { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } @@ -168,7 +168,7 @@ func TestApplyFlags_SecretProviderClassAnnotations(t *testing.T) { if err := fs.Parse(nil); err != nil { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } defaults := DefaultAnnotations() @@ -195,7 +195,7 @@ func TestApplyFlags_SecretProviderClassAnnotations(t *testing.T) { if err := fs.Parse(args); err != nil { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } if cfg.Annotations.SecretProviderClassAuto != "spc.example.com/auto" { @@ -218,7 +218,7 @@ func TestApplyFlags_ExcludeAnnotations(t *testing.T) { if err := fs.Parse(nil); err != nil { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } defaults := DefaultAnnotations() @@ -241,7 +241,7 @@ func TestApplyFlags_ExcludeAnnotations(t *testing.T) { if err := fs.Parse(args); err != nil { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } if cfg.Annotations.ConfigmapExclude != "cm.example.com/exclude" { @@ -261,7 +261,7 @@ func TestApplyFlags_IgnoreAnnotation(t *testing.T) { if err := fs.Parse(nil); err != nil { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } if cfg.Annotations.Ignore != DefaultAnnotations().Ignore { @@ -276,7 +276,7 @@ func TestApplyFlags_IgnoreAnnotation(t *testing.T) { if err := fs.Parse([]string{"--ignore-annotation=my.company.com/reloader-ignore"}); err != nil { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } if cfg.Annotations.Ignore != "my.company.com/reloader-ignore" { @@ -313,7 +313,7 @@ func TestApplyFlags_BooleanStrings(t *testing.T) { t.Fatalf("Parse() error = %v", err) } - err := ApplyFlags(cfg) + _, err := ApplyFlags(cfg) if (err != nil) != tt.wantErr { t.Errorf("ApplyFlags() error = %v, wantErr %v", err, tt.wantErr) return @@ -343,7 +343,7 @@ func TestApplyFlags_CommaSeparatedLists(t *testing.T) { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } @@ -378,7 +378,7 @@ func TestApplyFlags_Selectors(t *testing.T) { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } @@ -409,7 +409,7 @@ func TestApplyFlags_InvalidSelector(t *testing.T) { t.Fatalf("Parse() error = %v", err) } - err := ApplyFlags(cfg) + _, err := ApplyFlags(cfg) if err == nil { t.Error("ApplyFlags() should return error for invalid selector") } @@ -461,7 +461,7 @@ func TestApplyFlags_AlertingEnvVars(t *testing.T) { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } @@ -494,7 +494,7 @@ func TestApplyFlags_LegacyProxyEnvVar(t *testing.T) { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } @@ -511,7 +511,7 @@ func TestApplyFlagsCSIIntegration(t *testing.T) { if err := fs.Parse([]string{"--enable-csi-integration=true"}); err != nil { t.Fatal(err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatal(err) } if !cfg.CSIIntegrationEnabled { @@ -592,7 +592,7 @@ func TestApplyFlags_NamespacesScoped(t *testing.T) { if err := fs.Parse([]string{"--namespaces=team-a,team-b"}); err != nil { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } @@ -617,7 +617,7 @@ func TestApplyFlags_NamespacesFromEnv(t *testing.T) { if err := fs.Parse([]string{}); err != nil { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } @@ -636,7 +636,7 @@ func TestApplyFlags_NamespacesGlobal(t *testing.T) { if err := fs.Parse([]string{}); err != nil { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } @@ -657,7 +657,7 @@ func TestApplyFlags_NamespacesTrimsEmptyEntries(t *testing.T) { if err := fs.Parse([]string{"--namespaces=team-a, ,team-b,"}); err != nil { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } @@ -682,7 +682,7 @@ func TestApplyFlags_NamespacesAllEmptyIsGlobal(t *testing.T) { if err := fs.Parse([]string{"--namespaces=, ,"}); err != nil { t.Fatalf("Parse() error = %v", err) } - if err := ApplyFlags(cfg); err != nil { + if _, err := ApplyFlags(cfg); err != nil { t.Fatalf("ApplyFlags() error = %v", err) } @@ -693,3 +693,64 @@ func TestApplyFlags_NamespacesAllEmptyIsGlobal(t *testing.T) { t.Errorf("all-empty namespaces should be global mode") } } + +// ApplyFlags must finalize a self-consistent config: in scoped mode it enforces +// namespace-scope semantics (clears selector/ignore lists) and returns warnings, +// without the caller having to invoke ApplyNamespaceScope separately. +func TestApplyFlags_ScopedClearsSelectorsAndIgnores(t *testing.T) { + resetViper() + cfg := NewDefault() + fs := pflag.NewFlagSet("test", pflag.ContinueOnError) + BindFlags(fs, cfg) + + if err := fs.Parse([]string{ + "--namespaces=team-a", + "--namespace-selector=env=prod", + "--namespaces-to-ignore=kube-system", + }); err != nil { + t.Fatalf("Parse() error = %v", err) + } + warnings, err := ApplyFlags(cfg) + if err != nil { + t.Fatalf("ApplyFlags() error = %v", err) + } + + if len(cfg.NamespaceSelectors) != 0 || len(cfg.NamespaceSelectorStrings) != 0 { + t.Errorf("scoped mode should clear namespace selectors, got %v", cfg.NamespaceSelectorStrings) + } + if len(cfg.IgnoredNamespaces) != 0 { + t.Errorf("scoped mode should clear ignored namespaces, got %v", cfg.IgnoredNamespaces) + } + if len(warnings) != 2 { + t.Errorf("expected 2 scope warnings, got %v", warnings) + } +} + +func TestApplyFlags_GlobalKeepsSelectorsNoWarnings(t *testing.T) { + resetViper() + t.Setenv("KUBERNETES_NAMESPACE", "") + cfg := NewDefault() + fs := pflag.NewFlagSet("test", pflag.ContinueOnError) + BindFlags(fs, cfg) + + if err := fs.Parse([]string{ + "--namespace-selector=env=prod", + "--namespaces-to-ignore=kube-system", + }); err != nil { + t.Fatalf("Parse() error = %v", err) + } + warnings, err := ApplyFlags(cfg) + if err != nil { + t.Fatalf("ApplyFlags() error = %v", err) + } + + if !cfg.IsGlobalMode() { + t.Fatalf("no --namespaces should be global mode") + } + if len(cfg.NamespaceSelectors) != 1 || len(cfg.IgnoredNamespaces) != 1 { + t.Errorf("global mode should keep selectors and ignored namespaces") + } + if len(warnings) != 0 { + t.Errorf("global mode should produce no warnings, got %v", warnings) + } +} diff --git a/internal/pkg/controller/manager.go b/internal/pkg/controller/manager.go index 2c561e16..a6ae3182 100644 --- a/internal/pkg/controller/manager.go +++ b/internal/pkg/controller/manager.go @@ -66,9 +66,18 @@ type ManagerOptions struct { Collectors *metrics.Collectors } -// NewManager creates a new controller-runtime manager with the given options. -// This follows controller-runtime and operator-sdk conventions for leader election. +// NewManager creates a new controller-runtime manager using the ambient cluster +// configuration (in-cluster or kubeconfig). It follows controller-runtime and +// operator-sdk conventions for leader election. func NewManager(opts ManagerOptions) (ctrl.Manager, error) { + return NewManagerWithRestConfig(opts, ctrl.GetConfigOrDie()) +} + +// NewManagerWithRestConfig creates a new controller-runtime manager with the +// given rest.Config. NewManager delegates here; tests can call it directly with +// a pre-existing cluster configuration (set cfg.MetricsAddr/HealthAddr to "0" to +// disable those servers and avoid port conflicts). +func NewManagerWithRestConfig(opts ManagerOptions, restConfig *rest.Config) (ctrl.Manager, error) { cfg := opts.Config le := cfg.LeaderElection @@ -100,7 +109,7 @@ func NewManager(opts ManagerOptions) (ctrl.Manager, error) { opts.Log.Info("namespace filtering enabled", "namespaces", cfg.WatchedNamespaces) } - mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), mgrOpts) + mgr, err := ctrl.NewManager(restConfig, mgrOpts) if err != nil { return nil, fmt.Errorf("creating manager: %w", err) } @@ -119,43 +128,6 @@ func NewManager(opts ManagerOptions) (ctrl.Manager, error) { return mgr, nil } -// NewManagerWithRestConfig creates a new controller-runtime manager with the given rest.Config. -// This is useful for testing where you have a pre-existing cluster configuration. -func NewManagerWithRestConfig(opts ManagerOptions, restConfig *rest.Config) (ctrl.Manager, error) { - cfg := opts.Config - le := cfg.LeaderElection - - mgrOpts := ctrl.Options{ - Scheme: runtimeScheme, - Metrics: ctrlmetrics.Options{ - BindAddress: "0", // Disable metrics server in tests - }, - HealthProbeBindAddress: "0", // Disable health probes in tests - - // Leader election configuration - LeaderElection: cfg.EnableHA, - LeaderElectionID: le.LockName, - LeaderElectionNamespace: le.Namespace, - LeaderElectionReleaseOnCancel: le.ReleaseOnCancel, - LeaseDuration: &le.LeaseDuration, - RenewDeadline: &le.RenewDeadline, - RetryPeriod: &le.RetryPeriod, - } - - if nsScope := buildDefaultNamespaces(cfg.WatchedNamespaces); nsScope != nil { - mgrOpts.Cache = cache.Options{ - DefaultNamespaces: nsScope, - } - } - - mgr, err := ctrl.NewManager(restConfig, mgrOpts) - if err != nil { - return nil, fmt.Errorf("creating manager: %w", err) - } - - return mgr, nil -} - // SetupReconcilers sets up all reconcilers with the manager. func SetupReconcilers(mgr ctrl.Manager, cfg *config.Config, log logr.Logger, collectors *metrics.Collectors) error { registry := workload.NewRegistry(