From 36f7eb0b2a33e59d61f59bc63ae10fdf25e6a2ee Mon Sep 17 00:00:00 2001 From: Matt Butcher Date: Fri, 14 Oct 2016 16:28:43 -0600 Subject: [PATCH] fix(linter): add engine.FuncMap so linter can use real function list This adds a function engine.FuncMap that returns a function mapping that better represents the functions passed to a template. The linting logic is reconfigured to use this function instead of the sprig.FuncMap function. Closes #1366 --- pkg/engine/engine.go | 27 ++++++++++++++++++++++++--- pkg/engine/engine_test.go | 18 ++++++++++++++++++ pkg/lint/rules/template.go | 3 +-- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 93927bcb5..bdc4011d7 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -48,15 +48,36 @@ type Engine struct { // The FuncMap sets all of the Sprig functions except for those that provide // access to the underlying OS (env, expandenv). func New() *Engine { + f := FuncMap() + return &Engine{ + FuncMap: f, + } +} + +// FuncMap returns a mapping of all of the functions that Engine has. +// +// Because some functions are late-bound (e.g. contain context-sensitive +// data), the functions may not all perform identically outside of an +// Engine as they will inside of an Engine. +// +// Known late-bound functions: +// +// - "include": This is late-bound in Engine.Render(). The version +// included in the FuncMap is a placeholder. +func FuncMap() template.FuncMap { f := sprig.TxtFuncMap() delete(f, "env") delete(f, "expandenv") // Add a function to convert to YAML: f["toYaml"] = toYaml - return &Engine{ - FuncMap: f, - } + + // This is a placeholder for the "include" function, which is + // late-bound to a template. By declaring it here, we preserve the + // integrity of the linter. + f["include"] = func(string, interface{}) string { return "not implemented" } + + return f } func toYaml(v interface{}) string { diff --git a/pkg/engine/engine_test.go b/pkg/engine/engine_test.go index d9e595412..206fbc035 100644 --- a/pkg/engine/engine_test.go +++ b/pkg/engine/engine_test.go @@ -52,6 +52,24 @@ func TestEngine(t *testing.T) { } } +func TestFuncMap(t *testing.T) { + fns := FuncMap() + forbidden := []string{"env", "expandenv"} + for _, f := range forbidden { + if _, ok := fns[f]; ok { + t.Errorf("Forbidden function %s exists in FuncMap.", f) + } + } + + // Test for Engine-specific template functions. + expect := []string{"include", "toYaml"} + for _, f := range expect { + if _, ok := fns[f]; !ok { + t.Errorf("Expected add-on function %q", f) + } + } +} + func TestRender(t *testing.T) { c := &chart.Chart{ Metadata: &chart.Metadata{ diff --git a/pkg/lint/rules/template.go b/pkg/lint/rules/template.go index dabdbc305..5dc6d8424 100644 --- a/pkg/lint/rules/template.go +++ b/pkg/lint/rules/template.go @@ -25,7 +25,6 @@ import ( "regexp" "text/template" - "github.com/Masterminds/sprig" "github.com/ghodss/yaml" "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/engine" @@ -138,7 +137,7 @@ func validateAllowedExtension(fileName string) error { func validateNoMissingValues(templatesPath string, chartValues chartutil.Values, templateContent []byte) error { // 1 - Load Main and associated templates // Main template that we will parse dynamically - tmpl := template.New("tpl").Funcs(sprig.TxtFuncMap()) + tmpl := template.New("tpl").Funcs(engine.FuncMap()) // If the templatesPath includes any *.tpl files we will parse and import them as associated templates associatedTemplates, err := filepath.Glob(filepath.Join(templatesPath, "*.tpl"))