fix: template helmDefaults.postRendererArgs with release data (#2583)
PR #1839 introduced template rendering for postRendererArgs, but PR #2510 reverted it while fixing a separate regression. This left helmDefaults-level postRendererArgs containing template expressions (e.g. {{ .Release.Name }}) passed to helm as literal strings instead of being resolved per-release. Add renderPostRendererArgs() that templates helmDefaults.postRendererArgs at flag-generation time using the release's template data, reusing the existing createReleaseTemplateData() helper. Release-level args are already templated by ExecuteTemplateExpressions and CLI args are static, so only the helmDefaults path needs rendering. Fixes #2580 Signed-off-by: opencode <opencode@users.noreply.github.com> Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
parent
9e6ed57015
commit
c82c61e061
|
|
@ -13,10 +13,12 @@ import (
|
|||
"github.com/helmfile/chartify"
|
||||
"helm.sh/helm/v4/pkg/storage/driver"
|
||||
|
||||
"github.com/helmfile/helmfile/pkg/filesystem"
|
||||
"github.com/helmfile/helmfile/pkg/helmexec"
|
||||
"github.com/helmfile/helmfile/pkg/kubedog"
|
||||
"github.com/helmfile/helmfile/pkg/remote"
|
||||
"github.com/helmfile/helmfile/pkg/resource"
|
||||
"github.com/helmfile/helmfile/pkg/tmpl"
|
||||
)
|
||||
|
||||
type Dependency struct {
|
||||
|
|
@ -115,7 +117,7 @@ func (st *HelmState) appendPostRenderFlags(flags []string, release *ReleaseSpec,
|
|||
}
|
||||
|
||||
// append post-renderer-args flags to helm flags
|
||||
func (st *HelmState) appendPostRenderArgsFlags(flags []string, release *ReleaseSpec, postRendererArgs []string) []string {
|
||||
func (st *HelmState) appendPostRenderArgsFlags(flags []string, release *ReleaseSpec, postRendererArgs []string) ([]string, error) {
|
||||
postRendererArgsFlags := []string{}
|
||||
switch {
|
||||
case len(release.PostRendererArgs) != 0:
|
||||
|
|
@ -123,14 +125,44 @@ func (st *HelmState) appendPostRenderArgsFlags(flags []string, release *ReleaseS
|
|||
case len(postRendererArgs) != 0:
|
||||
postRendererArgsFlags = postRendererArgs
|
||||
case len(st.HelmDefaults.PostRendererArgs) != 0:
|
||||
postRendererArgsFlags = st.HelmDefaults.PostRendererArgs
|
||||
rendered, err := st.renderPostRendererArgs(release, st.HelmDefaults.PostRendererArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
postRendererArgsFlags = rendered
|
||||
}
|
||||
for _, arg := range postRendererArgsFlags {
|
||||
if arg != "" {
|
||||
flags = append(flags, "--post-renderer-args="+arg)
|
||||
}
|
||||
}
|
||||
return flags
|
||||
return flags, nil
|
||||
}
|
||||
|
||||
func (st *HelmState) renderPostRendererArgs(release *ReleaseSpec, args []string) ([]string, error) {
|
||||
vals := st.RenderedValues
|
||||
if vals == nil {
|
||||
vals = make(map[string]any)
|
||||
}
|
||||
|
||||
fs := st.fs
|
||||
if fs == nil {
|
||||
fs = filesystem.DefaultFileSystem()
|
||||
}
|
||||
|
||||
tmplData := st.createReleaseTemplateData(release, vals)
|
||||
renderer := tmpl.NewFileRenderer(fs, st.basePath, tmplData)
|
||||
|
||||
result := make([]string, 0, len(args))
|
||||
for _, arg := range args {
|
||||
rendered, err := renderer.RenderTemplateContentToString([]byte(arg))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed rendering postRendererArg %q for release %q: %w", arg, release.Name, err)
|
||||
}
|
||||
result = append(result, rendered)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// append skip-schema-validation flags to helm flags
|
||||
|
|
|
|||
|
|
@ -3627,7 +3627,10 @@ func (st *HelmState) flagsForUpgrade(helm helmexec.Interface, release *ReleaseSp
|
|||
if opt != nil {
|
||||
postRendererArgs = opt.PostRendererArgs
|
||||
}
|
||||
flags = st.appendPostRenderArgsFlags(flags, release, postRendererArgs)
|
||||
flags, err = st.appendPostRenderArgsFlags(flags, release, postRendererArgs)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
skipSchemaValidation := false
|
||||
if opt != nil {
|
||||
|
|
@ -3670,7 +3673,10 @@ func (st *HelmState) flagsForTemplate(helm helmexec.Interface, release *ReleaseS
|
|||
skipSchemaValidation = opt.SkipSchemaValidation
|
||||
}
|
||||
flags = st.appendPostRenderFlags(flags, release, postRenderer, helm)
|
||||
flags = st.appendPostRenderArgsFlags(flags, release, postRendererArgs)
|
||||
flags, err := st.appendPostRenderArgsFlags(flags, release, postRendererArgs)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
flags = st.appendApiVersionsFlags(flags, release, kubeVersion)
|
||||
flags = st.appendChartDownloadFlags(flags, release)
|
||||
flags = st.appendShowOnlyFlags(flags, showOnly)
|
||||
|
|
@ -3793,7 +3799,11 @@ func (st *HelmState) flagsForDiff(helm helmexec.Interface, release *ReleaseSpec,
|
|||
if opt != nil {
|
||||
postRendererArgs = opt.PostRendererArgs
|
||||
}
|
||||
flags = st.appendPostRenderArgsFlags(flags, release, postRendererArgs)
|
||||
var err error
|
||||
flags, err = st.appendPostRenderArgsFlags(flags, release, postRendererArgs)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
skipSchemaValidation := false
|
||||
if opt != nil {
|
||||
|
|
@ -3823,7 +3833,6 @@ func (st *HelmState) flagsForDiff(helm helmexec.Interface, release *ReleaseSpec,
|
|||
takeOwnership = opt.TakeOwnership
|
||||
}
|
||||
|
||||
var err error
|
||||
flags, err = st.appendTakeOwnershipFlagsForDiff(flags, release, takeOwnership, pluginsDir)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
|
|||
|
|
@ -1048,6 +1048,51 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
|
|||
"--namespace", "test-namespace",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "post-renderer-args-helmdefault-templated-with-release-name",
|
||||
defaults: HelmSpec{
|
||||
Verify: false,
|
||||
CreateNamespace: &enable,
|
||||
PostRendererArgs: []string{"{{ .Release.Name }}", "--chart={{ .Release.Chart }}"},
|
||||
},
|
||||
version: semver.MustParse("3.10.0"),
|
||||
release: &ReleaseSpec{
|
||||
Chart: "test/chart",
|
||||
Version: "0.1",
|
||||
Verify: &disable,
|
||||
Name: "my-release",
|
||||
Namespace: "test-namespace",
|
||||
CreateNamespace: &disable,
|
||||
},
|
||||
want: []string{
|
||||
"--version", "0.1",
|
||||
"--post-renderer-args=my-release",
|
||||
"--post-renderer-args=--chart=test/chart",
|
||||
"--namespace", "test-namespace",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "post-renderer-args-helmdefault-templated-with-namespace",
|
||||
defaults: HelmSpec{
|
||||
Verify: false,
|
||||
CreateNamespace: &enable,
|
||||
PostRendererArgs: []string{"{{ .Release.Namespace }}/{{ .Release.Name }}"},
|
||||
},
|
||||
version: semver.MustParse("3.10.0"),
|
||||
release: &ReleaseSpec{
|
||||
Chart: "test/chart",
|
||||
Version: "0.1",
|
||||
Verify: &disable,
|
||||
Name: "my-release",
|
||||
Namespace: "test-namespace",
|
||||
CreateNamespace: &disable,
|
||||
},
|
||||
want: []string{
|
||||
"--version", "0.1",
|
||||
"--post-renderer-args=test-namespace/my-release",
|
||||
"--namespace", "test-namespace",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "description-from-release",
|
||||
defaults: HelmSpec{
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ ${kubectl} create namespace ${test_ns} || fail "Could not create namespace ${tes
|
|||
. ${dir}/test-cases/yaml-overwrite.sh
|
||||
. ${dir}/test-cases/chart-needs.sh
|
||||
. ${dir}/test-cases/postrender.sh
|
||||
. ${dir}/test-cases/postrender-defaults-args.sh
|
||||
. ${dir}/test-cases/issue-2515.sh
|
||||
. ${dir}/test-cases/chartify.sh
|
||||
. ${dir}/test-cases/deps-mr-1011.sh
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
postrender_defaults_args_case_input_dir="${cases_dir}/postrender-defaults-args/input"
|
||||
postrender_defaults_args_case_output_dir="${cases_dir}/postrender-defaults-args/output"
|
||||
|
||||
# Helm 4 requires post-renderers to be plugins
|
||||
if [ "${HELMFILE_HELM4}" = "1" ]; then
|
||||
info "Installing echo-args post-renderer plugin for Helm 4"
|
||||
${helm} plugin uninstall echo-args &>/dev/null || true
|
||||
${helm} plugin install ${postrender_defaults_args_case_input_dir}/helm-plugin-echo-args ${PLUGIN_INSTALL_FLAGS} || fail "Failed to install echo-args plugin"
|
||||
fi
|
||||
|
||||
config_file="helmfile.yaml.gotmpl"
|
||||
postrender_defaults_args_tmp=$(mktemp -d)
|
||||
|
||||
test_start "postrender-defaults-args template"
|
||||
info "Running helmfile template with helmDefaults.postRendererArgs containing {{ .Release.Name }}"
|
||||
${helmfile} -f ${postrender_defaults_args_case_input_dir}/${config_file} template --concurrency 1 &> ${postrender_defaults_args_tmp}/template.out || fail "\"helmfile template\" shouldn't fail"
|
||||
|
||||
info "Verifying that helmDefaults.postRendererArgs were templated with release names"
|
||||
grep -q "name: rendered-arg-foo" ${postrender_defaults_args_tmp}/template.out || fail "Expected postRendererArg 'foo' for release foo, but not found in output"
|
||||
grep -q "name: rendered-arg-bar" ${postrender_defaults_args_tmp}/template.out || fail "Expected postRendererArg 'bar' for release bar, but not found in output"
|
||||
|
||||
info "Verifying that literal template expression was NOT passed"
|
||||
grep -q "rendered-arg-{{ .Release.Name }}" ${postrender_defaults_args_tmp}/template.out && fail "Template expression was NOT rendered (found literal {{ .Release.Name }})"
|
||||
|
||||
test_pass "postrender-defaults-args template"
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env bash
|
||||
arg=$1
|
||||
cat
|
||||
echo "---"
|
||||
cat <<EOS
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: rendered-arg-${arg}
|
||||
data:
|
||||
arg: ${arg}
|
||||
EOS
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
arg=$2
|
||||
input=$(cat)
|
||||
|
||||
echo "$input"
|
||||
|
||||
echo "---"
|
||||
|
||||
cat <<EOS
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: rendered-arg-${arg}
|
||||
data:
|
||||
arg: ${arg}
|
||||
EOS
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
apiVersion: v1
|
||||
type: postrenderer/v1
|
||||
name: echo-args
|
||||
version: 0.1.0
|
||||
runtime: subprocess
|
||||
runtimeConfig:
|
||||
platformCommand:
|
||||
- command: ${HELM_PLUGIN_DIR}/echo-args.sh
|
||||
args:
|
||||
- ${HELM_POST_RENDERER_ARGS}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
helmDefaults:
|
||||
postRenderer: {{ if eq (env "HELMFILE_HELM4") "1" }}echo-args{{ else }}./echo-args.bash{{ end }}
|
||||
postRendererArgs:
|
||||
- "{{ `{{ .Release.Name }}` }}"
|
||||
|
||||
releases:
|
||||
- name: foo
|
||||
chart: ../../../charts/raw
|
||||
values:
|
||||
- templates:
|
||||
- |
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{`{{ .Release.Name }}`}}-1
|
||||
namespace: {{`{{ .Release.Namespace }}`}}
|
||||
data:
|
||||
foo: FOO
|
||||
- name: bar
|
||||
chart: ../../../charts/raw
|
||||
values:
|
||||
- templates:
|
||||
- |
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{`{{ .Release.Name }}`}}-2
|
||||
namespace: {{`{{ .Release.Namespace }}`}}
|
||||
data:
|
||||
bar: BAR
|
||||
Loading…
Reference in New Issue