From d262e3dfaa27c25903d507b5fc988280ed52a037 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Tue, 6 Sep 2022 13:15:50 +0200 Subject: [PATCH] pkg/report: handle newline in template string Docker tries to be smart and replaces \n with the actual newline character. For compat we do the same but this will break formats such as '{{printf "\n"}}' To be backwards compatible with the previous behavior we try to replace and parse the template. If it fails use the original text and parse again. This fix will not be enough. It requires many changes in podman since most commands will do their own NormalizeFormat() call before using this backend which seems wrong and creates a lot of duplication. This has to be fixed in Podman. Required for https://bugzilla.redhat.com/show_bug.cgi?id=2059658 and https://github.com/containers/podman/issues/13446. Signed-off-by: Paul Holzinger --- pkg/report/formatter.go | 20 +++++++++++++++----- pkg/report/formatter_test.go | 2 ++ pkg/report/template_test.go | 4 ++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/pkg/report/formatter.go b/pkg/report/formatter.go index 1772f8765..22626fca1 100644 --- a/pkg/report/formatter.go +++ b/pkg/report/formatter.go @@ -59,16 +59,22 @@ type Formatter struct { func (f *Formatter) Parse(origin Origin, text string) (*Formatter, error) { f.Origin = origin + // docker tries to be smart and replaces \n with the actual newline character. + // For compat we do the same but this will break formats such as '{{printf "\n"}}' + // To be backwards compatible with the previous behavior we try to replace and + // parse the template. If it fails use the original text and parse again. + var normText string switch { case strings.HasPrefix(text, "table "): f.RenderTable = true - text = "{{range .}}" + NormalizeFormat(text) + "{{end -}}" + normText = "{{range .}}" + NormalizeFormat(text) + "{{end -}}" + text = "{{range .}}" + text + "{{end -}}" case OriginUser == origin: - text = EnforceRange(NormalizeFormat(text)) + normText = EnforceRange(NormalizeFormat(text)) + text = EnforceRange(text) default: - text = NormalizeFormat(text) + normText = NormalizeFormat(text) } - f.text = text if f.RenderTable || origin == OriginPodman { tw := tabwriter.NewWriter(f.writer, 12, 2, 2, ' ', tabwriter.StripEscape) @@ -77,10 +83,14 @@ func (f *Formatter) Parse(origin Origin, text string) (*Formatter, error) { f.RenderHeaders = true } - tmpl, err := f.template.Funcs(template.FuncMap(DefaultFuncs)).Parse(text) + tmpl, err := f.template.Funcs(template.FuncMap(DefaultFuncs)).Parse(normText) if err != nil { + tmpl, err = f.template.Funcs(template.FuncMap(DefaultFuncs)).Parse(text) + f.template = tmpl + f.text = text return f, err } + f.text = normText f.template = tmpl return f, nil } diff --git a/pkg/report/formatter_test.go b/pkg/report/formatter_test.go index c828dcdf2..d84935c3e 100644 --- a/pkg/report/formatter_test.go +++ b/pkg/report/formatter_test.go @@ -82,6 +82,8 @@ func TestFormatter_ParseTable(t *testing.T) { }, {&bytes.Buffer{}, OriginUser, "{{range .}}{{.ID}}\tID\n{{end}}", "c061a0839e\tID\nf10fc2e11057\tID\n1eb6fab5aa8f4b5cbfd3e66aa35e9b2a\tID\n\n"}, {&bytes.Buffer{}, OriginUser, `{{range .}}{{.ID}}{{end -}}`, "c061a0839ef10fc2e110571eb6fab5aa8f4b5cbfd3e66aa35e9b2a"}, + // regression test for https://bugzilla.redhat.com/show_bug.cgi?id=2059658 and https://github.com/containers/podman/issues/13446 + {&bytes.Buffer{}, OriginUser, `{{range .}}{{printf "\n"}}{{end -}}`, "\n\n\n"}, } for loop, tc := range testCase { diff --git a/pkg/report/template_test.go b/pkg/report/template_test.go index a7d5cac6e..01b775d0e 100644 --- a/pkg/report/template_test.go +++ b/pkg/report/template_test.go @@ -178,10 +178,10 @@ func TestTemplate_Newlines(t *testing.T) { {Field1: "Three", Field2: 3, Field3: "Third"}, } - hdrs := Headers(input[0], map[string]string{"Field1": "Ein", "Field2": "Zwei", "Field3": "Drei"}) + hdrs := Headers(input[0], map[string]string{"Field1": "Eins", "Field2": "Zwei", "Field3": "Drei"}) // Ensure no blank lines in table - expected := "EIN\tZWEI\tDREI\nOne\t1\tFirst\nTwo\t2\tSecond\nThree\t3\tThird\n" + expected := "EINS\tZWEI\tDREI\nOne\t1\tFirst\nTwo\t2\tSecond\nThree\t3\tThird\n" format := NormalizeFormat("{{.Field1}}\t{{.Field2}}\t{{.Field3}}") format = EnforceRange(format)