diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..008074e26 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "go.formatTool": "gofmt" +} \ No newline at end of file diff --git a/pkg/tanka/export.go b/pkg/tanka/export.go index 8916bd0ac..69109595f 100644 --- a/pkg/tanka/export.go +++ b/pkg/tanka/export.go @@ -175,7 +175,7 @@ func writeExportFile(path string, data []byte) error { func createTemplate(format string, env manifest.Manifest) (*template.Template, error) { // Replace all os.path separators in string with BelRune for creating subfolders - replaceFormat := strings.Replace(format, string(os.PathSeparator), BelRune, -1) + replaceFormat := replaceTmplText(format, string(os.PathSeparator), BelRune) envMap := template.FuncMap{"env": func() manifest.Manifest { return env }} @@ -189,6 +189,24 @@ func createTemplate(format string, env manifest.Manifest) (*template.Template, e return template, nil } +func replaceTmplText(s, old, new string) string { + parts := []string{} + l := strings.Index(s, "{{") + r := strings.Index(s, "}}") + 2 + + for l != -1 && l < r { + // replace only in text between template action blocks + text := strings.ReplaceAll(s[:l], old, new) + action := s[l:r] + parts = append(parts, text, action) + s = s[r:] + l = strings.Index(s, "{{") + r = strings.Index(s, "}}") + 2 + } + parts = append(parts, strings.ReplaceAll(s, old, new)) + return strings.Join(parts, "") +} + func applyTemplate(template *template.Template, m manifest.Manifest) (path string, err error) { buf := bytes.Buffer{} if err := template.Execute(&buf, m); err != nil { diff --git a/pkg/tanka/export_test.go b/pkg/tanka/export_test.go new file mode 100644 index 000000000..9663c6952 --- /dev/null +++ b/pkg/tanka/export_test.go @@ -0,0 +1,33 @@ +package tanka + +import "testing" + +func Test_replaceTmplText(t *testing.T) { + type args struct { + s string + old string + new string + } + tests := []struct { + name string + args args + want string + }{ + {"text only", args{"a", "a", "b"}, "b"}, + {"action blocks", args{"{{a}}{{.}}", "a", "b"}, "{{a}}{{.}}"}, + {"mixed", args{"a{{a}}a{{a}}a", "a", "b"}, "b{{a}}b{{a}}b"}, + {"invalid template format handled as text", args{"a}}a{{a", "a", "b"}, "b}}b{{b"}, + { + name: "keep path separator in action block", + args: args{`{{index .metadata.labels "app.kubernetes.io/name"}}/{{.metadata.name}}`, "/", BelRune}, + want: "{{index .metadata.labels \"app.kubernetes.io/name\"}}\u0007{{.metadata.name}}", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := replaceTmplText(tt.args.s, tt.args.old, tt.args.new); got != tt.want { + t.Errorf("replaceInTmplText() = %v, want %v", got, tt.want) + } + }) + } +}