Add helmfile template --show-only (#1494)
Add a `--show-only` parameter to the `helmfile template` command to pass on to the `helm template` command. Signed-off-by: Jim Barber <jim.barber@healthengine.com.au>
This commit is contained in:
		
							parent
							
								
									f2a0467b05
								
							
						
					
					
						commit
						f73da1e2a1
					
				|  | @ -47,6 +47,7 @@ func NewTemplateCmd(globalCfg *config.GlobalImpl) *cobra.Command { | ||||||
| 	f.StringVar(&templateOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`) | 	f.StringVar(&templateOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`) | ||||||
| 	f.StringArrayVar(&templateOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`) | 	f.StringArrayVar(&templateOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`) | ||||||
| 	f.StringVar(&templateOptions.KubeVersion, "kube-version", "", `pass --kube-version to "helm template". Overrides kubeVersion in helmfile.yaml`) | 	f.StringVar(&templateOptions.KubeVersion, "kube-version", "", `pass --kube-version to "helm template". Overrides kubeVersion in helmfile.yaml`) | ||||||
|  | 	f.StringArrayVar(&templateOptions.ShowOnly, "show-only", nil, `pass --show-only to "helm template"`) | ||||||
| 
 | 
 | ||||||
| 	return cmd | 	return cmd | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1964,6 +1964,7 @@ func (a *App) template(r *Run, c TemplateConfigProvider) (bool, []error) { | ||||||
| 			PostRenderer:      c.PostRenderer(), | 			PostRenderer:      c.PostRenderer(), | ||||||
| 			PostRendererArgs:  c.PostRendererArgs(), | 			PostRendererArgs:  c.PostRendererArgs(), | ||||||
| 			KubeVersion:       c.KubeVersion(), | 			KubeVersion:       c.KubeVersion(), | ||||||
|  | 			ShowOnly:          c.ShowOnly(), | ||||||
| 		} | 		} | ||||||
| 		return st.TemplateReleases(helm, c.OutputDir(), c.Values(), args, c.Concurrency(), c.Validate(), opts) | 		return st.TemplateReleases(helm, c.OutputDir(), c.Values(), args, c.Concurrency(), c.Validate(), opts) | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ func TestTemplate(t *testing.T) { | ||||||
| 		skipNeeds              bool | 		skipNeeds              bool | ||||||
| 		includeNeeds           bool | 		includeNeeds           bool | ||||||
| 		includeTransitiveNeeds bool | 		includeTransitiveNeeds bool | ||||||
|  | 		showOnly               []string | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	type testcase struct { | 	type testcase struct { | ||||||
|  | @ -131,6 +132,7 @@ releases: | ||||||
| 				skipNeeds:              tc.fields.skipNeeds, | 				skipNeeds:              tc.fields.skipNeeds, | ||||||
| 				includeNeeds:           tc.fields.includeNeeds, | 				includeNeeds:           tc.fields.includeNeeds, | ||||||
| 				includeTransitiveNeeds: tc.fields.includeTransitiveNeeds, | 				includeTransitiveNeeds: tc.fields.includeTransitiveNeeds, | ||||||
|  | 				showOnly:               tc.fields.showOnly, | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| 			var gotErr string | 			var gotErr string | ||||||
|  | @ -304,6 +306,18 @@ releases: | ||||||
| 			error:     "err: no releases found that matches specified selector(app=test_non_existent) and environment(default), in any helmfile", | 			error:     "err: no releases found that matches specified selector(app=test_non_existent) and environment(default), in any helmfile", | ||||||
| 		}) | 		}) | ||||||
| 	}) | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("show-only", func(t *testing.T) { | ||||||
|  | 		check(t, testcase{ | ||||||
|  | 			fields: fields{ | ||||||
|  | 				showOnly: []string{"templates/resources.yaml"}, | ||||||
|  | 			}, | ||||||
|  | 			selectors: []string{"name=logging"}, | ||||||
|  | 			templated: []exectest.Release{ | ||||||
|  | 				{Name: "logging", Flags: []string{"--show-only", "templates/resources.yaml", "--namespace", "kube-system"}}, | ||||||
|  | 			}, | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestTemplate_StrictParsing(t *testing.T) { | func TestTemplate_StrictParsing(t *testing.T) { | ||||||
|  |  | ||||||
|  | @ -2189,6 +2189,10 @@ func (c configImpl) KubeVersion() string { | ||||||
| 	return c.kubeVersion | 	return c.kubeVersion | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (c configImpl) ShowOnly() []string { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type applyConfig struct { | type applyConfig struct { | ||||||
| 	args    string | 	args    string | ||||||
| 	cascade string | 	cascade string | ||||||
|  | @ -2230,6 +2234,7 @@ type applyConfig struct { | ||||||
| 	postRendererArgs        []string | 	postRendererArgs        []string | ||||||
| 	kubeVersion             string | 	kubeVersion             string | ||||||
| 	suppressOutputLineRegex []string | 	suppressOutputLineRegex []string | ||||||
|  | 	showOnly                []string | ||||||
| 
 | 
 | ||||||
| 	// template-only options
 | 	// template-only options
 | ||||||
| 	includeCRDs, skipTests       bool | 	includeCRDs, skipTests       bool | ||||||
|  | @ -2406,6 +2411,10 @@ func (a applyConfig) KubeVersion() string { | ||||||
| 	return a.kubeVersion | 	return a.kubeVersion | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (a applyConfig) ShowOnly() []string { | ||||||
|  | 	return a.showOnly | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type depsConfig struct { | type depsConfig struct { | ||||||
| 	skipRepos              bool | 	skipRepos              bool | ||||||
| 	includeTransitiveNeeds bool | 	includeTransitiveNeeds bool | ||||||
|  |  | ||||||
|  | @ -233,6 +233,7 @@ type TemplateConfigProvider interface { | ||||||
| 	OutputDir() string | 	OutputDir() string | ||||||
| 	IncludeCRDs() bool | 	IncludeCRDs() bool | ||||||
| 	KubeVersion() string | 	KubeVersion() string | ||||||
|  | 	ShowOnly() []string | ||||||
| 
 | 
 | ||||||
| 	DAGConfig | 	DAGConfig | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,113 @@ | ||||||
|  | processing file "helmfile.yaml" in directory "." | ||||||
|  | changing working directory to "/path/to" | ||||||
|  | first-pass rendering starting for "helmfile.yaml.part.0": inherited=&{default  map[] map[]}, overrode=<nil> | ||||||
|  | first-pass uses: &{default  map[] map[]} | ||||||
|  | first-pass rendering output of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: logging | ||||||
|  |  3:   chart: incubator/raw | ||||||
|  |  4:   namespace: kube-system | ||||||
|  |  5:  | ||||||
|  |  6: - name: kubernetes-external-secrets | ||||||
|  |  7:   chart: incubator/raw | ||||||
|  |  8:   namespace: kube-system | ||||||
|  |  9:   needs: | ||||||
|  | 10:   - kube-system/logging | ||||||
|  | 11:  | ||||||
|  | 12: - name: external-secrets | ||||||
|  | 13:   chart: incubator/raw | ||||||
|  | 14:   namespace: default | ||||||
|  | 15:   labels: | ||||||
|  | 16:     app: test | ||||||
|  | 17:   needs: | ||||||
|  | 18:   - kube-system/kubernetes-external-secrets | ||||||
|  | 19:  | ||||||
|  | 20: - name: my-release | ||||||
|  | 21:   chart: incubator/raw | ||||||
|  | 22:   namespace: default | ||||||
|  | 23:   labels: | ||||||
|  | 24:     app: test | ||||||
|  | 25:   needs: | ||||||
|  | 26:   - default/external-secrets | ||||||
|  | 27:  | ||||||
|  | 28:  | ||||||
|  | 29: # Disabled releases are treated as missing | ||||||
|  | 30: - name: disabled | ||||||
|  | 31:   chart: incubator/raw | ||||||
|  | 32:   namespace: kube-system | ||||||
|  | 33:   installed: false | ||||||
|  | 34:  | ||||||
|  | 35: - name: test2 | ||||||
|  | 36:   chart: incubator/raw | ||||||
|  | 37:   needs: | ||||||
|  | 38:   - kube-system/disabled | ||||||
|  | 39:  | ||||||
|  | 40: - name: test3 | ||||||
|  | 41:   chart: incubator/raw | ||||||
|  | 42:   needs: | ||||||
|  | 43:   - test2 | ||||||
|  | 44:  | ||||||
|  | 
 | ||||||
|  | first-pass produced: &{default  map[] map[]} | ||||||
|  | first-pass rendering result of "helmfile.yaml.part.0": {default  map[] map[]} | ||||||
|  | vals: | ||||||
|  | map[] | ||||||
|  | defaultVals:[] | ||||||
|  | second-pass rendering result of "helmfile.yaml.part.0": | ||||||
|  |  0:  | ||||||
|  |  1: releases: | ||||||
|  |  2: - name: logging | ||||||
|  |  3:   chart: incubator/raw | ||||||
|  |  4:   namespace: kube-system | ||||||
|  |  5:  | ||||||
|  |  6: - name: kubernetes-external-secrets | ||||||
|  |  7:   chart: incubator/raw | ||||||
|  |  8:   namespace: kube-system | ||||||
|  |  9:   needs: | ||||||
|  | 10:   - kube-system/logging | ||||||
|  | 11:  | ||||||
|  | 12: - name: external-secrets | ||||||
|  | 13:   chart: incubator/raw | ||||||
|  | 14:   namespace: default | ||||||
|  | 15:   labels: | ||||||
|  | 16:     app: test | ||||||
|  | 17:   needs: | ||||||
|  | 18:   - kube-system/kubernetes-external-secrets | ||||||
|  | 19:  | ||||||
|  | 20: - name: my-release | ||||||
|  | 21:   chart: incubator/raw | ||||||
|  | 22:   namespace: default | ||||||
|  | 23:   labels: | ||||||
|  | 24:     app: test | ||||||
|  | 25:   needs: | ||||||
|  | 26:   - default/external-secrets | ||||||
|  | 27:  | ||||||
|  | 28:  | ||||||
|  | 29: # Disabled releases are treated as missing | ||||||
|  | 30: - name: disabled | ||||||
|  | 31:   chart: incubator/raw | ||||||
|  | 32:   namespace: kube-system | ||||||
|  | 33:   installed: false | ||||||
|  | 34:  | ||||||
|  | 35: - name: test2 | ||||||
|  | 36:   chart: incubator/raw | ||||||
|  | 37:   needs: | ||||||
|  | 38:   - kube-system/disabled | ||||||
|  | 39:  | ||||||
|  | 40: - name: test3 | ||||||
|  | 41:   chart: incubator/raw | ||||||
|  | 42:   needs: | ||||||
|  | 43:   - test2 | ||||||
|  | 44:  | ||||||
|  | 
 | ||||||
|  | merged environment: &{default  map[] map[]} | ||||||
|  | WARNING: release test2 needs disabled, but disabled is not installed due to installed: false. Either mark disabled as installed or remove disabled from test2's needs | ||||||
|  | 1 release(s) matching name=logging found in helmfile.yaml | ||||||
|  | 
 | ||||||
|  | processing 1 groups of releases in this order: | ||||||
|  | GROUP RELEASES | ||||||
|  | 1     default/kube-system/logging | ||||||
|  | 
 | ||||||
|  | processing releases in group 1/1: default/kube-system/logging | ||||||
|  | changing working directory back to "/path/to" | ||||||
|  | @ -38,6 +38,8 @@ type TemplateOptions struct { | ||||||
| 	PostRendererArgs []string | 	PostRendererArgs []string | ||||||
| 	// KubeVersion is the kube-version flag
 | 	// KubeVersion is the kube-version flag
 | ||||||
| 	KubeVersion string | 	KubeVersion string | ||||||
|  | 	// Propagate '--show-only` to helm template
 | ||||||
|  | 	ShowOnly []string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // NewTemplateOptions creates a new Apply
 | // NewTemplateOptions creates a new Apply
 | ||||||
|  | @ -137,3 +139,8 @@ func (t *TemplateImpl) PostRendererArgs() []string { | ||||||
| func (t *TemplateImpl) KubeVersion() string { | func (t *TemplateImpl) KubeVersion() string { | ||||||
| 	return t.TemplateOptions.KubeVersion | 	return t.TemplateOptions.KubeVersion | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // ShowOnly returns the ShowOnly.
 | ||||||
|  | func (t *TemplateImpl) ShowOnly() []string { | ||||||
|  | 	return t.TemplateOptions.ShowOnly | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -119,6 +119,20 @@ func (st *HelmState) appendCascadeFlags(flags []string, helm helmexec.Interface, | ||||||
| 	return flags | 	return flags | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // append show-only flags to helm flags
 | ||||||
|  | func (st *HelmState) appendShowOnlyFlags(flags []string, showOnly []string) []string { | ||||||
|  | 	showOnlyFlags := []string{} | ||||||
|  | 	if len(showOnly) != 0 { | ||||||
|  | 		showOnlyFlags = showOnly | ||||||
|  | 	} | ||||||
|  | 	for _, arg := range showOnlyFlags { | ||||||
|  | 		if arg != "" { | ||||||
|  | 			flags = append(flags, "--show-only", arg) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return flags | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type Chartify struct { | type Chartify struct { | ||||||
| 	Opts  *chartify.ChartifyOpts | 	Opts  *chartify.ChartifyOpts | ||||||
| 	Clean func() | 	Clean func() | ||||||
|  |  | ||||||
|  | @ -249,3 +249,30 @@ func TestAppendSuppressOutputLineRegexFlags(t *testing.T) { | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestAppendShowOnlyFlags(t *testing.T) { | ||||||
|  | 	tests := []struct { | ||||||
|  | 		name         string | ||||||
|  | 		templateOpts []string | ||||||
|  | 		expected     []string | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name:         "cli template show only with 1 file", | ||||||
|  | 			templateOpts: []string{"templates/config.yaml"}, | ||||||
|  | 			expected:     []string{"--show-only", "templates/config.yaml"}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:         "cli template show only with 2 files", | ||||||
|  | 			templateOpts: []string{"templates/config.yaml", "templates/resources.yaml"}, | ||||||
|  | 			expected:     []string{"--show-only", "templates/config.yaml", "--show-only", "templates/resources.yaml"}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  | 			st := &HelmState{} | ||||||
|  | 			got := st.appendShowOnlyFlags([]string{}, tt.templateOpts) | ||||||
|  | 			require.Equalf(t, tt.expected, got, "appendShowOnlyFlags() = %v, want %v", got, tt.expected) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1437,6 +1437,7 @@ type TemplateOpts struct { | ||||||
| 	PostRenderer      string | 	PostRenderer      string | ||||||
| 	PostRendererArgs  []string | 	PostRendererArgs  []string | ||||||
| 	KubeVersion       string | 	KubeVersion       string | ||||||
|  | 	ShowOnly          []string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type TemplateOpt interface{ Apply(*TemplateOpts) } | type TemplateOpt interface{ Apply(*TemplateOpts) } | ||||||
|  | @ -2691,15 +2692,18 @@ func (st *HelmState) flagsForTemplate(helm helmexec.Interface, release *ReleaseS | ||||||
| 	postRenderer := "" | 	postRenderer := "" | ||||||
| 	var postRendererArgs []string | 	var postRendererArgs []string | ||||||
| 	kubeVersion := "" | 	kubeVersion := "" | ||||||
|  | 	var showOnly []string | ||||||
| 	if opt != nil { | 	if opt != nil { | ||||||
| 		postRenderer = opt.PostRenderer | 		postRenderer = opt.PostRenderer | ||||||
| 		postRendererArgs = opt.PostRendererArgs | 		postRendererArgs = opt.PostRendererArgs | ||||||
| 		kubeVersion = opt.KubeVersion | 		kubeVersion = opt.KubeVersion | ||||||
|  | 		showOnly = opt.ShowOnly | ||||||
| 	} | 	} | ||||||
| 	flags = st.appendPostRenderFlags(flags, release, postRenderer) | 	flags = st.appendPostRenderFlags(flags, release, postRenderer) | ||||||
| 	flags = st.appendPostRenderArgsFlags(flags, release, postRendererArgs) | 	flags = st.appendPostRenderArgsFlags(flags, release, postRendererArgs) | ||||||
| 	flags = st.appendApiVersionsFlags(flags, release, kubeVersion) | 	flags = st.appendApiVersionsFlags(flags, release, kubeVersion) | ||||||
| 	flags = st.appendChartDownloadTLSFlags(flags, release) | 	flags = st.appendChartDownloadTLSFlags(flags, release) | ||||||
|  | 	flags = st.appendShowOnlyFlags(flags, showOnly) | ||||||
| 
 | 
 | ||||||
| 	common, files, err := st.namespaceAndValuesFlags(helm, release, workerIndex) | 	common, files, err := st.namespaceAndValuesFlags(helm, release, workerIndex) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue