diff --git a/internal/pkg/config/flags.go b/internal/pkg/config/flags.go index f3fe4955..1de5d2ef 100644 --- a/internal/pkg/config/flags.go +++ b/internal/pkg/config/flags.go @@ -25,104 +25,174 @@ var fv flagValues // Call this before parsing flags, then call ApplyFlags after parsing. func BindFlags(fs *pflag.FlagSet, cfg *Config) { // Auto reload - fs.BoolVar(&cfg.AutoReloadAll, "auto-reload-all", cfg.AutoReloadAll, - "Automatically reload all resources when their configmaps/secrets are updated, without requiring annotations") + fs.BoolVar( + &cfg.AutoReloadAll, "auto-reload-all", cfg.AutoReloadAll, + "Automatically reload all resources when their configmaps/secrets are updated, without requiring annotations", + ) // Reload strategy - fs.StringVar((*string)(&cfg.ReloadStrategy), "reload-strategy", string(cfg.ReloadStrategy), - "Strategy for triggering workload restart: 'env-vars' (default, GitOps friendly) or 'annotations'") + fs.StringVar( + (*string)(&cfg.ReloadStrategy), "reload-strategy", string(cfg.ReloadStrategy), + "Strategy for triggering workload restart: 'env-vars' (default, GitOps friendly) or 'annotations'", + ) - // Argo Rollouts (note: capital A in Argo for backward compatibility) - fs.StringVar(&fv.isArgoRollouts, "is-Argo-Rollouts", "false", - "Enable Argo Rollouts support (true/false)") + // Argo Rollouts + fs.StringVar( + &fv.isArgoRollouts, "is-Argo-Rollouts", "false", + "Enable Argo Rollouts support (true/false)", + ) // Event watching - fs.StringVar(&fv.reloadOnCreate, "reload-on-create", "false", - "Reload when configmaps/secrets are created (true/false)") - fs.StringVar(&fv.reloadOnDelete, "reload-on-delete", "false", - "Reload when configmaps/secrets are deleted (true/false)") + fs.StringVar( + &fv.reloadOnCreate, "reload-on-create", "false", + "Reload when configmaps/secrets are created (true/false)", + ) + fs.StringVar( + &fv.reloadOnDelete, "reload-on-delete", "false", + "Reload when configmaps/secrets are deleted (true/false)", + ) // Sync after restart - fs.BoolVar(&cfg.SyncAfterRestart, "sync-after-restart", cfg.SyncAfterRestart, - "Trigger sync operation after restart") + fs.BoolVar( + &cfg.SyncAfterRestart, "sync-after-restart", cfg.SyncAfterRestart, + "Trigger sync operation after restart", + ) // High availability / Leader election - fs.BoolVar(&cfg.EnableHA, "enable-ha", cfg.EnableHA, - "Enable high-availability mode with leader election") - fs.StringVar(&cfg.LeaderElection.LockName, "leader-election-id", cfg.LeaderElection.LockName, - "Name of the lease resource for leader election") - fs.StringVar(&cfg.LeaderElection.Namespace, "leader-election-namespace", cfg.LeaderElection.Namespace, - "Namespace for the leader election lease (defaults to pod namespace)") - fs.DurationVar(&cfg.LeaderElection.LeaseDuration, "leader-election-lease-duration", cfg.LeaderElection.LeaseDuration, - "Duration that non-leader candidates will wait before attempting to acquire leadership") - fs.DurationVar(&cfg.LeaderElection.RenewDeadline, "leader-election-renew-deadline", cfg.LeaderElection.RenewDeadline, - "Duration that the acting leader will retry refreshing leadership before giving up") - fs.DurationVar(&cfg.LeaderElection.RetryPeriod, "leader-election-retry-period", cfg.LeaderElection.RetryPeriod, - "Duration between leader election retries") - fs.BoolVar(&cfg.LeaderElection.ReleaseOnCancel, "leader-election-release-on-cancel", cfg.LeaderElection.ReleaseOnCancel, - "Release the leader lock when the manager is stopped") + fs.BoolVar( + &cfg.EnableHA, "enable-ha", cfg.EnableHA, + "Enable high-availability mode with leader election", + ) + fs.StringVar( + &cfg.LeaderElection.LockName, "leader-election-id", cfg.LeaderElection.LockName, + "Name of the lease resource for leader election", + ) + fs.StringVar( + &cfg.LeaderElection.Namespace, "leader-election-namespace", cfg.LeaderElection.Namespace, + "Namespace for the leader election lease (defaults to pod namespace)", + ) + fs.DurationVar( + &cfg.LeaderElection.LeaseDuration, "leader-election-lease-duration", cfg.LeaderElection.LeaseDuration, + "Duration that non-leader candidates will wait before attempting to acquire leadership", + ) + fs.DurationVar( + &cfg.LeaderElection.RenewDeadline, "leader-election-renew-deadline", cfg.LeaderElection.RenewDeadline, + "Duration that the acting leader will retry refreshing leadership before giving up", + ) + fs.DurationVar( + &cfg.LeaderElection.RetryPeriod, "leader-election-retry-period", cfg.LeaderElection.RetryPeriod, + "Duration between leader election retries", + ) + fs.BoolVar( + &cfg.LeaderElection.ReleaseOnCancel, "leader-election-release-on-cancel", cfg.LeaderElection.ReleaseOnCancel, + "Release the leader lock when the manager is stopped", + ) // Webhook - fs.StringVar(&cfg.WebhookURL, "webhook-url", cfg.WebhookURL, - "URL to send notification instead of triggering reload") + fs.StringVar( + &cfg.WebhookURL, "webhook-url", cfg.WebhookURL, + "URL to send notification instead of triggering reload", + ) // Filtering - resources (use StringVar not StringSliceVar for simpler parsing) - fs.StringVar(&fv.ignoredResources, "resources-to-ignore", "", - "Comma-separated list of resources to ignore (valid options: 'configMaps' or 'secrets')") - fs.StringVar(&fv.ignoredWorkloads, "ignored-workload-types", "", - "Comma-separated list of workload types to ignore (valid options: 'jobs', 'cronjobs', or both)") - fs.StringVar(&fv.ignoredNamespaces, "namespaces-to-ignore", "", - "Comma-separated list of namespaces to ignore") + fs.StringVar( + &fv.ignoredResources, "resources-to-ignore", "", + "Comma-separated list of resources to ignore (valid options: 'configMaps' or 'secrets')", + ) + fs.StringVar( + &fv.ignoredWorkloads, "ignored-workload-types", "", + "Comma-separated list of workload types to ignore (valid options: 'jobs', 'cronjobs', or both)", + ) + fs.StringVar( + &fv.ignoredNamespaces, "namespaces-to-ignore", "", + "Comma-separated list of namespaces to ignore", + ) // Filtering - selectors - fs.StringVar(&fv.namespaceSelectors, "namespace-selector", "", - "Comma-separated list of namespace label selectors") - fs.StringVar(&fv.resourceSelectors, "resource-label-selector", "", - "Comma-separated list of resource label selectors") + fs.StringVar( + &fv.namespaceSelectors, "namespace-selector", "", + "Comma-separated list of namespace label selectors", + ) + fs.StringVar( + &fv.resourceSelectors, "resource-label-selector", "", + "Comma-separated list of resource label selectors", + ) // Logging - fs.StringVar(&cfg.LogFormat, "log-format", cfg.LogFormat, - "Log format: 'json' or empty for default") - fs.StringVar(&cfg.LogLevel, "log-level", cfg.LogLevel, - "Log level: trace, debug, info, warning, error, fatal, panic") + fs.StringVar( + &cfg.LogFormat, "log-format", cfg.LogFormat, + "Log format: 'json' or empty for default", + ) + fs.StringVar( + &cfg.LogLevel, "log-level", cfg.LogLevel, + "Log level: trace, debug, info, warning, error, fatal, panic", + ) // Metrics - fs.StringVar(&cfg.MetricsAddr, "metrics-addr", cfg.MetricsAddr, - "Address to serve metrics on") + fs.StringVar( + &cfg.MetricsAddr, "metrics-addr", cfg.MetricsAddr, + "Address to serve metrics on", + ) // Health probes - fs.StringVar(&cfg.HealthAddr, "health-addr", cfg.HealthAddr, - "Address to serve health probes on") + fs.StringVar( + &cfg.HealthAddr, "health-addr", cfg.HealthAddr, + "Address to serve health probes on", + ) // Profiling - fs.BoolVar(&cfg.EnablePProf, "enable-pprof", cfg.EnablePProf, - "Enable pprof profiling server") - fs.StringVar(&cfg.PProfAddr, "pprof-addr", cfg.PProfAddr, - "Address for pprof server") + fs.BoolVar( + &cfg.EnablePProf, "enable-pprof", cfg.EnablePProf, + "Enable pprof profiling server", + ) + fs.StringVar( + &cfg.PProfAddr, "pprof-addr", cfg.PProfAddr, + "Address for pprof server", + ) // Annotation customization (flag names match v1 for backward compatibility) - fs.StringVar(&cfg.Annotations.Auto, "auto-annotation", cfg.Annotations.Auto, - "Annotation to detect changes in secrets/configmaps") - fs.StringVar(&cfg.Annotations.ConfigmapAuto, "configmap-auto-annotation", cfg.Annotations.ConfigmapAuto, - "Annotation to detect changes in configmaps") - fs.StringVar(&cfg.Annotations.SecretAuto, "secret-auto-annotation", cfg.Annotations.SecretAuto, - "Annotation to detect changes in secrets") - fs.StringVar(&cfg.Annotations.ConfigmapReload, "configmap-annotation", cfg.Annotations.ConfigmapReload, - "Annotation to detect changes in configmaps, specified by name") - fs.StringVar(&cfg.Annotations.SecretReload, "secret-annotation", cfg.Annotations.SecretReload, - "Annotation to detect changes in secrets, specified by name") - fs.StringVar(&cfg.Annotations.Search, "auto-search-annotation", cfg.Annotations.Search, - "Annotation to detect changes in configmaps or secrets tagged with special match annotation") - fs.StringVar(&cfg.Annotations.Match, "search-match-annotation", cfg.Annotations.Match, - "Annotation to mark secrets or configmaps to match the search") - fs.StringVar(&cfg.Annotations.PausePeriod, "pause-deployment-annotation", cfg.Annotations.PausePeriod, - "Annotation to define the time period to pause a deployment after a configmap/secret change") - fs.StringVar(&cfg.Annotations.PausedAt, "pause-deployment-time-annotation", cfg.Annotations.PausedAt, - "Annotation to indicate when a deployment was paused by Reloader") + fs.StringVar( + &cfg.Annotations.Auto, "auto-annotation", cfg.Annotations.Auto, + "Annotation to detect changes in secrets/configmaps", + ) + fs.StringVar( + &cfg.Annotations.ConfigmapAuto, "configmap-auto-annotation", cfg.Annotations.ConfigmapAuto, + "Annotation to detect changes in configmaps", + ) + fs.StringVar( + &cfg.Annotations.SecretAuto, "secret-auto-annotation", cfg.Annotations.SecretAuto, + "Annotation to detect changes in secrets", + ) + fs.StringVar( + &cfg.Annotations.ConfigmapReload, "configmap-annotation", cfg.Annotations.ConfigmapReload, + "Annotation to detect changes in configmaps, specified by name", + ) + fs.StringVar( + &cfg.Annotations.SecretReload, "secret-annotation", cfg.Annotations.SecretReload, + "Annotation to detect changes in secrets, specified by name", + ) + fs.StringVar( + &cfg.Annotations.Search, "auto-search-annotation", cfg.Annotations.Search, + "Annotation to detect changes in configmaps or secrets tagged with special match annotation", + ) + fs.StringVar( + &cfg.Annotations.Match, "search-match-annotation", cfg.Annotations.Match, + "Annotation to mark secrets or configmaps to match the search", + ) + fs.StringVar( + &cfg.Annotations.PausePeriod, "pause-deployment-annotation", cfg.Annotations.PausePeriod, + "Annotation to define the time period to pause a deployment after a configmap/secret change", + ) + fs.StringVar( + &cfg.Annotations.PausedAt, "pause-deployment-time-annotation", cfg.Annotations.PausedAt, + "Annotation to indicate when a deployment was paused by Reloader", + ) // Watched namespace (for single-namespace mode) - fs.StringVar(&cfg.WatchedNamespace, "watch-namespace", cfg.WatchedNamespace, - "Namespace to watch (empty for all namespaces)") + fs.StringVar( + &cfg.WatchedNamespace, "watch-namespace", cfg.WatchedNamespace, + "Namespace to watch (empty for all namespaces)", + ) } // ApplyFlags applies flag values that need post-processing. diff --git a/internal/pkg/controller/namespace_reconciler.go b/internal/pkg/controller/namespace_reconciler.go index ab25fff0..8cc03d63 100644 --- a/internal/pkg/controller/namespace_reconciler.go +++ b/internal/pkg/controller/namespace_reconciler.go @@ -6,6 +6,7 @@ import ( "github.com/go-logr/logr" "github.com/stakater/Reloader/internal/pkg/config" + "github.com/stakater/Reloader/internal/pkg/reload" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" ctrl "sigs.k8s.io/controller-runtime" @@ -124,7 +125,7 @@ func (r *NamespaceReconciler) matchesSelectors(ns *corev1.Namespace) bool { } for _, selector := range r.Config.NamespaceSelectors { - if selector.Matches(nsLabelsSet(nsLabels)) { + if selector.Matches(reload.LabelsSet(nsLabels)) { return true } } @@ -132,18 +133,6 @@ func (r *NamespaceReconciler) matchesSelectors(ns *corev1.Namespace) bool { return false } -// nsLabelsSet implements labels.Labels interface for a map. -type nsLabelsSet map[string]string - -func (ls nsLabelsSet) Has(key string) bool { - _, ok := ls[key] - return ok -} - -func (ls nsLabelsSet) Get(key string) string { - return ls[key] -} - // SetupWithManager sets up the controller with the Manager. func (r *NamespaceReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). diff --git a/internal/pkg/metrics/prometheus.go b/internal/pkg/metrics/prometheus.go index f78ef03d..87f9148b 100644 --- a/internal/pkg/metrics/prometheus.go +++ b/internal/pkg/metrics/prometheus.go @@ -48,11 +48,10 @@ func NewCollectors() Collectors { }, ) - //set 0 as default value reloaded.With(prometheus.Labels{"success": "true"}).Add(0) reloaded.With(prometheus.Labels{"success": "false"}).Add(0) - reloaded_by_namespace := prometheus.NewCounterVec( + reloadedByNamespace := prometheus.NewCounterVec( prometheus.CounterOpts{ Namespace: "reloader", Name: "reload_executed_total_by_namespace", @@ -65,7 +64,7 @@ func NewCollectors() Collectors { ) return Collectors{ Reloaded: reloaded, - ReloadedByNamespace: reloaded_by_namespace, + ReloadedByNamespace: reloadedByNamespace, countByNamespace: os.Getenv("METRICS_COUNT_BY_NAMESPACE") == "enabled", } } diff --git a/internal/pkg/reload/predicate.go b/internal/pkg/reload/predicate.go index f24c60a7..3582dd54 100644 --- a/internal/pkg/reload/predicate.go +++ b/internal/pkg/reload/predicate.go @@ -102,7 +102,7 @@ func LabelSelectorPredicate(cfg *config.Config) predicate.Predicate { // Check if any selector matches for _, selector := range cfg.ResourceSelectors { - if selector.Matches(labelsSet(labels)) { + if selector.Matches(LabelsSet(labels)) { return true } } @@ -111,15 +111,18 @@ func LabelSelectorPredicate(cfg *config.Config) predicate.Predicate { }) } -// labelsSet implements labels.Labels interface for a map. -type labelsSet map[string]string +// LabelsSet implements the k8s.io/apimachinery/pkg/labels.Labels interface +// for a map[string]string. This allows using label maps with label selectors. +type LabelsSet map[string]string -func (ls labelsSet) Has(key string) bool { +// Has returns whether the provided label key exists in the set. +func (ls LabelsSet) Has(key string) bool { _, ok := ls[key] return ok } -func (ls labelsSet) Get(key string) string { +// Get returns the value for the provided label key. +func (ls LabelsSet) Get(key string) string { return ls[key] }