mirror of
https://github.com/stakater/Reloader.git
synced 2026-08-27 14:37:17 +00:00
added support for multiple watch namespaces
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user