Adds support to print rendered charts on `helm lint --debug`

Fixes #8982

Signed-off-by: Jason Whalley <42138928+JasonWhall@users.noreply.github.com>
pull/8995/head
Jason Whalley 5 years ago
parent b690db13a0
commit 6784d42453

@ -100,6 +100,12 @@ func newLintCmd(out io.Writer) *cobra.Command {
failed++
}
if settings.Debug {
for _, contents := range result.RenderedContents {
fmt.Fprintf(&message, "---\n# Source: %s\n%s\n", path, contents)
}
}
// Adding extra new line here to break up the
// results, stops this from being a big wall of
// text and makes it easier to follow.

@ -33,6 +33,11 @@ func TestLintCmdWithSubchartsFlag(t *testing.T) {
cmd: fmt.Sprintf("lint --with-subcharts %s", testChart),
golden: "output/lint-chart-with-bad-subcharts-with-subcharts.txt",
wantError: true,
}, {
name: "lint bad chart using --debug flag",
cmd: fmt.Sprintf("lint %s --debug", "testdata/testcharts/chart-with-template-with-invalid-yaml"),
golden: "output/lint-chart-with-template-with-invalid-yaml-with-debug.txt",
wantError: true,
}}
runTestCmd(t, tests)
}

@ -0,0 +1,19 @@
==> Linting testdata/testcharts/chart-with-template-with-invalid-yaml
[INFO] Chart.yaml: icon is recommended
[ERROR] Chart.yaml: chart type is not valid in apiVersion 'v1'. It is valid in apiVersion 'v2'
[ERROR] templates/alpine-pod.yaml: unable to parse YAML: error converting YAML to JSON: yaml: line 11: could not find expected ':'
---
# Source: testdata/testcharts/chart-with-template-with-invalid-yaml
apiVersion: v1
kind: Pod
metadata:
name: "test-release-my-alpine"
spec:
containers:
- name: waiter
image: "alpine:3.9"
command: ["/bin/sleep","9000"]
invalid
Error: 1 chart(s) linted, 1 chart(s) failed

@ -41,6 +41,7 @@ type Lint struct {
// LintResult is the result of Lint
type LintResult struct {
TotalChartsLinted int
RenderedContents []string
Messages []support.Message
Errors []error
}
@ -59,6 +60,9 @@ func (l *Lint) Run(paths []string, vals map[string]interface{}) *LintResult {
result := &LintResult{}
for _, path := range paths {
linter, err := lintChart(path, vals, l.Namespace, l.Strict)
result.RenderedContents = append(result.RenderedContents, linter.RenderedContent...)
if err != nil {
result.Errors = append(result.Errors, err)
continue

@ -35,6 +35,7 @@ const badChartDir = "rules/testdata/badchartfile"
const badValuesFileDir = "rules/testdata/badvaluesfile"
const badYamlFileDir = "rules/testdata/albatross"
const goodChartDir = "rules/testdata/goodone"
const multiTemplateFail = "rules/testdata/multi-template-fail"
func TestBadChart(t *testing.T) {
m := All(badChartDir, values, namespace, strict).Messages
@ -105,6 +106,16 @@ func TestBadValues(t *testing.T) {
}
}
func TestRenderedContent(t *testing.T) {
m := All(multiTemplateFail, values, namespace, strict).RenderedContent
if len(m) < 1 {
t.Fatalf("All didn't return any content, got %#v", m)
}
if !strings.Contains(m[0], "apiVersion: v1") {
t.Errorf("All didn't have expected content")
}
}
func TestGoodChart(t *testing.T) {
m := All(goodChartDir, values, namespace, strict).Messages
if len(m) != 0 {

@ -82,10 +82,6 @@ func Templates(linter *support.Linter, values map[string]interface{}, namespace
renderOk := linter.RunLinterRule(support.ErrorSev, fpath, err)
if !renderOk {
return
}
/* Iterate over all the templates to check:
- It is a .yaml file
- All the values in the template file is defined
@ -117,6 +113,14 @@ func Templates(linter *support.Linter, values map[string]interface{}, namespace
renderedContent := renderedContentMap[path.Join(chart.Name(), fileName)]
if strings.TrimSpace(renderedContent) != "" {
linter.NewRenderedContent(renderedContent)
// We check if the render was successful here to allow any invalid templates to be returned in debug
if !renderOk {
break
}
linter.RunLinterRule(support.WarningSev, fpath, validateTopIndentLevel(renderedContent))
decoder := yaml.NewYAMLOrJSONDecoder(strings.NewReader(renderedContent), 4096)
@ -132,7 +136,7 @@ func Templates(linter *support.Linter, values map[string]interface{}, namespace
break
}
// If YAML linting fails, we sill progress. So we don't capture the returned state
// If YAML linting fails, we still progress. So we don't capture the returned state
// on this linter run.
linter.RunLinterRule(support.ErrorSev, fpath, validateYamlContent(err))

@ -36,6 +36,10 @@ var sev = []string{"UNKNOWN", "INFO", "WARNING", "ERROR"}
// Linter encapsulates a linting run of a particular chart.
type Linter struct {
Messages []Message
// Contains the rendered templates
RenderedContent []string
// The highest severity of all the failing lint rules
HighestSeverity int
ChartDir string
@ -49,6 +53,11 @@ type Message struct {
Err error
}
// NewRenderedContent appends content
func (l *Linter) NewRenderedContent(content string) {
l.RenderedContent = append(l.RenderedContent, content)
}
func (m Message) Error() string {
return fmt.Sprintf("[%s] %s: %s", sev[m.Severity], m.Path, m.Err.Error())
}

Loading…
Cancel
Save