From 7fa8d5e064bad6d65348a69b623ebb2ecffdf248 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Thu, 26 Jan 2017 12:49:40 -0800 Subject: [PATCH] Add `truncate` function for Go templates This fix is part of the discussion in 28199 about using `truncate` to replace `--no-trunc`. As part of the fix, a new function `truncate` has been added for Go templates so that it is possible to use ``` docker stack services --format "{{truncate .ID 5}}: {{.Mode}} {{.Replicas}}" ``` to show truncated ID. A unit test has been added. This fix is related to 28199. Signed-off-by: Yong Tang --- pkg/templates/templates.go | 21 +++++++++---- pkg/templates/templates_test.go | 55 +++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/pkg/templates/templates.go b/pkg/templates/templates.go index ac9da54d78..7988794316 100644 --- a/pkg/templates/templates.go +++ b/pkg/templates/templates.go @@ -13,12 +13,13 @@ var basicFunctions = template.FuncMap{ a, _ := json.Marshal(v) return string(a) }, - "split": strings.Split, - "join": strings.Join, - "title": strings.Title, - "lower": strings.ToLower, - "upper": strings.ToUpper, - "pad": padWithSpace, + "split": strings.Split, + "join": strings.Join, + "title": strings.Title, + "lower": strings.ToLower, + "upper": strings.ToUpper, + "pad": padWithSpace, + "truncate": truncateWithLength, } // Parse creates a new anonymous template with the basic functions @@ -40,3 +41,11 @@ func padWithSpace(source string, prefix, suffix int) string { } return strings.Repeat(" ", prefix) + source + strings.Repeat(" ", suffix) } + +// truncateWithLength truncates the source string up to the length provided by the input +func truncateWithLength(source string, length int) string { + if len(source) < length { + return source + } + return source[:length] +} diff --git a/pkg/templates/templates_test.go b/pkg/templates/templates_test.go index dd42901aed..7fa1df64ee 100644 --- a/pkg/templates/templates_test.go +++ b/pkg/templates/templates_test.go @@ -3,36 +3,57 @@ package templates import ( "bytes" "testing" + + "github.com/docker/docker/pkg/testutil/assert" ) func TestParseStringFunctions(t *testing.T) { tm, err := Parse(`{{join (split . ":") "/"}}`) - if err != nil { - t.Fatal(err) - } + assert.NilError(t, err) var b bytes.Buffer - if err := tm.Execute(&b, "text:with:colon"); err != nil { - t.Fatal(err) - } + assert.NilError(t, tm.Execute(&b, "text:with:colon")) want := "text/with/colon" - if b.String() != want { - t.Fatalf("expected %s, got %s", want, b.String()) - } + assert.Equal(t, b.String(), want) } func TestNewParse(t *testing.T) { tm, err := NewParse("foo", "this is a {{ . }}") - if err != nil { - t.Fatal(err) - } + assert.NilError(t, err) var b bytes.Buffer - if err := tm.Execute(&b, "string"); err != nil { - t.Fatal(err) - } + assert.NilError(t, tm.Execute(&b, "string")) want := "this is a string" - if b.String() != want { - t.Fatalf("expected %s, got %s", want, b.String()) + assert.Equal(t, b.String(), want) +} + +func TestParseTruncateFunction(t *testing.T) { + source := "tupx5xzf6hvsrhnruz5cr8gwp" + + testCases := []struct { + template string + expected string + }{ + { + template: `{{truncate . 5}}`, + expected: "tupx5", + }, + { + template: `{{truncate . 25}}`, + expected: "tupx5xzf6hvsrhnruz5cr8gwp", + }, + { + template: `{{truncate . 30}}`, + expected: "tupx5xzf6hvsrhnruz5cr8gwp", + }, + } + + for _, testCase := range testCases { + tm, err := Parse(testCase.template) + assert.NilError(t, err) + + var b bytes.Buffer + assert.NilError(t, tm.Execute(&b, source)) + assert.Equal(t, b.String(), testCase.expected) } }