feat: Reset values flag (#602)

Ref https://github.com/helmfile/helmfile/discussions/593

* implemented --reset-values flag overriding .helmDefaults.reuseValues=true
* tests for --reset-values flag
* fixed pkg/app tests
* added tests for both reset & reuse flags given
* added appendValuesControlMode method for --reuse/reset-values flag processing
* updated code comments & docs

Signed-off-by: Karol Ossowski <k@koralsky.pl>
This commit is contained in:
koralsky 2023-01-17 01:34:37 +01:00 committed by GitHub
parent c4eb62388b
commit fc634c9ee3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 122 additions and 15 deletions

View File

@ -63,6 +63,7 @@ func NewApplyCmd(globalCfg *config.GlobalImpl) *cobra.Command {
f.BoolVar(&applyOptions.Wait, "wait", false, `Override helmDefaults.wait setting "helm upgrade --install --wait"`) f.BoolVar(&applyOptions.Wait, "wait", false, `Override helmDefaults.wait setting "helm upgrade --install --wait"`)
f.BoolVar(&applyOptions.WaitForJobs, "wait-for-jobs", false, `Override helmDefaults.waitForJobs setting "helm upgrade --install --wait-for-jobs"`) f.BoolVar(&applyOptions.WaitForJobs, "wait-for-jobs", false, `Override helmDefaults.waitForJobs setting "helm upgrade --install --wait-for-jobs"`)
f.BoolVar(&applyOptions.ReuseValues, "reuse-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reuse-values"`) f.BoolVar(&applyOptions.ReuseValues, "reuse-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reuse-values"`)
f.BoolVar(&applyOptions.ResetValues, "reset-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reset-values"`)
f.StringVar(&applyOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`) f.StringVar(&applyOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`)
return cmd return cmd

View File

@ -50,6 +50,7 @@ func NewDiffCmd(globalCfg *config.GlobalImpl) *cobra.Command {
f.BoolVar(&diffOptions.SuppressSecrets, "suppress-secrets", false, "suppress secrets in the output. highly recommended to specify on CI/CD use-cases") f.BoolVar(&diffOptions.SuppressSecrets, "suppress-secrets", false, "suppress secrets in the output. highly recommended to specify on CI/CD use-cases")
f.StringArrayVar(&diffOptions.Suppress, "suppress", nil, "suppress specified Kubernetes objects in the output. Can be provided multiple times. For example: --suppress KeycloakClient --suppress VaultSecret") f.StringArrayVar(&diffOptions.Suppress, "suppress", nil, "suppress specified Kubernetes objects in the output. Can be provided multiple times. For example: --suppress KeycloakClient --suppress VaultSecret")
f.BoolVar(&diffOptions.ReuseValues, "reuse-values", false, `Override helmDefaults.reuseValues "helm diff upgrade --install --reuse-values"`) f.BoolVar(&diffOptions.ReuseValues, "reuse-values", false, `Override helmDefaults.reuseValues "helm diff upgrade --install --reuse-values"`)
f.BoolVar(&diffOptions.ResetValues, "reset-values", false, `Override helmDefaults.reuseValues "helm diff upgrade --install --reset-values"`)
return cmd return cmd
} }

View File

@ -44,6 +44,7 @@ func NewSyncCmd(globalCfg *config.GlobalImpl) *cobra.Command {
f.BoolVar(&syncOptions.Wait, "wait", false, `Override helmDefaults.wait setting "helm upgrade --install --wait"`) f.BoolVar(&syncOptions.Wait, "wait", false, `Override helmDefaults.wait setting "helm upgrade --install --wait"`)
f.BoolVar(&syncOptions.WaitForJobs, "wait-for-jobs", false, `Override helmDefaults.waitForJobs setting "helm upgrade --install --wait-for-jobs"`) f.BoolVar(&syncOptions.WaitForJobs, "wait-for-jobs", false, `Override helmDefaults.waitForJobs setting "helm upgrade --install --wait-for-jobs"`)
f.BoolVar(&syncOptions.ReuseValues, "reuse-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reuse-values"`) f.BoolVar(&syncOptions.ReuseValues, "reuse-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reuse-values"`)
f.BoolVar(&syncOptions.ResetValues, "reset-values", false, `Override helmDefaults.reuseValues "helm upgrade --install --reset-values"`)
f.StringVar(&syncOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`) f.StringVar(&syncOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`)
return cmd return cmd

View File

@ -212,7 +212,8 @@ helmDefaults:
# When set to `true`, skips running `helm dep up` and `helm dep build` on this release's chart. # When set to `true`, skips running `helm dep up` and `helm dep build` on this release's chart.
# Useful when the chart is broken, like seen in https://github.com/roboll/helmfile/issues/1547 # Useful when the chart is broken, like seen in https://github.com/roboll/helmfile/issues/1547
skipDeps: false skipDeps: false
# if set to true, reuses the last release's values and merges them with ones provided in helmfile. # If set to true, reuses the last release's values and merges them with ones provided in helmfile.
# This attribute, can be overriden in CLI with --reset/reuse-values flag of apply/sync/diff subcommands
reuseValues: false reuseValues: false
# propagate `--post-renderer` to helmv3 template and helm install # propagate `--post-renderer` to helmv3 template and helm install
postRenderer: "path/to/postRenderer" postRenderer: "path/to/postRenderer"

View File

@ -1317,6 +1317,7 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, bool, []error) {
SkipCleanup: c.RetainValuesFiles() || c.SkipCleanup(), SkipCleanup: c.RetainValuesFiles() || c.SkipCleanup(),
SkipDiffOnInstall: c.SkipDiffOnInstall(), SkipDiffOnInstall: c.SkipDiffOnInstall(),
ReuseValues: c.ReuseValues(), ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
} }
infoMsg, releasesToBeUpdated, releasesToBeDeleted, errs := r.diff(false, detailedExitCode, c, diffOpts) infoMsg, releasesToBeUpdated, releasesToBeDeleted, errs := r.diff(false, detailedExitCode, c, diffOpts)
@ -1428,6 +1429,7 @@ Do you really want to apply?
Wait: c.Wait(), Wait: c.Wait(),
WaitForJobs: c.WaitForJobs(), WaitForJobs: c.WaitForJobs(),
ReuseValues: c.ReuseValues(), ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
} }
return subst.SyncReleases(&affectedReleases, helm, c.Values(), c.Concurrency(), syncOpts) return subst.SyncReleases(&affectedReleases, helm, c.Values(), c.Concurrency(), syncOpts)
})) }))
@ -1549,6 +1551,7 @@ func (a *App) diff(r *Run, c DiffConfigProvider) (*string, bool, bool, []error)
Set: c.Set(), Set: c.Set(),
SkipDiffOnInstall: c.SkipDiffOnInstall(), SkipDiffOnInstall: c.SkipDiffOnInstall(),
ReuseValues: c.ReuseValues(), ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
} }
filtered := &Run{ filtered := &Run{
@ -1814,6 +1817,7 @@ Do you really want to sync?
Wait: c.Wait(), Wait: c.Wait(),
WaitForJobs: c.WaitForJobs(), WaitForJobs: c.WaitForJobs(),
ReuseValues: c.ReuseValues(), ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
} }
return subst.SyncReleases(&affectedReleases, helm, c.Values(), c.Concurrency(), opts) return subst.SyncReleases(&affectedReleases, helm, c.Values(), c.Concurrency(), opts)
})) }))

View File

@ -2353,6 +2353,10 @@ func (a applyConfig) ReuseValues() bool {
return a.reuseValues return a.reuseValues
} }
func (a applyConfig) ResetValues() bool {
return !a.reuseValues
}
func (a applyConfig) PostRenderer() string { func (a applyConfig) PostRenderer() string {
return a.postRenderer return a.postRenderer
} }

View File

@ -259,7 +259,8 @@ type InitConfigProvider interface {
Force() bool Force() bool
} }
// when enable reuse-values, reuse the last release's values and merge in any overrides values. // reset/reuse values helm cli flags handling for apply/sync/diff
type valuesControlMode interface { type valuesControlMode interface {
ReuseValues() bool ReuseValues() bool
ResetValues() bool
} }

View File

@ -146,6 +146,10 @@ func (a diffConfig) ReuseValues() bool {
return a.reuseValues return a.reuseValues
} }
func (a diffConfig) ResetValues() bool {
return !a.reuseValues
}
func TestDiff(t *testing.T) { func TestDiff(t *testing.T) {
type flags struct { type flags struct {
skipNeeds bool skipNeeds bool

View File

@ -53,6 +53,8 @@ type ApplyOptions struct {
WaitForJobs bool WaitForJobs bool
// ReuseValues is true if the helm command should reuse the values // ReuseValues is true if the helm command should reuse the values
ReuseValues bool ReuseValues bool
// ResetValues is true if helm command should reset values to charts' default
ResetValues bool
// Propagate '--post-renderer' to helmv3 template and helm install // Propagate '--post-renderer' to helmv3 template and helm install
PostRenderer string PostRenderer string
} }
@ -197,7 +199,14 @@ func (a *ApplyImpl) WaitForJobs() bool {
// ReuseValues returns the ReuseValues. // ReuseValues returns the ReuseValues.
func (a *ApplyImpl) ReuseValues() bool { func (a *ApplyImpl) ReuseValues() bool {
if !a.ResetValues() {
return a.ApplyOptions.ReuseValues return a.ApplyOptions.ReuseValues
}
return false
}
func (a *ApplyImpl) ResetValues() bool {
return a.ApplyOptions.ResetValues
} }
// PostRenderer returns the PostRenderer. // PostRenderer returns the PostRenderer.

View File

@ -38,6 +38,8 @@ type DiffOptions struct {
Output string Output string
// ReuseValues is true if the helm command should reuse the values // ReuseValues is true if the helm command should reuse the values
ReuseValues bool ReuseValues bool
// ResetValues is true if helm command should reset values to charts' default
ResetValues bool
} }
// NewDiffOptions creates a new Apply // NewDiffOptions creates a new Apply
@ -160,5 +162,12 @@ func (t *DiffImpl) SuppressSecrets() bool {
// ReuseValues returns the ReuseValues. // ReuseValues returns the ReuseValues.
func (t *DiffImpl) ReuseValues() bool { func (t *DiffImpl) ReuseValues() bool {
if !t.ResetValues() {
return t.DiffOptions.ReuseValues return t.DiffOptions.ReuseValues
}
return false
}
func (t *DiffImpl) ResetValues() bool {
return t.DiffOptions.ResetValues
} }

View File

@ -26,6 +26,8 @@ type SyncOptions struct {
WaitForJobs bool WaitForJobs bool
// ReuseValues is true if the helm command should reuse the values // ReuseValues is true if the helm command should reuse the values
ReuseValues bool ReuseValues bool
// ResetValues is true if helm command should reset values to charts' default
ResetValues bool
// Propagate '--post-renderer' to helmv3 template and helm install // Propagate '--post-renderer' to helmv3 template and helm install
PostRenderer string PostRenderer string
} }
@ -110,7 +112,13 @@ func (t *SyncImpl) WaitForJobs() bool {
// ReuseValues returns the ReuseValues. // ReuseValues returns the ReuseValues.
func (t *SyncImpl) ReuseValues() bool { func (t *SyncImpl) ReuseValues() bool {
if !t.ResetValues() {
return t.SyncOptions.ReuseValues return t.SyncOptions.ReuseValues
}
return false
}
func (t *SyncImpl) ResetValues() bool {
return t.SyncOptions.ResetValues
} }
// PostRenderer returns the PostRenderer. // PostRenderer returns the PostRenderer.

View File

@ -613,11 +613,7 @@ func (st *HelmState) prepareSyncReleases(helm helmexec.Interface, additionalValu
flags = append(flags, "--wait-for-jobs") flags = append(flags, "--wait-for-jobs")
} }
if opts.ReuseValues || st.HelmDefaults.ReuseValues { flags = st.appendValuesControlModeFlag(flags, opts.ReuseValues, opts.ResetValues)
flags = append(flags, "--reuse-values")
} else {
flags = append(flags, "--reset-values")
}
if len(errs) > 0 { if len(errs) > 0 {
results <- syncPrepareResult{errors: errs, files: files} results <- syncPrepareResult{errors: errs, files: files}
@ -696,6 +692,7 @@ type SyncOpts struct {
Wait bool Wait bool
WaitForJobs bool WaitForJobs bool
ReuseValues bool ReuseValues bool
ResetValues bool
} }
type SyncOpt interface{ Apply(*SyncOpts) } type SyncOpt interface{ Apply(*SyncOpts) }
@ -1677,11 +1674,7 @@ func (st *HelmState) commonDiffFlags(detailedExitCode bool, includeTests bool, s
flags = append(flags, "--output", opt.Output) flags = append(flags, "--output", opt.Output)
} }
if opt.ReuseValues || st.HelmDefaults.ReuseValues { flags = st.appendValuesControlModeFlag(flags, opt.ReuseValues, opt.ResetValues)
flags = append(flags, "--reuse-values")
} else {
flags = append(flags, "--reset-values")
}
if opt.Set != nil { if opt.Set != nil {
for _, s := range opt.Set { for _, s := range opt.Set {
@ -1858,6 +1851,7 @@ type DiffOpts struct {
SkipCleanup bool SkipCleanup bool
SkipDiffOnInstall bool SkipDiffOnInstall bool
ReuseValues bool ReuseValues bool
ResetValues bool
} }
func (o *DiffOpts) Apply(opts *DiffOpts) { func (o *DiffOpts) Apply(opts *DiffOpts) {
@ -2563,6 +2557,16 @@ func (st *HelmState) chartVersionFlags(release *ReleaseSpec) []string {
return flags return flags
} }
func (st *HelmState) appendValuesControlModeFlag(flags []string, reuseValues bool, resetValues bool) []string {
if !resetValues && (st.HelmDefaults.ReuseValues || reuseValues) {
flags = append(flags, "--reuse-values")
} else {
flags = append(flags, "--reset-values")
}
return flags
}
func (st *HelmState) appendApiVersionsFlags(flags []string, r *ReleaseSpec) []string { func (st *HelmState) appendApiVersionsFlags(flags []string, r *ReleaseSpec) []string {
if len(r.ApiVersions) != 0 { if len(r.ApiVersions) != 0 {
for _, a := range r.ApiVersions { for _, a := range r.ApiVersions {

View File

@ -2604,6 +2604,36 @@ func TestDiffpareSyncReleases(t *testing.T) {
ReuseValues: true, ReuseValues: true,
}, },
}, },
{
name: "force-reset-values",
flags: []string{"--reset-values"},
diffOptions: &DiffOpts{
ResetValues: true,
},
helmDefaults: &HelmSpec{
ReuseValues: true,
},
},
{
name: "both-reset-reuse-values",
flags: []string{"--reset-values"},
diffOptions: &DiffOpts{
ReuseValues: true,
ResetValues: true,
},
helmDefaults: &HelmSpec{},
},
{
name: "both-reset-reuse-default-reuse-values",
flags: []string{"--reset-values"},
diffOptions: &DiffOpts{
ReuseValues: true,
ResetValues: true,
},
helmDefaults: &HelmSpec{
ReuseValues: true,
},
},
} }
for _, tt := range tests { for _, tt := range tests {
@ -2665,6 +2695,36 @@ func TestPrepareSyncReleases(t *testing.T) {
ReuseValues: true, ReuseValues: true,
}, },
}, },
{
name: "force-reset-values",
flags: []string{"--reset-values"},
syncOptions: &SyncOpts{
ResetValues: true,
},
helmDefaults: &HelmSpec{
ReuseValues: true,
},
},
{
name: "both-reset-reuse-values",
flags: []string{"--reset-values"},
syncOptions: &SyncOpts{
ReuseValues: true,
ResetValues: true,
},
helmDefaults: &HelmSpec{},
},
{
name: "both-reset-reuse-default-reuse-values",
flags: []string{"--reset-values"},
syncOptions: &SyncOpts{
ReuseValues: true,
ResetValues: true,
},
helmDefaults: &HelmSpec{
ReuseValues: true,
},
},
} }
for _, tt := range tests { for _, tt := range tests {