diff --git a/README.md b/README.md index 8b38a43e..1a9aa675 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ Flags: --repo string specify the chart repository url to locate the requested chart --reset-values reset the values to the ones built into the chart and merge in any new values --reuse-values reuse the last release's values and merge in any new values. If '--reset-values' is specified, this is ignored + --reset-then-reuse-values reset the values to the ones built into the chart, apply the last release's values and merge in any new values. If '--reset-values' or '--reuse-values' is specified, this is ignored --set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2) --set-file stringArray set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2) --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2) @@ -198,6 +199,7 @@ Flags: --repo string specify the chart repository url to locate the requested chart --reset-values reset the values to the ones built into the chart and merge in any new values --reuse-values reuse the last release's values and merge in any new values. If '--reset-values' is specified, this is ignored + --reset-then-reuse-values reset the values to the ones built into the chart, apply the last release's values and merge in any new values. If '--reset-values' or '--reuse-values' is specified, this is ignored --set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2) --set-file stringArray set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2) --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2) diff --git a/cmd/helm3.go b/cmd/helm3.go index 8eccf723..f3f7db9e 100644 --- a/cmd/helm3.go +++ b/cmd/helm3.go @@ -16,8 +16,11 @@ import ( var ( helmVersionRE = regexp.MustCompile(`Version:\s*"([^"]+)"`) minHelmVersion = semver.MustParse("v3.1.0-rc.1") - // See https://github.com/helm/helm/pull/9426 + // See https://github.com/helm/helm/pull/9426. minHelmVersionWithDryRunLookupSupport = semver.MustParse("v3.13.0") + // The --reset-then-reuse-values flag for `helm upgrade` was added in + // https://github.com/helm/helm/pull/9653 and released as part of Helm v3.14.0. + minHelmVersionWithResetThenReuseValues = semver.MustParse("v3.14.0") ) func getHelmVersion() (*semver.Version, error) { @@ -132,7 +135,7 @@ func (d *diffCmd) template(isUpgrade bool) ([]byte, error) { // Let's simulate that in helm-diff. // See https://medium.com/@kcatstack/understand-helm-upgrade-flags-reset-values-reuse-values-6e58ac8f127e shouldDefaultReusingValues := isUpgrade && len(d.values) == 0 && len(d.stringValues) == 0 && len(d.stringLiteralValues) == 0 && len(d.jsonValues) == 0 && len(d.valueFiles) == 0 && len(d.fileValues) == 0 - if (d.reuseValues || shouldDefaultReusingValues) && !d.resetValues && d.clusterAccessAllowed() { + if (d.reuseValues || d.resetThenReuseValues || shouldDefaultReusingValues) && !d.resetValues && d.clusterAccessAllowed() { tmpfile, err := os.CreateTemp("", "existing-values") if err != nil { return nil, err @@ -140,7 +143,21 @@ func (d *diffCmd) template(isUpgrade bool) ([]byte, error) { defer func() { _ = os.Remove(tmpfile.Name()) }() - if err := d.writeExistingValues(tmpfile); err != nil { + // In the presence of --reuse-values (or --reset-values), --reset-then-reuse-values is ignored. + if d.resetThenReuseValues && !d.reuseValues { + var supported bool + supported, err = isHelmVersionAtLeast(minHelmVersionWithResetThenReuseValues) + if err != nil { + return nil, err + } + if !supported { + return nil, fmt.Errorf("Using --reset-then-reuse-values requires at least helm version %s", minHelmVersionWithResetThenReuseValues.String()) + } + err = d.writeExistingValues(tmpfile, false) + } else { + err = d.writeExistingValues(tmpfile, true) + } + if err != nil { return nil, err } flags = append(flags, "--values", tmpfile.Name()) @@ -308,8 +325,12 @@ func (d *diffCmd) template(isUpgrade bool) ([]byte, error) { return filter(out), err } -func (d *diffCmd) writeExistingValues(f *os.File) error { - cmd := exec.Command(os.Getenv("HELM_BIN"), "get", "values", d.release, "--all", "--output", "yaml") +func (d *diffCmd) writeExistingValues(f *os.File, all bool) error { + args := []string{"get", "values", d.release, "--output", "yaml"} + if all { + args = append(args, "--all") + } + cmd := exec.Command(os.Getenv("HELM_BIN"), args...) debugPrint("Executing %s", strings.Join(cmd.Args, " ")) defer func() { _ = f.Close() diff --git a/cmd/upgrade.go b/cmd/upgrade.go index 4fe554f7..21ffd724 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -56,6 +56,7 @@ type diffCmd struct { fileValues []string reuseValues bool resetValues bool + resetThenReuseValues bool allowUnreleased bool noHooks bool includeTests bool @@ -242,6 +243,7 @@ func newChartCommand() *cobra.Command { f.StringArrayVar(&diff.fileValues, "set-file", []string{}, "set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)") f.BoolVar(&diff.reuseValues, "reuse-values", false, "reuse the last release's values and merge in any new values. If '--reset-values' is specified, this is ignored") f.BoolVar(&diff.resetValues, "reset-values", false, "reset the values to the ones built into the chart and merge in any new values") + f.BoolVar(&diff.resetThenReuseValues, "reset-then-reuse-values", false, "reset the values to the ones built into the chart, apply the last release's values and merge in any new values. If '--reset-values' or '--reuse-values' is specified, this is ignored") f.BoolVar(&diff.allowUnreleased, "allow-unreleased", false, "enables diffing of releases that are not yet deployed via Helm") f.BoolVar(&diff.install, "install", false, "enables diffing of releases that are not yet deployed via Helm (equivalent to --allow-unreleased, added to match \"helm upgrade --install\" command") f.BoolVar(&diff.noHooks, "no-hooks", false, "disable diffing of hooks")