mirror of
https://github.com/helmfile/helmfile.git
synced 2026-10-18 08:19:48 +02:00
fix: skip recreatePods on Helm 4, which removed --recreate-pods (#2832)
* fix: skip recreatePods on Helm 4, which removed --recreate-pods - Helm 4 removed `--recreate-pods` (helm/helm#31023) and fails with "unknown flag", so a release with `recreatePods: true` broke `sync` and `apply`. On Helm 4 the flag is now left out with a warning; Helm 3 still receives it. - The upgrade flag tests gain Helm 4 cases, and the existing ones are pinned to Helm 3 so they no longer depend on the installed helm binary. - A test checks that the warning names the release on Helm 4 and is not logged on Helm 3. - The configuration docs note that recreatePods is ignored on Helm 4. Signed-off-by: Cayan <1619617+Cayan@users.noreply.github.com> * refactor: flatten recreatePods flag logic in flagsForUpgrade Drop the nested if-in-if and the st.logger nil-guard: no other log call in state.go nil-checks the logger (e.g. the --color Helm 4 skip). Compute recreatePodsEnabled and branch via a tagless switch, matching the switch style already used elsewhere in state.go: warn on Helm 4, append --recreate-pods otherwise. The flagsForUpgrade table runner now uses the shared discard logger so the Helm 4 recreate-pods cases log safely. Signed-off-by: yxxhero <aiopsclub@163.com> --------- Signed-off-by: Cayan <1619617+Cayan@users.noreply.github.com> Signed-off-by: yxxhero <aiopsclub@163.com> Co-authored-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
@@ -116,7 +116,8 @@ helmDefaults:
|
||||
waitForJobs: true
|
||||
# time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks, and waits on pod/pvc/svc/deployment readiness) (default 300)
|
||||
timeout: 600
|
||||
# performs pods restart for the resource if applicable (default false)
|
||||
# performs pods restart for the resource if applicable (default false).
|
||||
# Ignored with a warning on Helm 4, which removed --recreate-pods.
|
||||
recreatePods: true
|
||||
# forces resource update through delete/recreate if needed (default false)
|
||||
force: false
|
||||
@@ -254,7 +255,7 @@ releases:
|
||||
# waitRetries: 3
|
||||
waitForJobs: true
|
||||
timeout: 60
|
||||
recreatePods: true
|
||||
recreatePods: true # ignored with a warning on Helm 4
|
||||
force: false
|
||||
reuseValues: false
|
||||
# set `false` to uninstall this release on sync. (default true)
|
||||
|
||||
+8
-1
@@ -4296,7 +4296,14 @@ func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSp
|
||||
flags = append(flags, "--force-conflicts")
|
||||
}
|
||||
|
||||
if release.RecreatePods != nil && *release.RecreatePods || release.RecreatePods == nil && st.HelmDefaults.RecreatePods {
|
||||
recreatePodsEnabled := (release.RecreatePods != nil && *release.RecreatePods) || (release.RecreatePods == nil && st.HelmDefaults.RecreatePods)
|
||||
|
||||
// Helm 4 removed --recreate-pods (helm/helm#31023) and fails with "unknown flag".
|
||||
// It has no replacement flag; Helm recommends a checksum annotation on the pod template.
|
||||
switch {
|
||||
case recreatePodsEnabled && helm.IsHelm4():
|
||||
st.logger.Warnf("recreatePods is not supported by Helm 4, ignoring it for release %s", release.Name)
|
||||
case recreatePodsEnabled:
|
||||
flags = append(flags, "--recreate-pods")
|
||||
}
|
||||
|
||||
|
||||
+89
-4
@@ -1,12 +1,14 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
@@ -459,10 +461,12 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
|
||||
wantErr: "force and forceConflicts are mutually exclusive (check both releases[].force/forceConflicts and helmDefaults.force/forceConflicts)",
|
||||
},
|
||||
{
|
||||
name: "recreate-pods",
|
||||
name: "recreate-pods-helm3",
|
||||
defaults: HelmSpec{
|
||||
RecreatePods: false,
|
||||
RecreatePods: false,
|
||||
CreateNamespace: &disable,
|
||||
},
|
||||
version: semver.MustParse("3.10.0"),
|
||||
release: &ReleaseSpec{
|
||||
Chart: "test/chart",
|
||||
Version: "0.1",
|
||||
@@ -477,10 +481,12 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "recreate-pods-from-default",
|
||||
name: "recreate-pods-from-default-helm3",
|
||||
defaults: HelmSpec{
|
||||
RecreatePods: true,
|
||||
RecreatePods: true,
|
||||
CreateNamespace: &disable,
|
||||
},
|
||||
version: semver.MustParse("3.10.0"),
|
||||
release: &ReleaseSpec{
|
||||
Chart: "test/chart",
|
||||
Version: "0.1",
|
||||
@@ -493,6 +499,43 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
|
||||
"--namespace", "test-namespace",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "recreate-pods-helm4",
|
||||
defaults: HelmSpec{
|
||||
RecreatePods: false,
|
||||
CreateNamespace: &disable,
|
||||
},
|
||||
version: semver.MustParse("4.0.0"),
|
||||
release: &ReleaseSpec{
|
||||
Chart: "test/chart",
|
||||
Version: "0.1",
|
||||
RecreatePods: &enable,
|
||||
Name: "test-charts",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
want: []string{
|
||||
"--version", "0.1",
|
||||
"--namespace", "test-namespace",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "recreate-pods-from-default-helm4",
|
||||
defaults: HelmSpec{
|
||||
RecreatePods: true,
|
||||
CreateNamespace: &disable,
|
||||
},
|
||||
version: semver.MustParse("4.0.0"),
|
||||
release: &ReleaseSpec{
|
||||
Chart: "test/chart",
|
||||
Version: "0.1",
|
||||
Name: "test-charts",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
want: []string{
|
||||
"--version", "0.1",
|
||||
"--namespace", "test-namespace",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "wait",
|
||||
defaults: HelmSpec{
|
||||
@@ -1438,6 +1481,7 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
|
||||
basePath: "./",
|
||||
Releases: []ReleaseSpec{*tt.release},
|
||||
HelmDefaults: tt.defaults,
|
||||
logger: logger,
|
||||
valsRuntime: valsRuntime,
|
||||
}
|
||||
helm := &exectest.Helm{
|
||||
@@ -1458,6 +1502,47 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHelmState_flagsForUpgrade_RecreatePodsWarning(t *testing.T) {
|
||||
enable := true
|
||||
disable := false
|
||||
tests := []struct {
|
||||
name string
|
||||
version *semver.Version
|
||||
wantWarn bool
|
||||
}{
|
||||
{name: "helm4", version: semver.MustParse("4.0.0"), wantWarn: true},
|
||||
{name: "helm3", version: semver.MustParse("3.10.0"), wantWarn: false},
|
||||
}
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var logs bytes.Buffer
|
||||
release := &ReleaseSpec{
|
||||
Chart: "test/chart",
|
||||
RecreatePods: &enable,
|
||||
Name: "test-charts",
|
||||
Namespace: "test-namespace",
|
||||
}
|
||||
state := &HelmState{
|
||||
basePath: "./",
|
||||
Releases: []ReleaseSpec{*release},
|
||||
HelmDefaults: HelmSpec{CreateNamespace: &disable},
|
||||
logger: helmexec.NewLogger(&logs, "warn"),
|
||||
valsRuntime: valsRuntime,
|
||||
}
|
||||
|
||||
if _, _, err := state.flagsForUpgrade(&exectest.Helm{Version: tt.version}, release, 0, &SyncOpts{}); err != nil {
|
||||
t.Fatalf("unexpected error flagsForUpgrade: %v", err)
|
||||
}
|
||||
|
||||
warned := strings.Contains(logs.String(), "recreatePods is not supported by Helm 4, ignoring it for release test-charts")
|
||||
if warned != tt.wantWarn {
|
||||
t.Errorf("warning logged = %v, want %v; logs: %q", warned, tt.wantWarn, logs.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHelmState_flagsForTemplate(t *testing.T) {
|
||||
enable := true
|
||||
disable := false
|
||||
|
||||
Reference in New Issue
Block a user