Add "PostRendererArgs" option to be passed to helm (#1133)

* Add "PostRendererArgs" option to be passed to helm

This allows using PowerShell scripts on Windows as Post Renderer.

Signed-off-by: Maarten Boekhold <maarten.boekhold@finastra.com>
This commit is contained in:
Maarten Boekhold 2023-11-21 17:32:14 +04:00 committed by GitHub
parent b764b4ceed
commit d0b8d7ee5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 160 additions and 57 deletions

View File

@ -66,6 +66,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.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.StringArrayVar(&applyOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`)
f.StringVar(&applyOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background")
return cmd

View File

@ -53,6 +53,7 @@ func NewDiffCmd(globalCfg *config.GlobalImpl) *cobra.Command {
f.BoolVar(&diffOptions.ReuseValues, "reuse-values", false, `Override helmDefaults.reuseValues "helm diff upgrade --install --reuse-values"`)
f.BoolVar(&diffOptions.ResetValues, "reset-values", false, `Override helmDefaults.reuseValues "helm diff upgrade --install --reset-values"`)
f.StringVar(&diffOptions.PostRenderer, "post-renderer", "", `pass --post-renderer to "helm template" or "helm upgrade --install"`)
f.StringArrayVar(&diffOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`)
return cmd
}

View File

@ -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.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.StringArrayVar(&syncOptions.PostRendererArgs, "post-renderer-args", nil, `pass --post-renderer-args to "helm template" or "helm upgrade --install"`)
f.StringVar(&syncOptions.Cascade, "cascade", "", "pass cascade to helm exec, default: background")
return cmd

View File

@ -45,6 +45,7 @@ func NewTemplateCmd(globalCfg *config.GlobalImpl) *cobra.Command {
f.BoolVar(&templateOptions.IncludeTransitiveNeeds, "include-transitive-needs", false, `like --include-needs, but also includes transitive needs (needs of needs). Does nothing when --selector/-l flag is not provided. Overrides exclusions of other selectors and conditions.`)
f.BoolVar(&templateOptions.SkipCleanup, "skip-cleanup", false, "Stop cleaning up temporary values generated by helmfile and helm-secrets. Useful for debugging. Don't use in production for security")
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.StringVar(&templateOptions.KubeVersion, "kube-version", "", `pass --kube-version to "helm template". Overrides kubeVersion in helmfile.yaml`)
return cmd

View File

@ -211,6 +211,12 @@ helmDefaults:
reuseValues: false
# propagate `--post-renderer` to helmv3 template and helm install
postRenderer: "path/to/postRenderer"
# propagate `--post-renderer-args` to helmv3 template and helm install. This allows using Powershell
# scripts on Windows as a post renderer
postRendererArgs:
- PowerShell
- "-Command"
- "theScript.ps1"
# cascade `--cascade` to helmv3 delete, available values: background, foreground, or orphan, default: background
cascade: "background"
# insecureSkipTLSVerify is true if the TLS verification should be skipped when fetching remote chart
@ -314,6 +320,12 @@ releases:
skipDeps: false
# propagate `--post-renderer` to helmv3 template and helm install
postRenderer: "path/to/postRenderer"
# propagate `--post-renderer-args` to helmv3 template and helm install. This allows using Powershell
# scripts on Windows as a post renderer
postRendererArgs:
- PowerShell
- "-Command"
- "theScript.ps1"
# cascade `--cascade` to helmv3 delete, available values: background, foreground, or orphan, default: background
cascade: "background"
# insecureSkipTLSVerify is true if the TLS verification should be skipped when fetching remote chart

View File

@ -1370,6 +1370,7 @@ func (a *App) apply(r *Run, c ApplyConfigProvider) (bool, bool, []error) {
ResetValues: c.ResetValues(),
DiffArgs: c.DiffArgs(),
PostRenderer: c.PostRenderer(),
PostRendererArgs: c.PostRendererArgs(),
}
infoMsg, releasesToBeUpdated, releasesToBeDeleted, errs := r.diff(false, detailedExitCode, c, diffOpts)
@ -1472,14 +1473,15 @@ Do you really want to apply?
subst.Releases = rs
syncOpts := &state.SyncOpts{
Set: c.Set(),
SkipCleanup: c.RetainValuesFiles() || c.SkipCleanup(),
SkipCRDs: c.SkipCRDs(),
Wait: c.Wait(),
WaitForJobs: c.WaitForJobs(),
ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
PostRenderer: c.PostRenderer(),
Set: c.Set(),
SkipCleanup: c.RetainValuesFiles() || c.SkipCleanup(),
SkipCRDs: c.SkipCRDs(),
Wait: c.Wait(),
WaitForJobs: c.WaitForJobs(),
ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
PostRenderer: c.PostRenderer(),
PostRendererArgs: c.PostRendererArgs(),
}
return subst.SyncReleases(&affectedReleases, helm, c.Values(), c.Concurrency(), syncOpts)
}))
@ -1604,6 +1606,7 @@ func (a *App) diff(r *Run, c DiffConfigProvider) (*string, bool, bool, []error)
ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
PostRenderer: c.PostRenderer(),
PostRendererArgs: c.PostRendererArgs(),
}
filtered := &Run{
@ -1863,13 +1866,14 @@ Do you really want to sync?
subst.Releases = rs
opts := &state.SyncOpts{
Set: c.Set(),
SkipCRDs: c.SkipCRDs(),
Wait: c.Wait(),
WaitForJobs: c.WaitForJobs(),
ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
PostRenderer: c.PostRenderer(),
Set: c.Set(),
SkipCRDs: c.SkipCRDs(),
Wait: c.Wait(),
WaitForJobs: c.WaitForJobs(),
ReuseValues: c.ReuseValues(),
ResetValues: c.ResetValues(),
PostRenderer: c.PostRenderer(),
PostRendererArgs: c.PostRendererArgs(),
}
return subst.SyncReleases(&affectedReleases, helm, c.Values(), c.Concurrency(), opts)
}))
@ -1903,6 +1907,7 @@ func (a *App) template(r *Run, c TemplateConfigProvider) (bool, []error) {
SkipCleanup: c.SkipCleanup(),
SkipTests: c.SkipTests(),
PostRenderer: c.PostRenderer(),
PostRendererArgs: c.PostRendererArgs(),
KubeVersion: c.KubeVersion(),
}
return st.TemplateReleases(helm, c.OutputDir(), c.Values(), args, c.Concurrency(), c.Validate(), opts)

View File

@ -2181,6 +2181,10 @@ func (c configImpl) PostRenderer() string {
return ""
}
func (c configImpl) PostRendererArgs() []string {
return nil
}
func (c configImpl) KubeVersion() string {
return c.kubeVersion
}
@ -2222,6 +2226,7 @@ type applyConfig struct {
waitForJobs bool
reuseValues bool
postRenderer string
postRendererArgs []string
kubeVersion string
// template-only options
@ -2383,6 +2388,10 @@ func (a applyConfig) PostRenderer() string {
return a.postRenderer
}
func (a applyConfig) PostRendererArgs() []string {
return a.postRendererArgs
}
func (a applyConfig) KubeVersion() string {
return a.kubeVersion
}

View File

@ -48,6 +48,7 @@ type ReposConfigProvider interface {
type ApplyConfigProvider interface {
Args() string
PostRenderer() string
PostRendererArgs() []string
Cascade() string
Values() []string
@ -93,6 +94,7 @@ type ApplyConfigProvider interface {
type SyncConfigProvider interface {
Args() string
PostRenderer() string
PostRendererArgs() []string
Cascade() string
Values() []string
@ -118,6 +120,7 @@ type SyncConfigProvider interface {
type DiffConfigProvider interface {
Args() string
PostRenderer() string
PostRendererArgs() []string
Values() []string
Set() []string
@ -209,6 +212,7 @@ type FetchConfigProvider interface {
type TemplateConfigProvider interface {
Args() string
PostRenderer() string
PostRendererArgs() []string
Values() []string
Set() []string

View File

@ -164,6 +164,10 @@ func (a diffConfig) PostRenderer() string {
return ""
}
func (a diffConfig) PostRendererArgs() []string {
return nil
}
func TestDiff(t *testing.T) {
type flags struct {
skipNeeds bool

View File

@ -58,6 +58,8 @@ type ApplyOptions struct {
ResetValues bool
// Propagate '--post-renderer' to helmv3 template and helm install
PostRenderer string
// Propagate '--post-renderer-args' to helmv3 template and helm install
PostRendererArgs []string
// Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background
Cascade string
}
@ -222,6 +224,11 @@ func (a *ApplyImpl) PostRenderer() string {
return a.ApplyOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (a *ApplyImpl) PostRendererArgs() []string {
return a.ApplyOptions.PostRendererArgs
}
// Cascade returns cascade flag
func (a *ApplyImpl) Cascade() string {
return a.ApplyOptions.Cascade

View File

@ -42,6 +42,8 @@ type DiffOptions struct {
ResetValues bool
// Propagate '--post-renderer' to helmv3 template and helm install
PostRenderer string
// Propagate '--post-renderer-args' to helmv3 template and helm install
PostRendererArgs []string
// DiffArgs is the list of arguments to pass to helm-diff.
DiffArgs string
}
@ -185,3 +187,8 @@ func (t *DiffImpl) ResetValues() bool {
func (t *DiffImpl) PostRenderer() string {
return t.DiffOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (t *DiffImpl) PostRendererArgs() []string {
return t.DiffOptions.PostRendererArgs
}

View File

@ -28,6 +28,8 @@ type SyncOptions struct {
ResetValues bool
// Propagate '--post-renderer' to helmv3 template and helm install
PostRenderer string
// Propagate '--post-renderer-args' to helmv3 template and helm install
PostRendererArgs []string
// Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background
Cascade string
}
@ -121,6 +123,11 @@ func (t *SyncImpl) PostRenderer() string {
return t.SyncOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (t *SyncImpl) PostRendererArgs() []string {
return t.SyncOptions.PostRendererArgs
}
// Cascade returns cascade flag
func (t *SyncImpl) Cascade() string {
return t.SyncOptions.Cascade

View File

@ -34,6 +34,8 @@ type TemplateOptions struct {
SkipCleanup bool
// Propagate '--post-renderer' to helmv3 template and helm install
PostRenderer string
// Propagate '--post-renderer-args' to helmv3 template and helm install
PostRendererArgs []string
// KubeVersion is the kube-version flag
KubeVersion string
}
@ -126,6 +128,11 @@ func (t *TemplateImpl) PostRenderer() string {
return t.TemplateOptions.PostRenderer
}
// PostRendererArgs returns the PostRendererArgs.
func (t *TemplateImpl) PostRendererArgs() []string {
return t.TemplateOptions.PostRendererArgs
}
// KubeVersion returns the the KubeVersion.
func (t *TemplateImpl) KubeVersion() string {
return t.TemplateOptions.KubeVersion

View File

@ -39,6 +39,31 @@ func (st *HelmState) appendPostRenderFlags(flags []string, release *ReleaseSpec,
return flags
}
// append post-renderer-args flags to helm flags
func (st *HelmState) appendPostRenderArgsFlags(flags []string, release *ReleaseSpec, postRendererArgs []string) []string {
switch {
case len(release.PostRendererArgs) != 0:
for _, arg := range release.PostRendererArgs {
if arg != "" {
flags = append(flags, "--post-renderer-args", arg)
}
}
case len(postRendererArgs) != 0:
for _, arg := range postRendererArgs {
if arg != "" {
flags = append(flags, "--post-renderer-args", arg)
}
}
case len(st.HelmDefaults.PostRendererArgs) != 0:
for _, arg := range st.HelmDefaults.PostRendererArgs {
if arg != "" {
flags = append(flags, "--post-renderer-args", arg)
}
}
}
return flags
}
func (st *HelmState) appendWaitForJobsFlags(flags []string, release *ReleaseSpec, ops *SyncOpts) []string {
switch {
case release.WaitForJobs != nil && *release.WaitForJobs:

View File

@ -183,6 +183,8 @@ type HelmSpec struct {
ReuseValues bool `yaml:"reuseValues"`
// Propagate '--post-renderer' to helmv3 template and helm install
PostRenderer *string `yaml:"postRenderer,omitempty"`
// Propagate '--post-renderer-args' to helmv3 template and helm install
PostRendererArgs []string `yaml:"postRendererArgs,omitempty"`
// Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background
Cascade *string `yaml:"cascade,omitempty"`
@ -357,6 +359,9 @@ type ReleaseSpec struct {
// Propagate '--post-renderer' to helmv3 template and helm install
PostRenderer *string `yaml:"postRenderer,omitempty"`
// Propagate '--post-renderer-args' to helmv3 template and helm install
PostRendererArgs []string `yaml:"postRendererArgs,omitempty"`
// Cascade '--cascade' to helmv3 delete, available values: background, foreground, or orphan, default: background
Cascade *string `yaml:"cascade,omitempty"`
@ -711,14 +716,15 @@ func (st *HelmState) DetectReleasesToBeDeleted(helm helmexec.Interface, releases
}
type SyncOpts struct {
Set []string
SkipCleanup bool
SkipCRDs bool
Wait bool
WaitForJobs bool
ReuseValues bool
ResetValues bool
PostRenderer string
Set []string
SkipCleanup bool
SkipCRDs bool
Wait bool
WaitForJobs bool
ReuseValues bool
ResetValues bool
PostRenderer string
PostRendererArgs []string
}
type SyncOpt interface{ Apply(*SyncOpts) }
@ -1393,6 +1399,7 @@ type TemplateOpts struct {
IncludeCRDs bool
SkipTests bool
PostRenderer string
PostRendererArgs []string
KubeVersion string
}
@ -1914,6 +1921,7 @@ type DiffOpts struct {
ReuseValues bool
ResetValues bool
PostRenderer string
PostRendererArgs []string
}
func (o *DiffOpts) Apply(opts *DiffOpts) {
@ -2567,6 +2575,12 @@ func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSp
}
flags = st.appendPostRenderFlags(flags, release, postRenderer)
var postRendererArgs []string
if opt != nil {
postRendererArgs = opt.PostRendererArgs
}
flags = st.appendPostRenderArgsFlags(flags, release, postRendererArgs)
common, clean, err := st.namespaceAndValuesFlags(helm, release, workerIndex)
if err != nil {
return nil, clean, err
@ -2582,12 +2596,15 @@ func (st *HelmState) flagsForTemplate(helm helmexec.Interface, release *ReleaseS
flags = st.appendHelmXFlags(flags, release)
postRenderer := ""
var postRendererArgs []string
kubeVersion := ""
if opt != nil {
postRenderer = opt.PostRenderer
postRendererArgs = opt.PostRendererArgs
kubeVersion = opt.KubeVersion
}
flags = st.appendPostRenderFlags(flags, release, postRenderer)
flags = st.appendPostRenderArgsFlags(flags, release, postRendererArgs)
flags = st.appendApiVersionsFlags(flags, release, kubeVersion)
flags = st.appendChartDownloadTLSFlags(flags, release)
@ -2653,6 +2670,12 @@ func (st *HelmState) flagsForDiff(helm helmexec.Interface, release *ReleaseSpec,
}
flags = st.appendPostRenderFlags(flags, release, postRenderer)
var postRendererArgs []string
if opt != nil {
postRendererArgs = opt.PostRendererArgs
}
flags = st.appendPostRenderArgsFlags(flags, release, postRendererArgs)
common, files, err := st.namespaceAndValuesFlags(helm, release, workerIndex)
if err != nil {
return nil, files, err

View File

@ -38,39 +38,39 @@ func TestGenerateID(t *testing.T) {
run(testcase{
subject: "baseline",
release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"},
want: "foo-values-6749dfb776",
want: "foo-values-c7464bdc5",
})
run(testcase{
subject: "different bytes content",
release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"},
data: []byte(`{"k":"v"}`),
want: "foo-values-84f9645959",
want: "foo-values-79f8658596",
})
run(testcase{
subject: "different map content",
release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"},
data: map[string]any{"k": "v"},
want: "foo-values-7774fccb4f",
want: "foo-values-7996cc88d6",
})
run(testcase{
subject: "different chart",
release: ReleaseSpec{Name: "foo", Chart: "stable/envoy"},
want: "foo-values-5cdf68c495",
want: "foo-values-7cdb6bd8b6",
})
run(testcase{
subject: "different name",
release: ReleaseSpec{Name: "bar", Chart: "incubator/raw"},
want: "bar-values-758d78db87",
want: "bar-values-59cd6576c4",
})
run(testcase{
subject: "specific ns",
release: ReleaseSpec{Name: "foo", Chart: "incubator/raw", Namespace: "myns"},
want: "myns-foo-values-6888c4f5bf",
want: "myns-foo-values-5d5d46c98d",
})
for id, n := range ids {

View File

@ -27,7 +27,7 @@ test_start "postrender diff"
info "Comparing postrender diff output ${postrender_diff_reverse} with ${postrender_case_output_dir}/result.yaml"
for i in $(seq 10); do
info "Comparing build/postrender-diff #$i"
${helmfile} -f ${postrender_case_input_dir}/${config_file} diff --concurrency 1 --post-renderer ./add-cm1.bash &> ${postrender_diff_reverse} || fail "\"helmfile diff\" shouldn't fail"
${helmfile} -f ${postrender_case_input_dir}/${config_file} diff --concurrency 1 --post-renderer ./add-cm.bash --post-renderer-args cm1 &> ${postrender_diff_reverse} || fail "\"helmfile diff\" shouldn't fail"
diff -u ${postrender_diff_out_file} ${postrender_diff_reverse} || fail "\"helmfile diff\" should be consistent"
echo code=$?
done
@ -37,7 +37,7 @@ test_start "postrender template"
info "Comparing postrender template output ${postrender_template_reverse} with ${postrender_case_output_dir}/result.yaml"
for i in $(seq 10); do
info "Comparing build/postrender-diff #$i"
${helmfile} -f ${postrender_case_input_dir}/${config_file} template --concurrency 1 --post-renderer ./add-cm1.bash &> ${postrender_template_reverse} || fail "\"helmfile template\" shouldn't fail"
${helmfile} -f ${postrender_case_input_dir}/${config_file} template --concurrency 1 --post-renderer ./add-cm.bash --post-renderer-args cm1 &> ${postrender_template_reverse} || fail "\"helmfile template\" shouldn't fail"
diff -u ${postrender_template_out_file} ${postrender_template_reverse} || fail "\"helmfile template\" should be consistent"
echo code=$?
done

View File

@ -1,13 +1,13 @@
#!/usr/bin/env bash
cat $1
configmap_name=$1
cat
echo "---"
cat <<EOS
apiVersion: v1
kind: ConfigMap
data:
one: ONE
name: ${configmap_name}
metadata:
name: cm1
name: ${configmap_name}
EOS

View File

@ -1,13 +0,0 @@
#!/usr/bin/env bash
cat $1
echo "---"
cat <<EOS
apiVersion: v1
kind: ConfigMap
data:
two: TWO
metadata:
name: cm2
EOS

View File

@ -21,7 +21,9 @@ releases:
namespace: {{`{{ .Release.Namespace }}`}}
data:
bar: BAR
postRenderer: ./add-cm2.bash
postRenderer: ./add-cm.bash
postRendererArgs:
- cm2
- name: baz
chart: ../../../charts/raw
values:

View File

@ -11,7 +11,7 @@ helmfile-tests, cm2, ConfigMap (v1) has been added:
+ apiVersion: v1
+ kind: ConfigMap
+ data:
+ two: TWO
+ name: cm2
+ metadata:
+ name: cm2
helmfile-tests, foo-1, ConfigMap (v1) has been added:
@ -46,7 +46,7 @@ helmfile-tests, cm1, ConfigMap (v1) has been added:
+ apiVersion: v1
+ kind: ConfigMap
+ data:
+ one: ONE
+ name: cm1
+ metadata:
+ name: cm1

View File

@ -11,7 +11,7 @@ helmfile-tests, cm2, ConfigMap (v1) has been added:
+ apiVersion: v1
+ kind: ConfigMap
+ data:
+ two: TWO
+ name: cm2
+ metadata:
+ name: cm2
helmfile-tests, foo-1, ConfigMap (v1) has been added:
@ -44,7 +44,7 @@ helmfile-tests, cm1, ConfigMap (v1) has been added:
+ apiVersion: v1
+ kind: ConfigMap
+ data:
+ one: ONE
+ name: cm1
+ metadata:
+ name: cm1
Comparing release=foo, chart=../../../charts/raw

View File

@ -14,7 +14,7 @@ data:
apiVersion: v1
kind: ConfigMap
data:
two: TWO
name: cm2
metadata:
name: cm2
@ -32,7 +32,7 @@ data:
apiVersion: v1
kind: ConfigMap
data:
one: ONE
name: cm1
metadata:
name: cm1

View File

@ -15,7 +15,7 @@ data:
apiVersion: v1
kind: ConfigMap
data:
two: TWO
name: cm2
metadata:
name: cm2
@ -33,7 +33,7 @@ data:
apiVersion: v1
kind: ConfigMap
data:
one: ONE
name: cm1
metadata:
name: cm1