diff --git a/cmd/root.go b/cmd/root.go index dd201728..f94cd9be 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -129,6 +129,7 @@ func setGlobalOptionsForRootCmd(fs *pflag.FlagSet, globalOptions *config.GlobalO fs.StringArrayVar(&globalOptions.StateValuesSetString, "state-values-set-string", nil, "set state STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template).") fs.StringArrayVar(&globalOptions.StateValuesFile, "state-values-file", nil, "specify state values in a YAML file. Used to override .Values within the helmfile template (not values template).") fs.BoolVar(&globalOptions.SkipDeps, "skip-deps", false, `skip running "helm repo update" and "helm dependency build"`) + fs.BoolVar(&globalOptions.SkipRefresh, "skip-refresh", false, `skip running "helm repo update"`) fs.BoolVar(&globalOptions.StripArgsValuesOnExitError, "strip-args-values-on-exit-error", true, `Strip the potential secret values of the helm command args contained in a helmfile error message`) fs.BoolVar(&globalOptions.DisableForceUpdate, "disable-force-update", false, `do not force helm repos to update when executing "helm repo add"`) fs.BoolVarP(&globalOptions.Quiet, "quiet", "q", false, "Silence output. Equivalent to log-level warn") diff --git a/cmd/template.go b/cmd/template.go index dfd27c38..8d85f903 100644 --- a/cmd/template.go +++ b/cmd/template.go @@ -40,6 +40,7 @@ func NewTemplateCmd(globalCfg *config.GlobalImpl) *cobra.Command { f.BoolVar(&templateOptions.Validate, "validate", false, "validate your manifests against the Kubernetes cluster you are currently pointing at. Note that this requires access to a Kubernetes cluster to obtain information necessary for validating, like the template of available API versions") f.BoolVar(&templateOptions.IncludeCRDs, "include-crds", false, "include CRDs in the templated output") f.BoolVar(&templateOptions.SkipTests, "skip-tests", false, "skip tests from templated output") + f.BoolVar(&templateOptions.SkipNeeds, "skip-needs", true, `do not automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided. Defaults to true when --include-needs or --include-transitive-needs is not provided`) f.BoolVar(&templateOptions.IncludeNeeds, "include-needs", false, `automatically include releases from the target release's "needs" when --selector/-l flag is provided. Does nothing when --selector/-l flag is not provided`) f.BoolVar(&templateOptions.IncludeTransitiveNeeds, "include-transitive-needs", false, `like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`) diff --git a/pkg/app/app.go b/pkg/app/app.go index 87b44351..6f60ea66 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -175,7 +175,7 @@ func (a *App) Diff(c DiffConfigProvider) error { includeCRDs := !c.SkipCRDs() prepErr := run.withPreparedCharts("diff", state.ChartPrepareOptions{ - SkipRepos: c.SkipDeps(), + SkipRepos: c.SkipRefresh() || c.SkipDeps(), SkipDeps: c.SkipDeps(), IncludeCRDs: &includeCRDs, Validate: c.Validate(), @@ -240,7 +240,7 @@ func (a *App) Template(c TemplateConfigProvider) error { run.helm.SetEnableLiveOutput(false) prepErr := run.withPreparedCharts("template", state.ChartPrepareOptions{ - SkipRepos: c.SkipDeps(), + SkipRepos: c.SkipRefresh() || c.SkipDeps(), SkipDeps: c.SkipDeps(), IncludeCRDs: &includeCRDs, SkipCleanup: c.SkipCleanup(), @@ -264,7 +264,7 @@ func (a *App) Template(c TemplateConfigProvider) error { func (a *App) WriteValues(c WriteValuesConfigProvider) error { return a.ForEachState(func(run *Run) (ok bool, errs []error) { prepErr := run.withPreparedCharts("write-values", state.ChartPrepareOptions{ - SkipRepos: c.SkipDeps(), + SkipRepos: c.SkipRefresh() || c.SkipDeps(), SkipDeps: c.SkipDeps(), SkipCleanup: c.SkipCleanup(), Concurrency: c.Concurrency(), @@ -315,7 +315,7 @@ func (a *App) Lint(c LintConfigProvider) error { // `helm lint` on helm v2 and v3 does not support remote charts, that we need to set `forceDownload=true` here prepErr := run.withPreparedCharts("lint", state.ChartPrepareOptions{ ForceDownload: true, - SkipRepos: c.SkipDeps(), + SkipRepos: c.SkipRefresh() || c.SkipDeps(), SkipDeps: c.SkipDeps(), SkipCleanup: c.SkipCleanup(), Concurrency: c.Concurrency(), @@ -350,7 +350,7 @@ func (a *App) Fetch(c FetchConfigProvider) error { return a.ForEachState(func(run *Run) (ok bool, errs []error) { prepErr := run.withPreparedCharts("pull", state.ChartPrepareOptions{ ForceDownload: true, - SkipRepos: c.SkipDeps(), + SkipRepos: c.SkipRefresh() || c.SkipDeps(), SkipDeps: c.SkipDeps(), OutputDir: c.OutputDir(), OutputDirTemplate: c.OutputDirTemplate(), @@ -371,7 +371,7 @@ func (a *App) Sync(c SyncConfigProvider) error { includeCRDs := !c.SkipCRDs() prepErr := run.withPreparedCharts("sync", state.ChartPrepareOptions{ - SkipRepos: c.SkipDeps(), + SkipRepos: c.SkipRefresh() || c.SkipDeps(), SkipDeps: c.SkipDeps(), Wait: c.Wait(), WaitForJobs: c.WaitForJobs(), @@ -404,7 +404,7 @@ func (a *App) Apply(c ApplyConfigProvider) error { includeCRDs := !c.SkipCRDs() prepErr := run.withPreparedCharts("apply", state.ChartPrepareOptions{ - SkipRepos: c.SkipDeps(), + SkipRepos: c.SkipRefresh() || c.SkipDeps(), SkipDeps: c.SkipDeps(), Wait: c.Wait(), WaitForJobs: c.WaitForJobs(), @@ -466,7 +466,7 @@ func (a *App) Delete(c DeleteConfigProvider) error { return a.ForEachState(func(run *Run) (ok bool, errs []error) { if !c.SkipCharts() { err := run.withPreparedCharts("delete", state.ChartPrepareOptions{ - SkipRepos: c.SkipDeps(), + SkipRepos: c.SkipRefresh() || c.SkipDeps(), SkipDeps: c.SkipDeps(), Concurrency: c.Concurrency(), DeleteWait: c.DeleteWait(), @@ -489,7 +489,7 @@ func (a *App) Destroy(c DestroyConfigProvider) error { return a.ForEachState(func(run *Run) (ok bool, errs []error) { if !c.SkipCharts() { err := run.withPreparedCharts("destroy", state.ChartPrepareOptions{ - SkipRepos: c.SkipDeps(), + SkipRepos: c.SkipRefresh() || c.SkipDeps(), SkipDeps: c.SkipDeps(), Concurrency: c.Concurrency(), DeleteWait: c.DeleteWait(), @@ -516,7 +516,7 @@ func (a *App) Test(c TestConfigProvider) error { } err := run.withPreparedCharts("test", state.ChartPrepareOptions{ - SkipRepos: c.SkipDeps(), + SkipRepos: c.SkipRefresh() || c.SkipDeps(), SkipDeps: c.SkipDeps(), Concurrency: c.Concurrency(), }, func() { diff --git a/pkg/app/app_test.go b/pkg/app/app_test.go index 50770c2c..d84c8049 100644 --- a/pkg/app/app_test.go +++ b/pkg/app/app_test.go @@ -2092,6 +2092,7 @@ type configImpl struct { skipCleanup bool skipCRDs bool skipDeps bool + skipRefresh bool skipTests bool skipNeeds bool @@ -2133,6 +2134,10 @@ func (c configImpl) SkipDeps() bool { return c.skipDeps } +func (c configImpl) SkipRefresh() bool { + return c.skipRefresh +} + func (c configImpl) SkipNeeds() bool { return c.skipNeeds } @@ -2206,6 +2211,7 @@ type applyConfig struct { skipCleanup bool skipCRDs bool skipDeps bool + skipRefresh bool skipNeeds bool includeNeeds bool includeTransitiveNeeds bool @@ -2282,6 +2288,10 @@ func (a applyConfig) SkipDeps() bool { return a.skipDeps } +func (a applyConfig) SkipRefresh() bool { + return a.skipRefresh +} + func (a applyConfig) SkipNeeds() bool { return a.skipNeeds } diff --git a/pkg/app/config.go b/pkg/app/config.go index 9d9b377b..ba1b5173 100644 --- a/pkg/app/config.go +++ b/pkg/app/config.go @@ -10,6 +10,7 @@ type ConfigProvider interface { StripArgsValuesOnExitError() bool DisableForceUpdate() bool SkipDeps() bool + SkipRefresh() bool FileOrDir() string KubeContext() string @@ -58,6 +59,7 @@ type ApplyConfigProvider interface { Set() []string SkipCRDs() bool SkipDeps() bool + SkipRefresh() bool Wait() bool WaitForJobs() bool @@ -106,6 +108,7 @@ type SyncConfigProvider interface { Set() []string SkipCRDs() bool SkipDeps() bool + SkipRefresh() bool Wait() bool WaitForJobs() bool SyncArgs() string @@ -134,6 +137,7 @@ type DiffConfigProvider interface { Validate() bool SkipCRDs() bool SkipDeps() bool + SkipRefresh() bool IncludeTests() bool @@ -165,6 +169,7 @@ type DeleteConfigProvider interface { Purge() bool SkipDeps() bool + SkipRefresh() bool SkipCharts() bool DeleteWait() bool DeleteTimeout() int @@ -179,6 +184,7 @@ type DestroyConfigProvider interface { Cascade() string SkipDeps() bool + SkipRefresh() bool SkipCharts() bool DeleteWait() bool DeleteTimeout() int @@ -192,6 +198,7 @@ type TestConfigProvider interface { Args() string SkipDeps() bool + SkipRefresh() bool Timeout() int Cleanup() bool Logs() bool @@ -205,6 +212,7 @@ type LintConfigProvider interface { Values() []string Set() []string SkipDeps() bool + SkipRefresh() bool SkipCleanup() bool DAGConfig @@ -214,6 +222,7 @@ type LintConfigProvider interface { type FetchConfigProvider interface { SkipDeps() bool + SkipRefresh() bool OutputDir() string OutputDirTemplate() string @@ -230,6 +239,7 @@ type TemplateConfigProvider interface { OutputDirTemplate() string Validate() bool SkipDeps() bool + SkipRefresh() bool SkipCleanup() bool SkipTests() bool OutputDir() string @@ -253,6 +263,7 @@ type WriteValuesConfigProvider interface { Set() []string OutputFileTemplate() string SkipDeps() bool + SkipRefresh() bool SkipCleanup() bool IncludeTransitiveNeeds() bool diff --git a/pkg/app/destroy_test.go b/pkg/app/destroy_test.go index 4f815469..4d578851 100644 --- a/pkg/app/destroy_test.go +++ b/pkg/app/destroy_test.go @@ -38,6 +38,7 @@ type destroyConfig struct { concurrency int interactive bool skipDeps bool + skipRefresh bool logger *zap.SugaredLogger includeTransitiveNeeds bool skipCharts bool @@ -73,6 +74,10 @@ func (d destroyConfig) SkipDeps() bool { return d.skipDeps } +func (d destroyConfig) SkipRefresh() bool { + return d.skipRefresh +} + func (d destroyConfig) IncludeTransitiveNeeds() bool { return d.includeTransitiveNeeds } diff --git a/pkg/app/diff_test.go b/pkg/app/diff_test.go index f33c04a6..08ec45cd 100644 --- a/pkg/app/diff_test.go +++ b/pkg/app/diff_test.go @@ -24,6 +24,7 @@ type diffConfig struct { validate bool skipCRDs bool skipDeps bool + skipRefresh bool includeTests bool skipNeeds bool includeNeeds bool @@ -74,6 +75,10 @@ func (a diffConfig) SkipDeps() bool { return a.skipDeps } +func (a diffConfig) SkipRefresh() bool { + return a.skipRefresh +} + func (a diffConfig) IncludeTests() bool { return a.includeTests } diff --git a/pkg/config/global.go b/pkg/config/global.go index 23066711..d095e618 100644 --- a/pkg/config/global.go +++ b/pkg/config/global.go @@ -32,6 +32,8 @@ type GlobalOptions struct { StateValuesFile []string // SkipDeps is true if the running "helm repo update" and "helm dependency build" should be skipped SkipDeps bool + // SkipRefresh is true if the running "helm repo update" should be skipped + SkipRefresh bool // StripArgsValuesOnExitError is true if the ARGS output on exit error should be suppressed StripArgsValuesOnExitError bool // DisableForceUpdate is true if force updating repos is not desirable when executing "helm repo add" @@ -174,6 +176,11 @@ func (g *GlobalImpl) SkipDeps() bool { return g.GlobalOptions.SkipDeps } +// SkipRefresh return if running "helm repo update" +func (g *GlobalImpl) SkipRefresh() bool { + return g.GlobalOptions.SkipRefresh +} + // StripArgsValuesOnExitError return if the ARGS output on exit error should be suppressed func (g *GlobalImpl) StripArgsValuesOnExitError() bool { return g.GlobalOptions.StripArgsValuesOnExitError diff --git a/pkg/state/state.go b/pkg/state/state.go index 5cb8de3d..e0bab050 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -184,6 +184,8 @@ type HelmSpec struct { // This is relevant only when your release uses a local chart or a directory containing K8s manifests or a Kustomization // as a Helm chart. SkipDeps bool `yaml:"skipDeps"` + // SkipRefresh disables running `helm dependency up` + SkipRefresh bool `yaml:"skipRefresh"` // on helm upgrade/diff, reuse values currently set in the release and merge them with the ones defined within helmfile ReuseValues bool `yaml:"reuseValues"` // Propagate '--post-renderer' to helmv3 template and helm install @@ -374,6 +376,9 @@ type ReleaseSpec struct { // as a Helm chart. SkipDeps *bool `yaml:"skipDeps,omitempty"` + // SkipRefresh disables running `helm dependency up` + SkipRefresh *bool `yaml:"skipRefresh,omitempty"` + // Propagate '--post-renderer' to helmv3 template and helm install PostRenderer *string `yaml:"postRenderer,omitempty"` @@ -1099,6 +1104,7 @@ type ChartPrepareOptions struct { ForceDownload bool SkipRepos bool SkipDeps bool + SkipRefresh bool SkipResolve bool SkipCleanup bool // Validate is a helm-3-only option. When it is set to true, it configures chartify to pass --validate to helm-template run by it. diff --git a/pkg/state/temp_test.go b/pkg/state/temp_test.go index 258033e3..975456ef 100644 --- a/pkg/state/temp_test.go +++ b/pkg/state/temp_test.go @@ -38,39 +38,39 @@ func TestGenerateID(t *testing.T) { run(testcase{ subject: "baseline", release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, - want: "foo-values-867bdd68d", + want: "foo-values-d566bffd8", }) run(testcase{ subject: "different bytes content", release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, data: []byte(`{"k":"v"}`), - want: "foo-values-55d7dc5f87", + want: "foo-values-65b557f8c5", }) run(testcase{ subject: "different map content", release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, data: map[string]any{"k": "v"}, - want: "foo-values-58bdcf44f7", + want: "foo-values-74d5cd8cc7", }) run(testcase{ subject: "different chart", release: ReleaseSpec{Name: "foo", Chart: "stable/envoy"}, - want: "foo-values-67dcddd85", + want: "foo-values-85db6bbb4c", }) run(testcase{ subject: "different name", release: ReleaseSpec{Name: "bar", Chart: "incubator/raw"}, - want: "bar-values-6dd4989f97", + want: "bar-values-85cf974b7", }) run(testcase{ subject: "specific ns", release: ReleaseSpec{Name: "foo", Chart: "incubator/raw", Namespace: "myns"}, - want: "myns-foo-values-755d4487dc", + want: "myns-foo-values-574676fbb9", }) for id, n := range ids {