Skip to content

Commit

Permalink
fix: make export --format respect "/" in template actions
Browse files Browse the repository at this point in the history
During tk export path separators are temporarily replaced with BEL in
order to protect paths from being mixed with template output. But when
there is a slash in a template action (e.g. {{index .metadata.labels
"app.kubernetes.io/name"}}, that slash also got replaced, and the
template did not work as expected.

This fix ensures that the BEL replacement only occurs within the text
portions of the template, and the action blocks are being preserved.

Fixes #568
  • Loading branch information
dewe committed Jun 14, 2021
1 parent 60775d3 commit 55e9359
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"go.formatTool": "gofmt"
}
20 changes: 19 additions & 1 deletion pkg/tanka/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}

Expand All @@ -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 {
Expand Down
33 changes: 33 additions & 0 deletions pkg/tanka/export_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
})
}
}

0 comments on commit 55e9359

Please sign in to comment.