diff --git a/deployments/kubernetes/chart/reloader/templates/deployment.yaml b/deployments/kubernetes/chart/reloader/templates/deployment.yaml index 2aff3e5a0..31ab80895 100644 --- a/deployments/kubernetes/chart/reloader/templates/deployment.yaml +++ b/deployments/kubernetes/chart/reloader/templates/deployment.yaml @@ -225,7 +225,7 @@ spec: - "--resources-to-ignore=secrets" {{- end }} {{- if .Values.reloader.ignoreConfigMaps }} - - "--resources-to-ignore=configMaps" + - "--resources-to-ignore=configmaps" {{- end }} {{- if and (.Values.reloader.ignoreJobs) (.Values.reloader.ignoreCronJobs) }} - "--ignored-workload-types=jobs,cronjobs" diff --git a/internal/pkg/util/util.go b/internal/pkg/util/util.go index 2b961f0d3..365d35c39 100644 --- a/internal/pkg/util/util.go +++ b/internal/pkg/util/util.go @@ -94,7 +94,7 @@ func ConfigureReloaderFlags(cmd *cobra.Command) { cmd.PersistentFlags().StringVar(&options.LogFormat, "log-format", "", "Log format to use (empty string for text, or JSON)") cmd.PersistentFlags().StringVar(&options.LogLevel, "log-level", "info", "Log level to use (trace, debug, info, warning, error, fatal and panic)") cmd.PersistentFlags().StringVar(&options.WebhookUrl, "webhook-url", "", "webhook to trigger instead of performing a reload") - cmd.PersistentFlags().StringSliceVar(&options.ResourcesToIgnore, "resources-to-ignore", options.ResourcesToIgnore, "list of resources to ignore (valid options 'configMaps' or 'secrets')") + cmd.PersistentFlags().StringSliceVar(&options.ResourcesToIgnore, "resources-to-ignore", options.ResourcesToIgnore, "list of resources to ignore (valid options 'configmaps' or 'secrets')") cmd.PersistentFlags().StringSliceVar(&options.WorkloadTypesToIgnore, "ignored-workload-types", options.WorkloadTypesToIgnore, "list of workload types to ignore (valid options: 'jobs', 'cronjobs', or both)") cmd.PersistentFlags().StringSliceVar(&options.NamespacesToIgnore, "namespaces-to-ignore", options.NamespacesToIgnore, "list of namespaces to ignore") cmd.PersistentFlags().StringSliceVar(&options.NamespaceSelectors, "namespace-selector", options.NamespaceSelectors, "list of key:value labels to filter on for namespaces") @@ -114,17 +114,26 @@ func GetIgnoredResourcesList() (List, error) { ignoredResourcesList := options.ResourcesToIgnore // getStringSliceFromFlags(cmd, "resources-to-ignore") + // Normalize to the canonical lowercase keys used in kube.ResourceMap so the + // comparison is case-insensitive (e.g. "configMaps", "ConfigMaps", "sEcrets" + // all map to their canonical lowercase form). + normalized := make(List, 0, len(ignoredResourcesList)) for _, v := range ignoredResourcesList { - if v != "configMaps" && v != "secrets" { - return nil, fmt.Errorf("'resources-to-ignore' only accepts 'configMaps' or 'secrets', not '%s'", v) + switch strings.ToLower(v) { + case "configmaps": + normalized = append(normalized, "configmaps") + case "secrets": + normalized = append(normalized, "secrets") + default: + return nil, fmt.Errorf("'resources-to-ignore' only accepts 'configmaps' or 'secrets', not '%s'", v) } } - if len(ignoredResourcesList) > 1 { - return nil, errors.New("'resources-to-ignore' only accepts 'configMaps' or 'secrets', not both") + if len(normalized) > 1 { + return nil, errors.New("'resources-to-ignore' only accepts 'configmaps' or 'secrets', not both") } - return ignoredResourcesList, nil + return normalized, nil } func GetIgnoredWorkloadTypesList() (List, error) { diff --git a/internal/pkg/util/util_test.go b/internal/pkg/util/util_test.go index 338f329f3..31c82c416 100644 --- a/internal/pkg/util/util_test.go +++ b/internal/pkg/util/util_test.go @@ -136,6 +136,97 @@ func TestGetIgnoredWorkloadTypesList(t *testing.T) { } } +func TestGetIgnoredResourcesList(t *testing.T) { + // Save original state + originalResources := options.ResourcesToIgnore + defer func() { + options.ResourcesToIgnore = originalResources + }() + + tests := []struct { + name string + resources []string + expectError bool + expected []string + }{ + { + name: "Lowercase configmaps (canonical) normalizes to configmaps", + resources: []string{"configmaps"}, + expectError: false, + expected: []string{"configmaps"}, + }, + { + name: "Legacy camelCase configMaps normalizes to configmaps", + resources: []string{"configMaps"}, + expectError: false, + expected: []string{"configmaps"}, + }, + { + name: "Mixed-case ConfigMaps normalizes to configmaps", + resources: []string{"ConfigMaps"}, + expectError: false, + expected: []string{"configmaps"}, + }, + { + name: "secrets", + resources: []string{"secrets"}, + expectError: false, + expected: []string{"secrets"}, + }, + { + name: "Mixed-case sEcrets normalizes to secrets", + resources: []string{"sEcrets"}, + expectError: false, + expected: []string{"secrets"}, + }, + { + name: "Empty list", + resources: []string{}, + expectError: false, + expected: []string{}, + }, + { + name: "Invalid resource", + resources: []string{"deployments"}, + expectError: true, + expected: nil, + }, + { + name: "Both configmaps and secrets rejected", + resources: []string{"configmaps", "secrets"}, + expectError: true, + expected: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + options.ResourcesToIgnore = tt.resources + result, err := GetIgnoredResourcesList() + + if tt.expectError && err == nil { + t.Errorf("Expected error but got none") + } + if !tt.expectError && err != nil { + t.Errorf("Expected no error but got: %v", err) + } + + if !tt.expectError { + if len(result) != len(tt.expected) { + t.Errorf("Expected %v, got %v", tt.expected, result) + return + } + for i, expected := range tt.expected { + if result[i] != expected { + t.Errorf("Expected %v, got %v", tt.expected, result) + break + } + } + } + }) + } +} + func TestListContains(t *testing.T) { tests := []struct { name string