Merge pull request #5889 from andytom/fix/backport_lint_fix

Helm 3: Stop Lint from breaking when using required
pull/5970/head
Matthew Fisher 5 years ago committed by GitHub
commit 1ea07feac8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -18,6 +18,7 @@ package engine
import (
"fmt"
"log"
"path"
"path/filepath"
"sort"
@ -35,6 +36,8 @@ type Engine struct {
// If strict is enabled, template rendering will fail if a template references
// a value that was not passed in.
Strict bool
// In LintMode, some 'required' template values may be missing, so don't fail
LintMode bool
}
// Render takes a chart, optional values, and value overrides, and attempts to render the Go templates.
@ -114,6 +117,29 @@ func (e Engine) initFunMap(t *template.Template, referenceTpls map[string]render
}
return result[templateName.(string)], nil
}
// Add the `required` function here so we can use lintMode
funcMap["required"] = func(warn string, val interface{}) (interface{}, error) {
if val == nil {
if e.LintMode {
// Don't fail on missing required values when linting
log.Printf("[INFO] Missing required value: %s", warn)
return "", nil
}
return val, errors.Errorf(warn)
} else if _, ok := val.(string); ok {
if val == "" {
if e.LintMode {
// Don't fail on missing required values when linting
log.Printf("[INFO] Missing required value: %s", warn)
return "", nil
}
return val, errors.Errorf(warn)
}
}
return val, nil
}
t.Funcs(funcMap)
}

@ -480,6 +480,33 @@ func TestAlterFuncMap_require(t *testing.T) {
if gotNum := out["conan/templates/bases"]; gotNum != expectNum {
t.Errorf("Expected %q, got %q (%v)", expectNum, gotNum, out)
}
// test required without passing in needed values with lint mode on
// verifies lint replaces required with an empty string (should not fail)
lintValues := chartutil.Values{
"Values": chartutil.Values{
"who": "us",
},
"Chart": c.Metadata,
"Release": chartutil.Values{
"Name": "That 90s meme",
},
}
var e Engine
e.LintMode = true
out, err = e.Render(c, lintValues)
if err != nil {
t.Fatal(err)
}
expectStr = "All your base are belong to us"
if gotStr := out["conan/templates/quote"]; gotStr != expectStr {
t.Errorf("Expected %q, got %q (%v)", expectStr, gotStr, out)
}
expectNum = "All of them!"
if gotNum := out["conan/templates/bases"]; gotNum != expectNum {
t.Errorf("Expected %q, got %q (%v)", expectNum, gotNum, out)
}
}
func TestAlterFuncMap_tpl(t *testing.T) {

@ -24,7 +24,6 @@ import (
"github.com/BurntSushi/toml"
"github.com/Masterminds/sprig"
"github.com/pkg/errors"
yaml "gopkg.in/yaml.v2"
)
@ -54,13 +53,13 @@ func funcMap() template.FuncMap {
"fromYaml": fromYAML,
"toJson": toJSON,
"fromJson": fromJSON,
"required": required,
// 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.
"include": func(string, interface{}) string { return "not implemented" },
"tpl": func(string, interface{}) interface{} { return "not implemented" },
"include": func(string, interface{}) string { return "not implemented" },
"tpl": func(string, interface{}) interface{} { return "not implemented" },
"required": func(string, interface{}) (interface{}, error) { return "not implemented", nil },
}
for k, v := range extra {
@ -70,17 +69,6 @@ func funcMap() template.FuncMap {
return f
}
func required(warn string, val interface{}) (interface{}, error) {
if val == nil {
return val, errors.Errorf(warn)
} else if _, ok := val.(string); ok {
if val == "" {
return val, errors.Errorf(warn)
}
}
return val, nil
}
// toYAML takes an interface, marshals it to yaml, and returns a string. It will
// always return a string, even on marshal error (empty string).
//

@ -30,10 +30,6 @@ func TestFuncs(t *testing.T) {
tpl, expect string
vars interface{}
}{{
tpl: `All {{ required "A valid 'bases' is required" .bases }} of them!`,
expect: `All 2 of them!`,
vars: map[string]interface{}{"bases": 2},
}, {
tpl: `{{ toYaml . }}`,
expect: `foo: bar`,
vars: map[string]interface{}{"foo": "bar"},

@ -68,6 +68,7 @@ func Templates(linter *support.Linter, values map[string]interface{}, namespace
}
var e engine.Engine
e.Strict = strict
e.LintMode = true
renderedContentMap, err := e.Render(chart, valuesToRender)
renderOk := linter.RunLinterRule(support.ErrorSev, path, err)

Loading…
Cancel
Save