diff --git a/cmd/sync.go b/cmd/sync.go index 1d8ed45f..3bd80e6f 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -46,6 +46,7 @@ func NewSyncCmd(globalCfg *config.GlobalImpl) *cobra.Command { f.BoolVar(&syncOptions.SyncReleaseLabels, "sync-release-labels", false, "sync release labels to the target release") 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.IntVar(&syncOptions.Timeout, "timeout", 0, `Override helmDefaults.timeout setting "helm upgrade --install --timeout" (default 0, which means no timeout)`) 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"`) diff --git a/docs/index.md b/docs/index.md index 21099f11..399f356b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -646,6 +646,8 @@ Flags: Use "helmfile [command] --help" for more information about a command. ``` +**Note:** Each command has its own specific flags. Use `helmfile [command] --help` to see command-specific options. For example, `helmfile sync --help` shows operational flags like `--timeout`, `--wait`, and `--wait-for-jobs`. + ### init The `helmfile init` sub-command checks the dependencies required for helmfile operation, such as `helm`, `helm diff plugin`, `helm secrets plugin`, `helm helm-git plugin`, `helm s3 plugin`. When it does not exist or the version is too low, it can be installed automatically. @@ -661,6 +663,25 @@ The `helmfile sync` sub-command sync your cluster state as described in your `he Under the covers, Helmfile executes `helm upgrade --install` for each `release` declared in the manifest, by optionally decrypting [secrets](#secrets) to be consumed as helm chart values. It also updates specified chart repositories and updates the dependencies of any referenced local charts. +#### Common sync flags + +* `--timeout SECONDS` - Override the default timeout for all releases in this sync operation. This takes precedence over `helmDefaults.timeout` and per-release `timeout` settings. +* `--wait` - Override the default wait behavior for all releases +* `--wait-for-jobs` - Override the default wait-for-jobs behavior for all releases + +Examples: + +```bash +# Override timeout for all releases to 10 minutes +helmfile sync --timeout 600 + +# Combine timeout with wait flags +helmfile sync --timeout 900 --wait --wait-for-jobs + +# Target specific releases with custom timeout +helmfile sync --selector tier=backend --timeout 1200 +``` + For Helm 2.9+ you can use a username and password to authenticate to a remote repository. ### deps diff --git a/pkg/config/sync.go b/pkg/config/sync.go index 71d38034..8d68aba8 100644 --- a/pkg/config/sync.go +++ b/pkg/config/sync.go @@ -24,6 +24,8 @@ type SyncOptions struct { WaitRetries int // WaitForJobs is the wait for jobs flag WaitForJobs bool + // Timeout is the timeout flag in seconds + Timeout int // 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 @@ -124,6 +126,11 @@ func (t *SyncImpl) WaitForJobs() bool { return t.SyncOptions.WaitForJobs } +// Timeout returns the timeout +func (t *SyncImpl) Timeout() int { + return t.SyncOptions.Timeout +} + // ReuseValues returns the ReuseValues. func (t *SyncImpl) ReuseValues() bool { if !t.ResetValues() { diff --git a/pkg/state/state.go b/pkg/state/state.go index 60289117..4b2b14a7 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -807,6 +807,7 @@ type SyncOpts struct { Wait bool WaitRetries int WaitForJobs bool + Timeout int SyncReleaseLabels bool ReuseValues bool ResetValues bool @@ -2271,7 +2272,7 @@ func (st *HelmState) TestReleases(helm helmexec.Interface, cleanup bool, timeout } if timeout == EmptyTimeout { - flags = append(flags, st.timeoutFlags(&release)...) + flags = append(flags, st.timeoutFlags(&release, nil)...) } else { duration := strconv.Itoa(timeout) duration += "s" @@ -2751,13 +2752,16 @@ func (st *HelmState) needsInsecureSkipTLSVerify(release *ReleaseSpec, repo *Repo return relSkipTLSVerify || st.HelmDefaults.InsecureSkipTLSVerify || repoSkipTLSVerify } -func (st *HelmState) timeoutFlags(release *ReleaseSpec) []string { +func (st *HelmState) timeoutFlags(release *ReleaseSpec, ops *SyncOpts) []string { var flags []string timeout := st.HelmDefaults.Timeout if release.Timeout != nil { timeout = *release.Timeout } + if ops != nil && ops.Timeout > 0 { + timeout = ops.Timeout + } if timeout != 0 { duration := strconv.Itoa(timeout) duration += "s" @@ -2783,7 +2787,7 @@ func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSp flags = st.appendKeyringFlags(flags, release) } - flags = append(flags, st.timeoutFlags(release)...) + flags = append(flags, st.timeoutFlags(release, opt)...) if release.Force != nil && *release.Force || release.Force == nil && st.HelmDefaults.Force { flags = append(flags, "--force") diff --git a/pkg/state/state_test.go b/pkg/state/state_test.go index 4834ba1c..b499279c 100644 --- a/pkg/state/state_test.go +++ b/pkg/state/state_test.go @@ -170,6 +170,7 @@ func TestHelmState_flagsForUpgrade(t *testing.T) { version *semver.Version defaults HelmSpec release *ReleaseSpec + syncOpts *SyncOpts want []string wantErr string }{ @@ -455,6 +456,27 @@ func TestHelmState_flagsForUpgrade(t *testing.T) { "--namespace", "test-namespace", }, }, + { + name: "timeout-from-cli-flag", + defaults: HelmSpec{ + Timeout: 123, + }, + release: &ReleaseSpec{ + Chart: "test/chart", + Version: "0.1", + Timeout: some(456), + Name: "test-charts", + Namespace: "test-namespace", + }, + syncOpts: &SyncOpts{ + Timeout: 789, + }, + want: []string{ + "--version", "0.1", + "--timeout", "789s", + "--namespace", "test-namespace", + }, + }, { name: "atomic", defaults: HelmSpec{ @@ -737,7 +759,7 @@ func TestHelmState_flagsForUpgrade(t *testing.T) { Version: tt.version, } - args, _, err := state.flagsForUpgrade(helm, tt.release, 0, nil) + args, _, err := state.flagsForUpgrade(helm, tt.release, 0, tt.syncOpts) if err != nil && tt.wantErr == "" { t.Errorf("unexpected error flagsForUpgrade: %v", err) }