From 7d11f5dedc6b2c26a29af79c2c601a6388713d5a Mon Sep 17 00:00:00 2001 From: RaymondKYLiu Date: Fri, 10 Apr 2020 07:23:42 +0800 Subject: [PATCH] feat: add tmpl function `required` (#1188) Co-authored-by: Raymond Liu (RD-TW) --- pkg/tmpl/context_funcs.go | 13 ++++++ pkg/tmpl/context_funcs_test.go | 44 +++++++++++++++++++ pkg/tmpl/context_tmpl_test.go | 78 ++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) diff --git a/pkg/tmpl/context_funcs.go b/pkg/tmpl/context_funcs.go index 0819d9ea..025102fe 100644 --- a/pkg/tmpl/context_funcs.go +++ b/pkg/tmpl/context_funcs.go @@ -26,6 +26,7 @@ func (c *Context) createFuncMap() template.FuncMap { "get": get, "getOrNil": getOrNil, "tpl": c.Tpl, + "required": Required, } if c.preRender { // disable potential side-effect template calls @@ -242,3 +243,15 @@ func RequiredEnv(name string) (string, error) { return "", fmt.Errorf("required env var `%s` is not set", name) } + +func Required(warn string, val interface{}) (interface{}, error) { + if val == nil { + return nil, fmt.Errorf(warn) + } else if _, ok := val.(string); ok { + if val == "" { + return nil, fmt.Errorf(warn) + } + } + + return val, nil +} diff --git a/pkg/tmpl/context_funcs_test.go b/pkg/tmpl/context_funcs_test.go index 373d6eb0..3483ae89 100644 --- a/pkg/tmpl/context_funcs_test.go +++ b/pkg/tmpl/context_funcs_test.go @@ -133,3 +133,47 @@ func TestTpl(t *testing.T) { t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual) } } + +func TestRequired(t *testing.T) { + type args struct { + warn string + val interface{} + } + tests := []struct { + name string + args args + want interface{} + wantErr bool + }{ + { + name: "required val is nil", + args: args{warn: "This value is required", val: nil}, + want: nil, + wantErr: true, + }, + { + name: "required val is empty string", + args: args{warn: "This value is required", val: ""}, + want: nil, + wantErr: true, + }, + { + name: "required val is existed", + args: args{warn: "This value is required", val: "foo"}, + want: "foo", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Required(tt.args.warn, tt.args.val) + if (err != nil) != tt.wantErr { + t.Errorf("Required() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Required() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/tmpl/context_tmpl_test.go b/pkg/tmpl/context_tmpl_test.go index b30b8cc5..af14824c 100644 --- a/pkg/tmpl/context_tmpl_test.go +++ b/pkg/tmpl/context_tmpl_test.go @@ -250,3 +250,81 @@ func Test_renderTemplateToString(t *testing.T) { }) } } + +func TestRenderTemplate_Required(t *testing.T) { + tests := []struct { + name string + s string + data map[string]interface{} + want string + wantErr bool + }{ + { + name: ".foo is existed", + s: `{{ required ".foo.bar is required" .foo }}`, + data: map[string]interface{}{ + "foo": "bar", + }, + want: "bar", + wantErr: false, + }, + { + name: ".foo.bar is existed", + s: `{{ required "foo.bar is required" .foo.bar }}`, + data: map[string]interface{}{ + "foo": map[string]interface{}{ + "bar": "FOO_BAR", + }, + }, + want: "FOO_BAR", + wantErr: false, + }, + { + name: ".foo.bar is existed but value is nil", + s: `{{ required "foo.bar is required" .foo.bar }}`, + data: map[string]interface{}{ + "foo": map[string]interface{}{ + "bar": nil, + }, + }, + wantErr: true, + }, + { + name: ".foo.bar is existed but value is empty string", + s: `{{ required "foo.bar is required" .foo.bar }}`, + data: map[string]interface{}{ + "foo": map[string]interface{}{ + "bar": "", + }, + }, + wantErr: true, + }, + { + name: ".foo is nil", + s: `{{ required "foo is required" .foo }}`, + data: map[string]interface{}{ + "foo": nil, + }, + wantErr: true, + }, + { + name: ".foo is a empty string", + s: `{{ required "foo is required" .foo }}`, + data: map[string]interface{}{ + "foo": "", + }, + wantErr: true, + }, + } + + for _, tt := range tests { + got, err := renderTemplateToString(tt.s, tt.data) + if (err != nil) != tt.wantErr { + t.Errorf("renderTemplateToString() for %s error = %v, wantErr %v", tt.name, err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("renderTemplateToString() for %s = %v, want %v", tt.name, got, tt.want) + } + } +}