Feat add cascade support (#860)
* feat: add cascade support for helm v3.12.0 Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
		
							parent
							
								
									8e036e19dc
								
							
						
					
					
						commit
						00dace9b63
					
				|  | @ -65,6 +65,7 @@ func NewApplyCmd(globalCfg *config.GlobalImpl) *cobra.Command { | ||||||
| 	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.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"`) | ||||||
|  | 	f.StringVar(&applyOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background") | ||||||
| 
 | 
 | ||||||
| 	return cmd | 	return cmd | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ func NewDeleteCmd(globalCfg *config.GlobalImpl) *cobra.Command { | ||||||
| 
 | 
 | ||||||
| 	f := cmd.Flags() | 	f := cmd.Flags() | ||||||
| 	f.StringVar(&globalCfg.GlobalOptions.Args, "args", "", "pass args to helm exec") | 	f.StringVar(&globalCfg.GlobalOptions.Args, "args", "", "pass args to helm exec") | ||||||
|  | 	f.StringVar(&deleteOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background") | ||||||
| 	f.IntVar(&deleteOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited") | 	f.IntVar(&deleteOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited") | ||||||
| 	f.BoolVar(&deleteOptions.Purge, "purge", false, "purge releases i.e. free release names and histories") | 	f.BoolVar(&deleteOptions.Purge, "purge", false, "purge releases i.e. free release names and histories") | ||||||
| 	f.BoolVar(&deleteOptions.SkipCharts, "skip-charts", false, "don't prepare charts when deleting releases") | 	f.BoolVar(&deleteOptions.SkipCharts, "skip-charts", false, "don't prepare charts when deleting releases") | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ func NewDestroyCmd(globalCfg *config.GlobalImpl) *cobra.Command { | ||||||
| 
 | 
 | ||||||
| 	f := cmd.Flags() | 	f := cmd.Flags() | ||||||
| 	f.StringVar(&globalCfg.GlobalOptions.Args, "args", "", "pass args to helm exec") | 	f.StringVar(&globalCfg.GlobalOptions.Args, "args", "", "pass args to helm exec") | ||||||
|  | 	f.StringVar(&destroyOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background") | ||||||
| 	f.IntVar(&destroyOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited") | 	f.IntVar(&destroyOptions.Concurrency, "concurrency", 0, "maximum number of concurrent helm processes to run, 0 is unlimited") | ||||||
| 	f.BoolVar(&destroyOptions.SkipCharts, "skip-charts", false, "don't prepare charts when destroying releases") | 	f.BoolVar(&destroyOptions.SkipCharts, "skip-charts", false, "don't prepare charts when destroying releases") | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -45,6 +45,7 @@ func NewSyncCmd(globalCfg *config.GlobalImpl) *cobra.Command { | ||||||
| 	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.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"`) | ||||||
|  | 	f.StringVar(&syncOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background") | ||||||
| 
 | 
 | ||||||
| 	return cmd | 	return cmd | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										2
									
								
								go.mod
								
								
								
								
							|  | @ -54,7 +54,7 @@ require ( | ||||||
| 	github.com/a8m/envsubst v1.3.0 // indirect | 	github.com/a8m/envsubst v1.3.0 // indirect | ||||||
| 	github.com/aws/aws-sdk-go v1.44.122 // indirect | 	github.com/aws/aws-sdk-go v1.44.122 // indirect | ||||||
| 	github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect | 	github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect | ||||||
| 	github.com/blang/semver v3.5.1+incompatible // indirect | 	github.com/blang/semver v3.5.1+incompatible | ||||||
| 	github.com/dimchansky/utfbom v1.1.1 // indirect | 	github.com/dimchansky/utfbom v1.1.1 // indirect | ||||||
| 	github.com/fatih/color v1.13.0 // indirect | 	github.com/fatih/color v1.13.0 // indirect | ||||||
| 	github.com/fujiwara/tfstate-lookup v1.1.1 // indirect | 	github.com/fujiwara/tfstate-lookup v1.1.1 // indirect | ||||||
|  |  | ||||||
|  | @ -1441,7 +1441,7 @@ Do you really want to apply? | ||||||
| 
 | 
 | ||||||
| 				subst.Releases = rs | 				subst.Releases = rs | ||||||
| 
 | 
 | ||||||
| 				return subst.DeleteReleasesForSync(&affectedReleases, helm, c.Concurrency()) | 				return subst.DeleteReleasesForSync(&affectedReleases, helm, c.Concurrency(), c.Cascade()) | ||||||
| 			})) | 			})) | ||||||
| 
 | 
 | ||||||
| 			if len(deletionErrs) > 0 { | 			if len(deletionErrs) > 0 { | ||||||
|  | @ -1560,7 +1560,7 @@ Do you really want to delete? | ||||||
| 
 | 
 | ||||||
| 		if len(releasesToDelete) > 0 { | 		if len(releasesToDelete) > 0 { | ||||||
| 			_, deletionErrs := withDAG(st, helm, a.Logger, state.PlanOptions{SelectedReleases: toDelete, Reverse: true, SkipNeeds: true}, a.WrapWithoutSelector(func(subst *state.HelmState, helm helmexec.Interface) []error { | 			_, deletionErrs := withDAG(st, helm, a.Logger, state.PlanOptions{SelectedReleases: toDelete, Reverse: true, SkipNeeds: true}, a.WrapWithoutSelector(func(subst *state.HelmState, helm helmexec.Interface) []error { | ||||||
| 				return subst.DeleteReleases(&affectedReleases, helm, c.Concurrency(), purge) | 				return subst.DeleteReleases(&affectedReleases, helm, c.Concurrency(), purge, c.Cascade()) | ||||||
| 			})) | 			})) | ||||||
| 
 | 
 | ||||||
| 			if len(deletionErrs) > 0 { | 			if len(deletionErrs) > 0 { | ||||||
|  | @ -1832,7 +1832,7 @@ Do you really want to sync? | ||||||
| 
 | 
 | ||||||
| 				subst.Releases = rs | 				subst.Releases = rs | ||||||
| 
 | 
 | ||||||
| 				return subst.DeleteReleasesForSync(&affectedReleases, helm, c.Concurrency()) | 				return subst.DeleteReleasesForSync(&affectedReleases, helm, c.Concurrency(), c.Cascade()) | ||||||
| 			})) | 			})) | ||||||
| 
 | 
 | ||||||
| 			if len(deletionErrs) > 0 { | 			if len(deletionErrs) > 0 { | ||||||
|  |  | ||||||
|  | @ -57,7 +57,7 @@ func expectNoCallsToHelmVersion(app *App) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	app.helms = map[helmKey]helmexec.Interface{ | 	app.helms = map[helmKey]helmexec.Interface{ | ||||||
| 		createHelmKey(app.OverrideHelmBinary, app.OverrideKubeContext): &versionOnlyHelmExec{isHelm3: true}, | 		createHelmKey(app.OverrideHelmBinary, app.OverrideKubeContext): testutil.NewV3HelmExec(true), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -2185,8 +2185,9 @@ func (c configImpl) KubeVersion() string { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type applyConfig struct { | type applyConfig struct { | ||||||
| 	args   string | 	args    string | ||||||
| 	values []string | 	cascade string | ||||||
|  | 	values  []string | ||||||
| 
 | 
 | ||||||
| 	// TODO: Remove this function once Helmfile v0.x
 | 	// TODO: Remove this function once Helmfile v0.x
 | ||||||
| 	retainValuesFiles bool | 	retainValuesFiles bool | ||||||
|  | @ -2230,6 +2231,10 @@ func (a applyConfig) Args() string { | ||||||
| 	return a.args | 	return a.args | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (a applyConfig) Cascade() string { | ||||||
|  | 	return a.cascade | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (a applyConfig) Wait() bool { | func (a applyConfig) Wait() bool { | ||||||
| 	return a.wait | 	return a.wait | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -46,6 +46,7 @@ type ReposConfigProvider interface { | ||||||
| type ApplyConfigProvider interface { | type ApplyConfigProvider interface { | ||||||
| 	Args() string | 	Args() string | ||||||
| 	PostRenderer() string | 	PostRenderer() string | ||||||
|  | 	Cascade() string | ||||||
| 
 | 
 | ||||||
| 	Values() []string | 	Values() []string | ||||||
| 	Set() []string | 	Set() []string | ||||||
|  | @ -88,6 +89,7 @@ type ApplyConfigProvider interface { | ||||||
| type SyncConfigProvider interface { | type SyncConfigProvider interface { | ||||||
| 	Args() string | 	Args() string | ||||||
| 	PostRenderer() string | 	PostRenderer() string | ||||||
|  | 	Cascade() string | ||||||
| 
 | 
 | ||||||
| 	Values() []string | 	Values() []string | ||||||
| 	Set() []string | 	Set() []string | ||||||
|  | @ -144,6 +146,7 @@ type DiffConfigProvider interface { | ||||||
| // TODO: Remove this function once Helmfile v0.x
 | // TODO: Remove this function once Helmfile v0.x
 | ||||||
| type DeleteConfigProvider interface { | type DeleteConfigProvider interface { | ||||||
| 	Args() string | 	Args() string | ||||||
|  | 	Cascade() string | ||||||
| 
 | 
 | ||||||
| 	Purge() bool | 	Purge() bool | ||||||
| 	SkipDeps() bool | 	SkipDeps() bool | ||||||
|  | @ -156,6 +159,7 @@ type DeleteConfigProvider interface { | ||||||
| 
 | 
 | ||||||
| type DestroyConfigProvider interface { | type DestroyConfigProvider interface { | ||||||
| 	Args() string | 	Args() string | ||||||
|  | 	Cascade() string | ||||||
| 
 | 
 | ||||||
| 	SkipDeps() bool | 	SkipDeps() bool | ||||||
| 	SkipCharts() bool | 	SkipCharts() bool | ||||||
|  |  | ||||||
|  | @ -34,6 +34,7 @@ func listFlags(namespace, kubeContext string) string { | ||||||
| 
 | 
 | ||||||
| type destroyConfig struct { | type destroyConfig struct { | ||||||
| 	args                   string | 	args                   string | ||||||
|  | 	cascade                string | ||||||
| 	concurrency            int | 	concurrency            int | ||||||
| 	interactive            bool | 	interactive            bool | ||||||
| 	skipDeps               bool | 	skipDeps               bool | ||||||
|  | @ -46,6 +47,10 @@ func (d destroyConfig) Args() string { | ||||||
| 	return d.args | 	return d.args | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (d destroyConfig) Cascade() string { | ||||||
|  | 	return d.cascade | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (d destroyConfig) SkipCharts() bool { | func (d destroyConfig) SkipCharts() bool { | ||||||
| 	return d.skipCharts | 	return d.skipCharts | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -56,6 +56,8 @@ type ApplyOptions struct { | ||||||
| 	ResetValues bool | 	ResetValues bool | ||||||
| 	// Propagate '--post-renderer' to helmv3 template and helm install
 | 	// Propagate '--post-renderer' to helmv3 template and helm install
 | ||||||
| 	PostRenderer string | 	PostRenderer string | ||||||
|  | 	// Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background
 | ||||||
|  | 	Cascade string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NewApply creates a new Apply
 | // NewApply creates a new Apply
 | ||||||
|  | @ -212,3 +214,8 @@ func (a *ApplyImpl) ResetValues() bool { | ||||||
| func (a *ApplyImpl) PostRenderer() string { | func (a *ApplyImpl) PostRenderer() string { | ||||||
| 	return a.ApplyOptions.PostRenderer | 	return a.ApplyOptions.PostRenderer | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // Cascade returns cascade flag
 | ||||||
|  | func (a *ApplyImpl) Cascade() string { | ||||||
|  | 	return a.ApplyOptions.Cascade | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -9,6 +9,8 @@ type DeleteOptions struct { | ||||||
| 	Purge bool | 	Purge bool | ||||||
| 	// SkipCharts makes Delete skip `withPreparedCharts`
 | 	// SkipCharts makes Delete skip `withPreparedCharts`
 | ||||||
| 	SkipCharts bool | 	SkipCharts bool | ||||||
|  | 	// Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background
 | ||||||
|  | 	Cascade string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NewDeleteOptions creates a new Apply
 | // NewDeleteOptions creates a new Apply
 | ||||||
|  | @ -44,3 +46,8 @@ func (c *DeleteImpl) Purge() bool { | ||||||
| func (c *DeleteImpl) SkipCharts() bool { | func (c *DeleteImpl) SkipCharts() bool { | ||||||
| 	return c.DeleteOptions.SkipCharts | 	return c.DeleteOptions.SkipCharts | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // Cascade returns cascade flag
 | ||||||
|  | func (c *DeleteImpl) Cascade() string { | ||||||
|  | 	return c.DeleteOptions.Cascade | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -6,6 +6,8 @@ type DestroyOptions struct { | ||||||
| 	Concurrency int | 	Concurrency int | ||||||
| 	// SkipCharts makes Destroy skip `withPreparedCharts`
 | 	// SkipCharts makes Destroy skip `withPreparedCharts`
 | ||||||
| 	SkipCharts bool | 	SkipCharts bool | ||||||
|  | 	// Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background
 | ||||||
|  | 	Cascade string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NewDestroyOptions creates a new Apply
 | // NewDestroyOptions creates a new Apply
 | ||||||
|  | @ -36,3 +38,8 @@ func (c *DestroyImpl) Concurrency() int { | ||||||
| func (c *DestroyImpl) SkipCharts() bool { | func (c *DestroyImpl) SkipCharts() bool { | ||||||
| 	return c.DestroyOptions.SkipCharts | 	return c.DestroyOptions.SkipCharts | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // Cascade returns cascade flag
 | ||||||
|  | func (c *DestroyImpl) Cascade() string { | ||||||
|  | 	return c.DestroyOptions.Cascade | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -28,6 +28,8 @@ type SyncOptions struct { | ||||||
| 	ResetValues bool | 	ResetValues bool | ||||||
| 	// Propagate '--post-renderer' to helmv3 template and helm install
 | 	// Propagate '--post-renderer' to helmv3 template and helm install
 | ||||||
| 	PostRenderer string | 	PostRenderer string | ||||||
|  | 	// Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background
 | ||||||
|  | 	Cascade string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NewSyncOptions creates a new Apply
 | // NewSyncOptions creates a new Apply
 | ||||||
|  | @ -118,3 +120,8 @@ func (t *SyncImpl) ResetValues() bool { | ||||||
| func (t *SyncImpl) PostRenderer() string { | func (t *SyncImpl) PostRenderer() string { | ||||||
| 	return t.SyncOptions.PostRenderer | 	return t.SyncOptions.PostRenderer | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // Cascade returns cascade flag
 | ||||||
|  | func (t *SyncImpl) Cascade() string { | ||||||
|  | 	return t.SyncOptions.Cascade | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -39,6 +39,24 @@ func (st *HelmState) appendPostRenderFlags(flags []string, release *ReleaseSpec, | ||||||
| 	return flags | 	return flags | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // append post-renderer flags to helm flags
 | ||||||
|  | func (st *HelmState) appendCascadeFlags(flags []string, helm helmexec.Interface, release *ReleaseSpec, cascade string) []string { | ||||||
|  | 	// see https://github.com/helm/helm/releases/tag/v3.12.0
 | ||||||
|  | 	if !helm.IsVersionAtLeast("3.12.0") { | ||||||
|  | 		return flags | ||||||
|  | 	} | ||||||
|  | 	switch { | ||||||
|  | 	// postRenderer arg comes from cmd flag.
 | ||||||
|  | 	case release.Cascade != nil && *release.Cascade != "": | ||||||
|  | 		flags = append(flags, "--cascade", *release.Cascade) | ||||||
|  | 	case cascade != "": | ||||||
|  | 		flags = append(flags, "--cascade", cascade) | ||||||
|  | 	case st.HelmDefaults.Cascade != nil && *st.HelmDefaults.Cascade != "": | ||||||
|  | 		flags = append(flags, "--cascade", *st.HelmDefaults.Cascade) | ||||||
|  | 	} | ||||||
|  | 	return flags | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type Chartify struct { | type Chartify struct { | ||||||
| 	Opts  *chartify.ChartifyOpts | 	Opts  *chartify.ChartifyOpts | ||||||
| 	Clean func() | 	Clean func() | ||||||
|  |  | ||||||
|  | @ -0,0 +1,75 @@ | ||||||
|  | package state | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
|  | 
 | ||||||
|  | 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||||
|  | 	"github.com/helmfile/helmfile/pkg/testutil" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestAppendCascadeFlags(t *testing.T) { | ||||||
|  | 	type args struct { | ||||||
|  | 		flags    []string | ||||||
|  | 		release  *ReleaseSpec | ||||||
|  | 		cascade  string | ||||||
|  | 		helm     helmexec.Interface | ||||||
|  | 		helmSpec HelmSpec | ||||||
|  | 		expected []string | ||||||
|  | 	} | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name string | ||||||
|  | 		args args | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name: "no cascade when helm less than 3.11.0", | ||||||
|  | 			args: args{ | ||||||
|  | 				flags:    []string{}, | ||||||
|  | 				release:  &ReleaseSpec{}, | ||||||
|  | 				cascade:  "background", | ||||||
|  | 				helm:     testutil.NewVersionHelmExec("3.11.0"), | ||||||
|  | 				expected: []string{}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "cascade from release", | ||||||
|  | 			args: args{ | ||||||
|  | 				flags:    []string{}, | ||||||
|  | 				release:  &ReleaseSpec{Cascade: &[]string{"background", "background"}[0]}, | ||||||
|  | 				cascade:  "", | ||||||
|  | 				helm:     testutil.NewVersionHelmExec("3.12.0"), | ||||||
|  | 				expected: []string{"--cascade", "background"}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "cascade from cmd flag", | ||||||
|  | 			args: args{ | ||||||
|  | 				flags:    []string{}, | ||||||
|  | 				release:  &ReleaseSpec{}, | ||||||
|  | 				cascade:  "background", | ||||||
|  | 				helm:     testutil.NewVersionHelmExec("3.12.0"), | ||||||
|  | 				expected: []string{"--cascade", "background"}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "cascade from helm defaults", | ||||||
|  | 			args: args{ | ||||||
|  | 				flags:    []string{}, | ||||||
|  | 				release:  &ReleaseSpec{}, | ||||||
|  | 				helmSpec: HelmSpec{Cascade: &[]string{"background", "background"}[0]}, | ||||||
|  | 				cascade:  "", | ||||||
|  | 				helm:     testutil.NewVersionHelmExec("3.12.0"), | ||||||
|  | 				expected: []string{"--cascade", "background"}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			st := &HelmState{} | ||||||
|  | 			st.HelmDefaults = tt.args.helmSpec | ||||||
|  | 			got := st.appendCascadeFlags(tt.args.flags, tt.args.helm, tt.args.release, tt.args.cascade) | ||||||
|  | 			require.Equalf(t, tt.args.expected, got, "appendCascadeFlags() = %v, want %v", got, tt.args.expected) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -187,6 +187,8 @@ type HelmSpec struct { | ||||||
| 	ReuseValues bool `yaml:"reuseValues"` | 	ReuseValues bool `yaml:"reuseValues"` | ||||||
| 	// Propagate '--post-renderer' to helmv3 template and helm install
 | 	// Propagate '--post-renderer' to helmv3 template and helm install
 | ||||||
| 	PostRenderer *string `yaml:"postRenderer,omitempty"` | 	PostRenderer *string `yaml:"postRenderer,omitempty"` | ||||||
|  | 	// Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background
 | ||||||
|  | 	Cascade *string `yaml:"cascade,omitempty"` | ||||||
| 
 | 
 | ||||||
| 	TLS                      bool   `yaml:"tls"` | 	TLS                      bool   `yaml:"tls"` | ||||||
| 	TLSCACert                string `yaml:"tlsCACert,omitempty"` | 	TLSCACert                string `yaml:"tlsCACert,omitempty"` | ||||||
|  | @ -360,6 +362,9 @@ type ReleaseSpec struct { | ||||||
| 	// Propagate '--post-renderer' to helmv3 template and helm install
 | 	// Propagate '--post-renderer' to helmv3 template and helm install
 | ||||||
| 	PostRenderer *string `yaml:"postRenderer,omitempty"` | 	PostRenderer *string `yaml:"postRenderer,omitempty"` | ||||||
| 
 | 
 | ||||||
|  | 	// Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background
 | ||||||
|  | 	Cascade *string `yaml:"cascade,omitempty"` | ||||||
|  | 
 | ||||||
| 	// Inherit is used to inherit a release template from a release or another release template
 | 	// Inherit is used to inherit a release template from a release or another release template
 | ||||||
| 	Inherit Inherits `yaml:"inherit,omitempty"` | 	Inherit Inherits `yaml:"inherit,omitempty"` | ||||||
| } | } | ||||||
|  | @ -767,7 +772,7 @@ func ReleaseToID(r *ReleaseSpec) string { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // DeleteReleasesForSync deletes releases that are marked for deletion
 | // DeleteReleasesForSync deletes releases that are marked for deletion
 | ||||||
| func (st *HelmState) DeleteReleasesForSync(affectedReleases *AffectedReleases, helm helmexec.Interface, workerLimit int) []error { | func (st *HelmState) DeleteReleasesForSync(affectedReleases *AffectedReleases, helm helmexec.Interface, workerLimit int, cascade string) []error { | ||||||
| 	errs := []error{} | 	errs := []error{} | ||||||
| 
 | 
 | ||||||
| 	releases := st.Releases | 	releases := st.Releases | ||||||
|  | @ -801,7 +806,9 @@ func (st *HelmState) DeleteReleasesForSync(affectedReleases *AffectedReleases, h | ||||||
| 					if release.Namespace != "" { | 					if release.Namespace != "" { | ||||||
| 						args = append(args, "--namespace", release.Namespace) | 						args = append(args, "--namespace", release.Namespace) | ||||||
| 					} | 					} | ||||||
| 					deletionFlags := st.appendConnectionFlags(args, release) | 					args = st.appendConnectionFlags(args, release) | ||||||
|  | 					deletionFlags := st.appendCascadeFlags(args, helm, release, cascade) | ||||||
|  | 
 | ||||||
| 					m.Lock() | 					m.Lock() | ||||||
| 					start := time.Now() | 					start := time.Now() | ||||||
| 					if _, err := st.triggerReleaseEvent("preuninstall", nil, release, "sync"); err != nil { | 					if _, err := st.triggerReleaseEvent("preuninstall", nil, release, "sync"); err != nil { | ||||||
|  | @ -2031,15 +2038,17 @@ func (st *HelmState) ReleaseStatuses(helm helmexec.Interface, workerLimit int) [ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // DeleteReleases wrapper for executing helm delete on the releases
 | // DeleteReleases wrapper for executing helm delete on the releases
 | ||||||
| func (st *HelmState) DeleteReleases(affectedReleases *AffectedReleases, helm helmexec.Interface, concurrency int, purge bool) []error { | func (st *HelmState) DeleteReleases(affectedReleases *AffectedReleases, helm helmexec.Interface, concurrency int, purge bool, cascade string) []error { | ||||||
| 	return st.scatterGatherReleases(helm, concurrency, func(release ReleaseSpec, workerIndex int) error { | 	return st.scatterGatherReleases(helm, concurrency, func(release ReleaseSpec, workerIndex int) error { | ||||||
| 		st.ApplyOverrides(&release) | 		st.ApplyOverrides(&release) | ||||||
| 
 | 
 | ||||||
| 		flags := make([]string, 0) | 		flags := make([]string, 0) | ||||||
| 		flags = st.appendConnectionFlags(flags, &release) | 		flags = st.appendConnectionFlags(flags, &release) | ||||||
|  | 		flags = st.appendCascadeFlags(flags, helm, &release, cascade) | ||||||
| 		if release.Namespace != "" { | 		if release.Namespace != "" { | ||||||
| 			flags = append(flags, "--namespace", release.Namespace) | 			flags = append(flags, "--namespace", release.Namespace) | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 		context := st.createHelmContext(&release, workerIndex) | 		context := st.createHelmContext(&release, workerIndex) | ||||||
| 
 | 
 | ||||||
| 		start := time.Now() | 		start := time.Now() | ||||||
|  |  | ||||||
|  | @ -2647,7 +2647,7 @@ func TestHelmState_Delete(t *testing.T) { | ||||||
| 				helm.Lists[exectest.ListKey{Filter: "^" + name + "$", Flags: tt.flags}] = name | 				helm.Lists[exectest.ListKey{Filter: "^" + name + "$", Flags: tt.flags}] = name | ||||||
| 			} | 			} | ||||||
| 			affectedReleases := AffectedReleases{} | 			affectedReleases := AffectedReleases{} | ||||||
| 			errs := state.DeleteReleases(&affectedReleases, helm, 1, tt.purge) | 			errs := state.DeleteReleases(&affectedReleases, helm, 1, tt.purge, "") | ||||||
| 			if errs != nil { | 			if errs != nil { | ||||||
| 				if !tt.wantErr || len(affectedReleases.Failed) != 1 || affectedReleases.Failed[0].Name != release.Name { | 				if !tt.wantErr || len(affectedReleases.Failed) != 1 || affectedReleases.Failed[0].Name != release.Name { | ||||||
| 					t.Errorf("DeleteReleases() for %s error = %v, wantErr %v", tt.name, errs, tt.wantErr) | 					t.Errorf("DeleteReleases() for %s error = %v, wantErr %v", tt.name, errs, tt.wantErr) | ||||||
|  |  | ||||||
|  | @ -38,39 +38,39 @@ func TestGenerateID(t *testing.T) { | ||||||
| 	run(testcase{ | 	run(testcase{ | ||||||
| 		subject: "baseline", | 		subject: "baseline", | ||||||
| 		release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, | 		release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, | ||||||
| 		want:    "foo-values-76d4857b56", | 		want:    "foo-values-6cbf8f5f9f", | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	run(testcase{ | 	run(testcase{ | ||||||
| 		subject: "different bytes content", | 		subject: "different bytes content", | ||||||
| 		release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, | 		release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, | ||||||
| 		data:    []byte(`{"k":"v"}`), | 		data:    []byte(`{"k":"v"}`), | ||||||
| 		want:    "foo-values-55d59fb487", | 		want:    "foo-values-6cb9d4f956", | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	run(testcase{ | 	run(testcase{ | ||||||
| 		subject: "different map content", | 		subject: "different map content", | ||||||
| 		release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, | 		release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, | ||||||
| 		data:    map[string]interface{}{"k": "v"}, | 		data:    map[string]interface{}{"k": "v"}, | ||||||
| 		want:    "foo-values-7c8d99f9f7", | 		want:    "foo-values-5bdffb5f4b", | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	run(testcase{ | 	run(testcase{ | ||||||
| 		subject: "different chart", | 		subject: "different chart", | ||||||
| 		release: ReleaseSpec{Name: "foo", Chart: "stable/envoy"}, | 		release: ReleaseSpec{Name: "foo", Chart: "stable/envoy"}, | ||||||
| 		want:    "foo-values-7467f76549", | 		want:    "foo-values-6595bd68c6", | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	run(testcase{ | 	run(testcase{ | ||||||
| 		subject: "different name", | 		subject: "different name", | ||||||
| 		release: ReleaseSpec{Name: "bar", Chart: "incubator/raw"}, | 		release: ReleaseSpec{Name: "bar", Chart: "incubator/raw"}, | ||||||
| 		want:    "bar-values-dbdf465b7", | 		want:    "bar-values-75698946b", | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	run(testcase{ | 	run(testcase{ | ||||||
| 		subject: "specific ns", | 		subject: "specific ns", | ||||||
| 		release: ReleaseSpec{Name: "foo", Chart: "incubator/raw", Namespace: "myns"}, | 		release: ReleaseSpec{Name: "foo", Chart: "incubator/raw", Namespace: "myns"}, | ||||||
| 		want:    "myns-foo-values-6d4874d757", | 		want:    "myns-foo-values-5bf477bbfb", | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	for id, n := range ids { | 	for id, n := range ids { | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| package app | package testutil | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"github.com/blang/semver" | ||||||
| 	"helm.sh/helm/v3/pkg/chart" | 	"helm.sh/helm/v3/pkg/chart" | ||||||
| 
 | 
 | ||||||
| 	"github.com/helmfile/helmfile/pkg/helmexec" | 	"github.com/helmfile/helmfile/pkg/helmexec" | ||||||
|  | @ -9,15 +10,34 @@ import ( | ||||||
| type noCallHelmExec struct { | type noCallHelmExec struct { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type versionOnlyHelmExec struct { | type V3HelmExec struct { | ||||||
| 	*noCallHelmExec | 	*noCallHelmExec | ||||||
| 	isHelm3 bool | 	isHelm3 bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (helm *versionOnlyHelmExec) IsHelm3() bool { | func NewV3HelmExec(isHelm3 bool) *V3HelmExec { | ||||||
|  | 	return &V3HelmExec{noCallHelmExec: &noCallHelmExec{}, isHelm3: isHelm3} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type VersionHelmExec struct { | ||||||
|  | 	*noCallHelmExec | ||||||
|  | 	version string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewVersionHelmExec(version string) *VersionHelmExec { | ||||||
|  | 	return &VersionHelmExec{noCallHelmExec: &noCallHelmExec{}, version: version} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (helm *V3HelmExec) IsHelm3() bool { | ||||||
| 	return helm.isHelm3 | 	return helm.isHelm3 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (helm *VersionHelmExec) IsVersionAtLeast(ver string) bool { | ||||||
|  | 	currentSemVer := semver.MustParse(helm.version) | ||||||
|  | 	verSemVer := semver.MustParse(ver) | ||||||
|  | 	return currentSemVer.GTE(verSemVer) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (helm *noCallHelmExec) doPanic() { | func (helm *noCallHelmExec) doPanic() { | ||||||
| 	panic("unexpected call to helm") | 	panic("unexpected call to helm") | ||||||
| } | } | ||||||
		Loading…
	
		Reference in New Issue