From f28ad5af2330621ac85e1ddf05c526c4147f2340 Mon Sep 17 00:00:00 2001 From: katsew Date: Sat, 1 May 2021 12:42:29 +0900 Subject: [PATCH] Fix defaulting and overriding kubeContext (#1814) Ref #1810 * fix defaulting and overriding kubeContext * make defaulting kubeContext side-effect free * checkDuplicates should check releases with overriden values --- pkg/app/app.go | 2 +- pkg/app/app_test.go | 8 ++++---- pkg/app/desired_state_file_loader.go | 6 ++++++ pkg/state/state.go | 29 ++++++++++++++-------------- pkg/state/state_exec_tmpl.go | 7 ++++++- pkg/state/types.go | 4 ++++ 6 files changed, 36 insertions(+), 20 deletions(-) diff --git a/pkg/app/app.go b/pkg/app/app.go index 1e1fc187..d305f627 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -970,7 +970,7 @@ func processFilteredReleases(st *state.HelmState, helm helmexec.Interface, conve } } - if err := checkDuplicates(helm, st, st.Releases); err != nil { + if err := checkDuplicates(helm, st, st.GetReleasesWithOverrides()); err != nil { return false, []error{err} } diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index 71749b84..42242319 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -500,7 +500,7 @@ releases: {label: "name", expectedCount: 0, expectErr: true, errMsg: "in ./helmfile.yaml: in .helmfiles[0]: in /path/to/helmfile.d/a1.yaml: Malformed label: name. Expected label in form k=v or k!=v"}, // See https://github.com/roboll/helmfile/issues/193 {label: "duplicatedNs=yes", expectedCount: 0, expectErr: true, errMsg: "in ./helmfile.yaml: in .helmfiles[2]: in /path/to/helmfile.d/b.yaml: duplicate release \"foo\" found in namespace \"zoo\" in kubecontext \"default\": there were 2 releases named \"foo\" matching specified selector"}, - {label: "duplicatedCtx=yes", expectedCount: 0, expectErr: true, errMsg: "in ./helmfile.yaml: in .helmfiles[2]: in /path/to/helmfile.d/b.yaml: duplicate release \"foo\" found in namespace \"zoo\" in kubecontext \"baz\": there were 2 releases named \"foo\" matching specified selector"}, + {label: "duplicatedCtx=yes", expectedCount: 0, expectErr: true, errMsg: "in ./helmfile.yaml: in .helmfiles[2]: in /path/to/helmfile.d/b.yaml: duplicate release \"foo\" found in namespace \"zoo\" in kubecontext \"default\": there were 2 releases named \"foo\" matching specified selector"}, {label: "duplicatedOK=yes", expectedCount: 2, expectErr: false}, } @@ -1319,7 +1319,7 @@ releases: SetFilter(true), ) - expected := "in ./helmfile.yaml: duplicate release \"foo\" found: there were 2 releases named \"foo\" matching specified selector" + expected := "in ./helmfile.yaml: duplicate release \"foo\" found in kubecontext \"default\": there were 2 releases named \"foo\" matching specified selector" if err == nil { t.Errorf("error expected but not happened") } else if err.Error() != expected { @@ -1453,7 +1453,7 @@ releases: SetFilter(true), ) - expected := "in ./helmfile.yaml: duplicate release \"foo\" found in namespace \"foo\": there were 2 releases named \"foo\" matching specified selector" + expected := "in ./helmfile.yaml: duplicate release \"foo\" found in namespace \"foo\" in kubecontext \"default\": there were 2 releases named \"foo\" matching specified selector" if err == nil { t.Errorf("error expected but not happened") } else if err.Error() != expected { @@ -1500,7 +1500,7 @@ releases: SetFilter(true), ) - expected := "in ./helmfile.yaml: duplicate release \"foo\" found in namespace \"foo\" in kubecontext \"foo\": there were 2 releases named \"foo\" matching specified selector" + expected := "in ./helmfile.yaml: duplicate release \"foo\" found in namespace \"foo\" in kubecontext \"default\": there were 2 releases named \"foo\" matching specified selector" if err == nil { t.Errorf("error expected but not happened") } else if err.Error() != expected { diff --git a/pkg/app/desired_state_file_loader.go b/pkg/app/desired_state_file_loader.go index 14445d4a..9e5bc485 100644 --- a/pkg/app/desired_state_file_loader.go +++ b/pkg/app/desired_state_file_loader.go @@ -73,6 +73,12 @@ func (ld *desiredStateLoader) Load(f string, opts LoadOpts) (*state.HelmState, e } if ld.overrideKubeContext != "" { + if st.OverrideKubeContext != "" { + return nil, errors.New("err: Cannot use option --kube-context and set attribute kubeContext.") + } + st.OverrideKubeContext = ld.overrideKubeContext + // HelmDefaults.KubeContext is also overriden in here + // to set default release value properly. st.HelmDefaults.KubeContext = ld.overrideKubeContext } diff --git a/pkg/state/state.go b/pkg/state/state.go index a5010200..8c6515fb 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -48,18 +48,19 @@ type ReleaseSetSpec struct { Environments map[string]EnvironmentSpec `yaml:"environments,omitempty"` - Bases []string `yaml:"bases,omitempty"` - HelmDefaults HelmSpec `yaml:"helmDefaults,omitempty"` - Helmfiles []SubHelmfileSpec `yaml:"helmfiles,omitempty"` - DeprecatedContext string `yaml:"context,omitempty"` - DeprecatedReleases []ReleaseSpec `yaml:"charts,omitempty"` - OverrideNamespace string `yaml:"namespace,omitempty"` - OverrideChart string `yaml:"chart,omitempty"` - Repositories []RepositorySpec `yaml:"repositories,omitempty"` - CommonLabels map[string]string `yaml:"commonLabels,omitempty"` - Releases []ReleaseSpec `yaml:"releases,omitempty"` - Selectors []string `yaml:"-"` - ApiVersions []string `yaml:"apiVersions,omitempty"` + Bases []string `yaml:"bases,omitempty"` + HelmDefaults HelmSpec `yaml:"helmDefaults,omitempty"` + Helmfiles []SubHelmfileSpec `yaml:"helmfiles,omitempty"` + DeprecatedContext string `yaml:"context,omitempty"` + DeprecatedReleases []ReleaseSpec `yaml:"charts,omitempty"` + OverrideKubeContext string `yaml:"kubeContext,omitempty"` + OverrideNamespace string `yaml:"namespace,omitempty"` + OverrideChart string `yaml:"chart,omitempty"` + Repositories []RepositorySpec `yaml:"repositories,omitempty"` + CommonLabels map[string]string `yaml:"commonLabels,omitempty"` + Releases []ReleaseSpec `yaml:"releases,omitempty"` + Selectors []string `yaml:"-"` + ApiVersions []string `yaml:"apiVersions,omitempty"` // Hooks is a list of extension points paired with operations, that are executed in specific points of the lifecycle of releases defined in helmfile Hooks []event.Hook `yaml:"hooks,omitempty"` @@ -332,8 +333,8 @@ const MissingFileHandlerWarn = "Warn" const MissingFileHandlerDebug = "Debug" func (st *HelmState) ApplyOverrides(spec *ReleaseSpec) { - if spec.KubeContext == "" { - spec.KubeContext = st.HelmDefaults.KubeContext + if st.OverrideKubeContext != "" { + spec.KubeContext = st.OverrideKubeContext } if st.OverrideNamespace != "" { spec.Namespace = st.OverrideNamespace diff --git a/pkg/state/state_exec_tmpl.go b/pkg/state/state_exec_tmpl.go index 3e12cd6d..5674d108 100644 --- a/pkg/state/state_exec_tmpl.go +++ b/pkg/state/state_exec_tmpl.go @@ -17,8 +17,13 @@ func (st *HelmState) Values() map[string]interface{} { } func (st *HelmState) createReleaseTemplateData(release *ReleaseSpec, vals map[string]interface{}) releaseTemplateData { + kubeContext := release.KubeContext + if kubeContext == "" { + kubeContext = st.HelmDefaults.KubeContext + } tmplData := releaseTemplateData{ Environment: st.Env, + KubeContext: st.OverrideKubeContext, Namespace: st.OverrideNamespace, Chart: st.OverrideChart, Values: vals, @@ -27,7 +32,7 @@ func (st *HelmState) createReleaseTemplateData(release *ReleaseSpec, vals map[st Chart: release.Chart, Namespace: release.Namespace, Labels: release.Labels, - KubeContext: release.KubeContext, + KubeContext: kubeContext, }, } tmplData.StateValues = &tmplData.Values diff --git a/pkg/state/types.go b/pkg/state/types.go index 674a5eee..5105378d 100644 --- a/pkg/state/types.go +++ b/pkg/state/types.go @@ -30,6 +30,10 @@ type releaseTemplateData struct { // Values is accessible as `.Values` and it contains default state values overrode by environment values and override values. Values map[string]interface{} StateValues *map[string]interface{} + // KubeContext is HelmState.OverrideKubeContext. + // You should better use Release.KubeContext as it might work as you'd expect even if HelmState.OverrideKubeContext is not set. + // See releaseTemplateDataRelease.KubeContext for more information. + KubeContext string // Namespace is HelmState.OverrideNamespace. // You should better use Release.Namespace as it might work as you'd expect even if OverrideNamespace is not set. // See releaseTemplateDataRelease.Namespace for more information.