Fix: Restrict template processing to .gotmpl files only
Co-authored-by: zhaque44 <20215376+zhaque44@users.noreply.github.com>
This commit is contained in:
parent
a7b23ac81c
commit
1bbe2c667f
|
|
@ -3,6 +3,7 @@ package state
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -110,27 +111,33 @@ func (st *HelmState) ExecuteTemplates() (*HelmState, error) {
|
||||||
release.KubeVersion = st.KubeVersion
|
release.KubeVersion = st.KubeVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
successFlag := false
|
// Only process templates if the file has .gotmpl extension
|
||||||
for it, prev := 0, release; it < 6; it++ {
|
if filepath.Ext(st.FilePath) == ".gotmpl" {
|
||||||
tmplData := st.createReleaseTemplateData(prev, vals)
|
successFlag := false
|
||||||
renderer := tmpl.NewFileRenderer(st.fs, st.basePath, tmplData)
|
for it, prev := 0, release; it < 6; it++ {
|
||||||
r, err := release.ExecuteTemplateExpressions(renderer)
|
tmplData := st.createReleaseTemplateData(prev, vals)
|
||||||
if err != nil {
|
renderer := tmpl.NewFileRenderer(st.fs, st.basePath, tmplData)
|
||||||
return nil, fmt.Errorf("failed executing templates in release \"%s\".\"%s\": %v", st.FilePath, release.Name, err)
|
r, err := release.ExecuteTemplateExpressions(renderer)
|
||||||
}
|
if err != nil {
|
||||||
if reflect.DeepEqual(prev, r) {
|
|
||||||
successFlag = true
|
|
||||||
if err := updateBoolTemplatedValues(r); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed executing templates in release \"%s\".\"%s\": %v", st.FilePath, release.Name, err)
|
return nil, fmt.Errorf("failed executing templates in release \"%s\".\"%s\": %v", st.FilePath, release.Name, err)
|
||||||
}
|
}
|
||||||
st.Releases[i] = *r
|
if reflect.DeepEqual(prev, r) {
|
||||||
break
|
successFlag = true
|
||||||
|
if err := updateBoolTemplatedValues(r); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed executing templates in release \"%s\".\"%s\": %v", st.FilePath, release.Name, err)
|
||||||
|
}
|
||||||
|
st.Releases[i] = *r
|
||||||
|
break
|
||||||
|
}
|
||||||
|
prev = r
|
||||||
}
|
}
|
||||||
prev = r
|
if !successFlag {
|
||||||
}
|
return nil, fmt.Errorf("failed executing templates in release \"%s\".\"%s\": %s", st.FilePath, release.Name,
|
||||||
if !successFlag {
|
"recursive references can't be resolved")
|
||||||
return nil, fmt.Errorf("failed executing templates in release \"%s\".\"%s\": %s", st.FilePath, release.Name,
|
}
|
||||||
"recursive references can't be resolved")
|
} else {
|
||||||
|
// For non-.gotmpl files, skip template processing entirely
|
||||||
|
st.Releases[i] = *release
|
||||||
}
|
}
|
||||||
|
|
||||||
if st.Releases[i].Chart == "" {
|
if st.Releases[i].Chart == "" {
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@ func TestHelmState_executeTemplates(t *testing.T) {
|
||||||
fs: &filesystem.FileSystem{
|
fs: &filesystem.FileSystem{
|
||||||
Glob: func(s string) ([]string, error) { return nil, nil }},
|
Glob: func(s string) ([]string, error) { return nil, nil }},
|
||||||
basePath: ".",
|
basePath: ".",
|
||||||
|
FilePath: "helmfile.yaml.gotmpl", // Set to .gotmpl to enable template processing
|
||||||
ReleaseSetSpec: ReleaseSetSpec{
|
ReleaseSetSpec: ReleaseSetSpec{
|
||||||
HelmDefaults: HelmSpec{
|
HelmDefaults: HelmSpec{
|
||||||
KubeContext: "test_context",
|
KubeContext: "test_context",
|
||||||
|
|
@ -269,6 +270,7 @@ func TestHelmState_recursiveRefsTemplates(t *testing.T) {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
state := &HelmState{
|
state := &HelmState{
|
||||||
basePath: ".",
|
basePath: ".",
|
||||||
|
FilePath: "helmfile.yaml.gotmpl", // Set to .gotmpl to enable template processing for error tests
|
||||||
fs: &filesystem.FileSystem{
|
fs: &filesystem.FileSystem{
|
||||||
Glob: func(s string) ([]string, error) { return nil, nil },
|
Glob: func(s string) ([]string, error) { return nil, nil },
|
||||||
},
|
},
|
||||||
|
|
@ -294,3 +296,97 @@ func TestHelmState_recursiveRefsTemplates(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHelmState_executeTemplates_yaml_vs_gotmpl(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
filePath string
|
||||||
|
input ReleaseSpec
|
||||||
|
want ReleaseSpec
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "YAML file should NOT process templates",
|
||||||
|
filePath: "helmfile.yaml",
|
||||||
|
input: ReleaseSpec{
|
||||||
|
Chart: "test-charts/{{ .Release.Name }}",
|
||||||
|
Version: "{{ .Release.Name }}-0.1",
|
||||||
|
Name: "test-app",
|
||||||
|
Namespace: "test-namespace-{{ .Release.Name }}",
|
||||||
|
Labels: map[string]string{"id": "{{ .Release.Name }}"},
|
||||||
|
},
|
||||||
|
want: ReleaseSpec{
|
||||||
|
Chart: "test-charts/{{ .Release.Name }}", // Template NOT processed
|
||||||
|
Version: "{{ .Release.Name }}-0.1", // Template NOT processed
|
||||||
|
Name: "test-app",
|
||||||
|
Namespace: "test-namespace-{{ .Release.Name }}", // Template NOT processed
|
||||||
|
Labels: map[string]string{"id": "{{ .Release.Name }}"}, // Template NOT processed
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "GOTMPL file should process templates",
|
||||||
|
filePath: "helmfile.yaml.gotmpl",
|
||||||
|
input: ReleaseSpec{
|
||||||
|
Chart: "test-charts/{{ .Release.Name }}",
|
||||||
|
Version: "{{ .Release.Name }}-0.1",
|
||||||
|
Name: "test-app",
|
||||||
|
Namespace: "test-namespace-{{ .Release.Name }}",
|
||||||
|
Labels: map[string]string{"id": "{{ .Release.Name }}"},
|
||||||
|
},
|
||||||
|
want: ReleaseSpec{
|
||||||
|
Chart: "test-charts/test-app", // Template processed
|
||||||
|
Version: "test-app-0.1", // Template processed
|
||||||
|
Name: "test-app",
|
||||||
|
Namespace: "test-namespace-test-app", // Template processed
|
||||||
|
Labels: map[string]string{"id": "test-app"}, // Template processed
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range tests {
|
||||||
|
tt := tests[i]
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
state := &HelmState{
|
||||||
|
fs: &filesystem.FileSystem{
|
||||||
|
Glob: func(s string) ([]string, error) { return nil, nil }},
|
||||||
|
basePath: ".",
|
||||||
|
FilePath: tt.filePath, // This is the key difference
|
||||||
|
ReleaseSetSpec: ReleaseSetSpec{
|
||||||
|
HelmDefaults: HelmSpec{
|
||||||
|
KubeContext: "test_context",
|
||||||
|
},
|
||||||
|
Env: environment.Environment{Name: "test_env"},
|
||||||
|
OverrideNamespace: "test-namespace_",
|
||||||
|
Repositories: nil,
|
||||||
|
Releases: []ReleaseSpec{
|
||||||
|
tt.input,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RenderedValues: map[string]any{},
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := state.ExecuteTemplates()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := r.Releases[0]
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual.Name, tt.want.Name) {
|
||||||
|
t.Errorf("expected Name %+v, got %+v", tt.want.Name, actual.Name)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(actual.Chart, tt.want.Chart) {
|
||||||
|
t.Errorf("expected Chart %+v, got %+v", tt.want.Chart, actual.Chart)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(actual.Namespace, tt.want.Namespace) {
|
||||||
|
t.Errorf("expected Namespace %+v, got %+v", tt.want.Namespace, actual.Namespace)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(actual.Version, tt.want.Version) {
|
||||||
|
t.Errorf("expected Version %+v, got %+v", tt.want.Version, actual.Version)
|
||||||
|
}
|
||||||
|
if diff := deep.Equal(actual.Labels, tt.want.Labels); diff != nil && len(actual.Labels) > 0 {
|
||||||
|
t.Errorf("Labels differs \n%+v", strings.Join(diff, "\n"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue