feat(helm): version flag on helm lint

version flag is supported in helm lint, so the version value of chart
can be passed via command line.

eg: `helm lint mychart/ --version=1.0`

Signed-off-by: Mohan Prasath <openmohan@gmail.com>
pull/5086/head^2
Mohan Prasath 7 years ago
parent e7bd4da683
commit 2d015f6b60

@ -52,6 +52,7 @@ type lintCmd struct {
strict bool strict bool
paths []string paths []string
out io.Writer out io.Writer
version string
} }
func newLintCmd(out io.Writer) *cobra.Command { func newLintCmd(out io.Writer) *cobra.Command {
@ -77,6 +78,7 @@ func newLintCmd(out io.Writer) *cobra.Command {
cmd.Flags().StringArrayVar(&l.fValues, "set-file", []string{}, "set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)") cmd.Flags().StringArrayVar(&l.fValues, "set-file", []string{}, "set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)")
cmd.Flags().StringVar(&l.namespace, "namespace", "default", "namespace to put the release into") cmd.Flags().StringVar(&l.namespace, "namespace", "default", "namespace to put the release into")
cmd.Flags().BoolVar(&l.strict, "strict", false, "fail on lint warnings") cmd.Flags().BoolVar(&l.strict, "strict", false, "fail on lint warnings")
cmd.Flags().StringVar(&l.version, "version", "", "version of the chart")
return cmd return cmd
} }
@ -100,7 +102,7 @@ func (l *lintCmd) run() error {
var total int var total int
var failures int var failures int
for _, path := range l.paths { for _, path := range l.paths {
if linter, err := lintChart(path, rvals, l.namespace, l.strict); err != nil { if linter, err := lintChart(path, rvals, l.namespace, l.strict, l.version); err != nil {
fmt.Println("==> Skipping", path) fmt.Println("==> Skipping", path)
fmt.Println(err) fmt.Println(err)
if err == errLintNoChart { if err == errLintNoChart {
@ -135,7 +137,7 @@ func (l *lintCmd) run() error {
return nil return nil
} }
func lintChart(path string, vals []byte, namespace string, strict bool) (support.Linter, error) { func lintChart(path string, vals []byte, namespace string, strict bool, version string) (support.Linter, error) {
var chartPath string var chartPath string
linter := support.Linter{} linter := support.Linter{}
@ -171,7 +173,7 @@ func lintChart(path string, vals []byte, namespace string, strict bool) (support
return linter, errLintNoChart return linter, errLintNoChart
} }
return lint.All(chartPath, vals, namespace, strict), nil return lint.All(chartPath, vals, namespace, strict, version), nil
} }
// vals merges values from files specified via -f/--values and // vals merges values from files specified via -f/--values and

@ -29,26 +29,32 @@ var (
invalidArchivedChartPath = "testdata/testcharts/invalidcompressedchart0.1.0.tgz" invalidArchivedChartPath = "testdata/testcharts/invalidcompressedchart0.1.0.tgz"
chartDirPath = "testdata/testcharts/decompressedchart/" chartDirPath = "testdata/testcharts/decompressedchart/"
chartMissingManifest = "testdata/testcharts/chart-missing-manifest" chartMissingManifest = "testdata/testcharts/chart-missing-manifest"
chartMissingVersion = "testdata/testcharts/chart-missing-version"
) )
func TestLintChart(t *testing.T) { func TestLintChart(t *testing.T) {
if _, err := lintChart(chartDirPath, values, namespace, strict); err != nil { if _, err := lintChart(chartDirPath, values, namespace, strict, ""); err != nil {
t.Errorf("%s", err) t.Errorf("%s", err)
} }
if _, err := lintChart(archivedChartPath, values, namespace, strict); err != nil { if _, err := lintChart(archivedChartPath, values, namespace, strict, ""); err != nil {
t.Errorf("%s", err) t.Errorf("%s", err)
} }
if _, err := lintChart(archivedChartPathWithHyphens, values, namespace, strict); err != nil { if _, err := lintChart(archivedChartPathWithHyphens, values, namespace, strict, ""); err != nil {
t.Errorf("%s", err) t.Errorf("%s", err)
} }
if _, err := lintChart(invalidArchivedChartPath, values, namespace, strict); err == nil { if _, err := lintChart(chartMissingVersion, values, namespace, strict, "0.1.0"); err != nil {
t.Errorf("%s", err)
}
if _, err := lintChart(invalidArchivedChartPath, values, namespace, strict, ""); err == nil {
t.Errorf("Expected a chart parsing error") t.Errorf("Expected a chart parsing error")
} }
if _, err := lintChart(chartMissingManifest, values, namespace, strict); err == nil { if _, err := lintChart(chartMissingManifest, values, namespace, strict, ""); err == nil {
t.Errorf("Expected a chart parsing error") t.Errorf("Expected a chart parsing error")
} }
} }

@ -0,0 +1,5 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
.git

@ -0,0 +1,2 @@
description: A Helm chart for Kubernetes
name: decompressedchart

@ -0,0 +1,4 @@
# Default values for decompressedchart.
# This is a YAML-formatted file.
# Declare name/value pairs to be passed into your templates.
name: my-decompressed-chart

@ -27,6 +27,7 @@ helm lint [flags] PATH
--set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2) --set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)
--strict fail on lint warnings --strict fail on lint warnings
-f, --values valueFiles specify values in a YAML file (can specify multiple) (default []) -f, --values valueFiles specify values in a YAML file (can specify multiple) (default [])
--version string version of the chart
``` ```
### Options inherited from parent commands ### Options inherited from parent commands
@ -45,4 +46,4 @@ helm lint [flags] PATH
* [helm](helm.md) - The Helm package manager for Kubernetes. * [helm](helm.md) - The Helm package manager for Kubernetes.
###### Auto generated by spf13/cobra on 1-Aug-2018 ###### Auto generated by spf13/cobra on 20-Dec-2018

@ -24,12 +24,12 @@ import (
) )
// All runs all of the available linters on the given base directory. // All runs all of the available linters on the given base directory.
func All(basedir string, values []byte, namespace string, strict bool) support.Linter { func All(basedir string, values []byte, namespace string, strict bool, version string) support.Linter {
// Using abs path to get directory context // Using abs path to get directory context
chartDir, _ := filepath.Abs(basedir) chartDir, _ := filepath.Abs(basedir)
linter := support.Linter{ChartDir: chartDir} linter := support.Linter{ChartDir: chartDir}
rules.Chartfile(&linter) rules.Chartfile(&linter, version)
rules.Values(&linter) rules.Values(&linter)
rules.Templates(&linter, values, namespace, strict) rules.Templates(&linter, values, namespace, strict)
return linter return linter

@ -28,14 +28,16 @@ var values = []byte{}
const namespace = "testNamespace" const namespace = "testNamespace"
const strict = false const strict = false
const version = "199.44.12345-Alpha.1+cafe009"
const badChartDir = "rules/testdata/badchartfile" const badChartDir = "rules/testdata/badchartfile"
const badValuesFileDir = "rules/testdata/badvaluesfile" const badValuesFileDir = "rules/testdata/badvaluesfile"
const badYamlFileDir = "rules/testdata/albatross" const badYamlFileDir = "rules/testdata/albatross"
const goodChartDir = "rules/testdata/goodone" const goodChartDir = "rules/testdata/goodone"
const chartNoVersionDir = "rules/testdata/noversionchart"
func TestBadChart(t *testing.T) { func TestBadChart(t *testing.T) {
m := All(badChartDir, values, namespace, strict).Messages m := All(badChartDir, values, namespace, strict, "").Messages
if len(m) != 5 { if len(m) != 5 {
t.Errorf("Number of errors %v", len(m)) t.Errorf("Number of errors %v", len(m))
t.Errorf("All didn't fail with expected errors, got %#v", m) t.Errorf("All didn't fail with expected errors, got %#v", m)
@ -68,10 +70,28 @@ func TestBadChart(t *testing.T) {
if !e || !e2 || !e3 || !w || !i { if !e || !e2 || !e3 || !w || !i {
t.Errorf("Didn't find all the expected errors, got %#v", m) t.Errorf("Didn't find all the expected errors, got %#v", m)
} }
m = All(chartNoVersionDir, values, namespace, strict, "").Messages
if len(m) != 1 {
t.Errorf("Number of errors %v, expected 1", len(m))
}
e = false
// There should be one ERROR messages, check for them
for _, msg := range m {
if msg.Severity == support.ErrorSev {
if strings.Contains(msg.Err.Error(), "version is required") {
e = true
}
}
if !e {
t.Errorf("Didn't find all the expected errors, got %#v expected: \"version is required\"", msg.Err.Error())
}
}
} }
func TestInvalidYaml(t *testing.T) { func TestInvalidYaml(t *testing.T) {
m := All(badYamlFileDir, values, namespace, strict).Messages m := All(badYamlFileDir, values, namespace, strict, "").Messages
if len(m) != 1 { if len(m) != 1 {
t.Fatalf("All didn't fail with expected errors, got %#v", m) t.Fatalf("All didn't fail with expected errors, got %#v", m)
} }
@ -81,7 +101,7 @@ func TestInvalidYaml(t *testing.T) {
} }
func TestBadValues(t *testing.T) { func TestBadValues(t *testing.T) {
m := All(badValuesFileDir, values, namespace, strict).Messages m := All(badValuesFileDir, values, namespace, strict, "").Messages
if len(m) != 1 { if len(m) != 1 {
t.Fatalf("All didn't fail with expected errors, got %#v", m) t.Fatalf("All didn't fail with expected errors, got %#v", m)
} }
@ -91,8 +111,13 @@ func TestBadValues(t *testing.T) {
} }
func TestGoodChart(t *testing.T) { func TestGoodChart(t *testing.T) {
m := All(goodChartDir, values, namespace, strict).Messages m := All(goodChartDir, values, namespace, strict, "").Messages
if len(m) != 0 { if len(m) != 0 {
t.Errorf("All failed but shouldn't have: %#v", m) t.Errorf("All failed but shouldn't have: %#v", m)
} }
m = All(chartNoVersionDir, values, namespace, strict, "199.44.12345-Alpha.1+cafe009").Messages
if len(m) != 0 {
t.Errorf("All failed but shouldn't have: %#v", m[0].Err)
}
} }

@ -32,7 +32,7 @@ import (
) )
// Chartfile runs a set of linter rules related to Chart.yaml file // Chartfile runs a set of linter rules related to Chart.yaml file
func Chartfile(linter *support.Linter) { func Chartfile(linter *support.Linter, version string) {
chartFileName := "Chart.yaml" chartFileName := "Chart.yaml"
chartPath := filepath.Join(linter.ChartDir, chartFileName) chartPath := filepath.Join(linter.ChartDir, chartFileName)
@ -46,6 +46,10 @@ func Chartfile(linter *support.Linter) {
return return
} }
if chartFile.Version == "" && version != "" {
chartFile.Version = version
}
linter.RunLinterRule(support.ErrorSev, chartFileName, validateChartName(chartFile)) linter.RunLinterRule(support.ErrorSev, chartFileName, validateChartName(chartFile))
linter.RunLinterRule(support.ErrorSev, chartFileName, validateChartNameDirMatch(linter.ChartDir, chartFile)) linter.RunLinterRule(support.ErrorSev, chartFileName, validateChartNameDirMatch(linter.ChartDir, chartFile))

@ -31,6 +31,8 @@ import (
const ( const (
badChartDir = "testdata/badchartfile" badChartDir = "testdata/badchartfile"
goodChartDir = "testdata/goodone" goodChartDir = "testdata/goodone"
noVersionChartDir = "testdata/noversionchart"
version = "1.0"
) )
var ( var (
@ -75,7 +77,7 @@ func TestValidateChartName(t *testing.T) {
func TestValidateChartNameDirMatch(t *testing.T) { func TestValidateChartNameDirMatch(t *testing.T) {
err := validateChartNameDirMatch(goodChartDir, goodChart) err := validateChartNameDirMatch(goodChartDir, goodChart)
if err != nil { if err != nil {
t.Errorf("validateChartNameDirMatch to return no error, gor a linter error") t.Errorf("validateChartNameDirMatch to return no error, got a linter error")
} }
// It has not name // It has not name
err = validateChartNameDirMatch(badChartDir, badChart) err = validateChartNameDirMatch(badChartDir, badChart)
@ -223,7 +225,7 @@ func TestValidateChartIconURL(t *testing.T) {
func TestChartfile(t *testing.T) { func TestChartfile(t *testing.T) {
linter := support.Linter{ChartDir: badChartDir} linter := support.Linter{ChartDir: badChartDir}
Chartfile(&linter) Chartfile(&linter, "")
msgs := linter.Messages msgs := linter.Messages
if len(msgs) != 4 { if len(msgs) != 4 {
@ -246,4 +248,15 @@ func TestChartfile(t *testing.T) {
t.Errorf("Unexpected message 3: %s", msgs[3].Err) t.Errorf("Unexpected message 3: %s", msgs[3].Err)
} }
linter = support.Linter{ChartDir: noVersionChartDir}
Chartfile(&linter, "")
msgs = linter.Messages
if len(msgs) != 1 {
t.Errorf("Expected 1 errors, got %d", len(msgs))
}
if !strings.Contains(msgs[0].Err.Error(), "version is required") {
t.Errorf("Unexpected message 0: %s, expected \"version is required\"", msgs[0].Err)
}
} }

@ -0,0 +1,3 @@
name: noversionchart
description: no version chart for testing
icon: http://riverrun.io

@ -0,0 +1,2 @@
metadata:
name: {{.Values.name | default "foo" | title}}

@ -0,0 +1 @@
name: "noversionchart here"
Loading…
Cancel
Save