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.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.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"`)
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.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.ResetValues, "reset-values", false, `Override helmDefaults.reuseValues "helm diff upgrade --install --reset-values"`)
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.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.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"`)
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.
# Useful when the chart is broken, like seen in https://github.com/roboll/helmfile/issues/1547
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
# propagate `--post-renderer` to helmv3 template and helm install
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(),
SkipDiffOnInstall: c.SkipDiffOnInstall(),
ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
}
infoMsg, releasesToBeUpdated, releasesToBeDeleted, errs := r.diff(false, detailedExitCode, c, diffOpts)
@ -1428,6 +1429,7 @@ Do you really want to apply?
Wait: c.Wait(),
WaitForJobs: c.WaitForJobs(),
ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
}
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(),
SkipDiffOnInstall: c.SkipDiffOnInstall(),
ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
}
filtered := &Run{
@ -1814,6 +1817,7 @@ Do you really want to sync?
Wait: c.Wait(),
WaitForJobs: c.WaitForJobs(),
ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
}
return subst.SyncReleases(&affectedReleases, helm, c.Values(), c.Concurrency(), opts)
}))

View File

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

View File

@ -259,7 +259,8 @@ type InitConfigProvider interface {
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 {
ReuseValues() bool
ResetValues() bool
}

View File

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

View File

@ -53,6 +53,8 @@ type ApplyOptions struct {
WaitForJobs bool
// ReuseValues is true if the helm command should reuse the values
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
PostRenderer string
}
@ -197,7 +199,14 @@ func (a *ApplyImpl) WaitForJobs() bool {
// ReuseValues returns the ReuseValues.
func (a *ApplyImpl) ReuseValues() bool {
return a.ApplyOptions.ReuseValues
if !a.ResetValues() {
return a.ApplyOptions.ReuseValues
}
return false
}
func (a *ApplyImpl) ResetValues() bool {
return a.ApplyOptions.ResetValues
}
// PostRenderer returns the PostRenderer.

View File

@ -38,6 +38,8 @@ type DiffOptions struct {
Output string
// ReuseValues is true if the helm command should reuse the values
ReuseValues bool
// ResetValues is true if helm command should reset values to charts' default
ResetValues bool
}
// NewDiffOptions creates a new Apply
@ -160,5 +162,12 @@ func (t *DiffImpl) SuppressSecrets() bool {
// ReuseValues returns the ReuseValues.
func (t *DiffImpl) ReuseValues() bool {
return t.DiffOptions.ReuseValues
if !t.ResetValues() {
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
// ReuseValues is true if the helm command should reuse the values
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
PostRenderer string
}
@ -110,7 +112,13 @@ func (t *SyncImpl) WaitForJobs() bool {
// ReuseValues returns the ReuseValues.
func (t *SyncImpl) ReuseValues() bool {
return t.SyncOptions.ReuseValues
if !t.ResetValues() {
return t.SyncOptions.ReuseValues
}
return false
}
func (t *SyncImpl) ResetValues() bool {
return t.SyncOptions.ResetValues
}
// PostRenderer returns the PostRenderer.

View File

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

View File

@ -2604,6 +2604,36 @@ func TestDiffpareSyncReleases(t *testing.T) {
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 {
@ -2665,6 +2695,36 @@ func TestPrepareSyncReleases(t *testing.T) {
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 {