diff --git a/_proto/hapi/chart/metadata.proto b/_proto/hapi/chart/metadata.proto index f64327a4a..2e848c5e2 100644 --- a/_proto/hapi/chart/metadata.proto +++ b/_proto/hapi/chart/metadata.proto @@ -17,6 +17,10 @@ message Maintainer { // // Spec: https://k8s.io/helm/blob/master/docs/design/chart_format.md#the-chart-file message Metadata { + enum Engine { + UNKNOWN = 0; + GOTPL = 1; + } // The name of the chart string name = 1; diff --git a/cmd/helm/lint.go b/cmd/helm/lint.go index 35645b151..71c53aceb 100644 --- a/cmd/helm/lint.go +++ b/cmd/helm/lint.go @@ -45,6 +45,11 @@ func lintCmd(cmd *cobra.Command, args []string) error { } issues := lint.All(path) + + if len(issues) == 0 { + fmt.Println("Lint OK") + } + for _, i := range issues { fmt.Printf("%s\n", i) } diff --git a/docs/examples/alpine/Chart.yaml b/docs/examples/alpine/Chart.yaml index 2f2af3f74..bb2602087 100644 --- a/docs/examples/alpine/Chart.yaml +++ b/docs/examples/alpine/Chart.yaml @@ -4,5 +4,3 @@ version: 0.1.0 home: https://k8s.io/helm sources: - https://github.com/kubernetes/helm - - diff --git a/glide.lock b/glide.lock index 27912b75e..467dbb7db 100644 --- a/glide.lock +++ b/glide.lock @@ -5,6 +5,8 @@ imports: version: 75cd24fc2f2c - name: github.com/aokoli/goutils version: 9c37978a95bd5c709a15883b6242714ea6709e64 +- name: github.com/asaskevich/govalidator + version: df81827fdd59d8b4fb93d8910b286ab7a3919520 - name: github.com/beorn7/perks version: b965b613227fddccbfffe13eae360ed3fa822f8d subpackages: diff --git a/glide.yaml b/glide.yaml index e23f6fb7a..fb1af830d 100644 --- a/glide.yaml +++ b/glide.yaml @@ -38,3 +38,4 @@ import: - package: speter.net/go/exp/math/dec/inf repo: https://github.com/go-inf/inf.git vcs: git +- package: github.com/asaskevich/govalidator diff --git a/pkg/lint/chartfile.go b/pkg/lint/chartfile.go deleted file mode 100644 index a7cbbf784..000000000 --- a/pkg/lint/chartfile.go +++ /dev/null @@ -1,46 +0,0 @@ -package lint - -import ( - "os" - "path/filepath" - - "k8s.io/helm/pkg/chartutil" -) - -// Chartfile checks the Chart.yaml file for errors and warnings. -func Chartfile(basepath string) (m []Message) { - m = []Message{} - - path := filepath.Join(basepath, "Chart.yaml") - if fi, err := os.Stat(path); err != nil { - m = append(m, Message{Severity: ErrorSev, Text: "Chart.yaml file: " + path + " does not exist"}) - return - } else if fi.IsDir() { - m = append(m, Message{Severity: ErrorSev, Text: "Chart.yaml is a directory."}) - return - } - - cf, err := chartutil.LoadChartfile(path) - if err != nil { - m = append(m, Message{ - Severity: ErrorSev, - Text: err.Error(), - }) - return - } - - if cf.Name == "" { - m = append(m, Message{ - Severity: ErrorSev, - Text: "Chart.yaml: 'name' is required", - }) - } - - if cf.Version == "" || cf.Version == "0.0.0" { - m = append(m, Message{ - Severity: ErrorSev, - Text: "Chart.yaml: 'version' is required, and must be greater than 0.0.0", - }) - } - return -} diff --git a/pkg/lint/chartfile_test.go b/pkg/lint/chartfile_test.go deleted file mode 100644 index c8c3be911..000000000 --- a/pkg/lint/chartfile_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package lint - -import ( - "testing" -) - -const badchartfile = "testdata/badchartfile" - -func TestChartfile(t *testing.T) { - msgs := Chartfile(badchartfile) - if len(msgs) != 2 { - t.Errorf("Expected 2 errors, got %d", len(msgs)) - } - - if msgs[0].Text != "Chart.yaml: 'name' is required" { - t.Errorf("Unexpected message 0: %s", msgs[0].Text) - } - - if msgs[1].Text != "Chart.yaml: 'version' is required, and must be greater than 0.0.0" { - t.Errorf("Unexpected message 1: %s", msgs[1].Text) - } -} diff --git a/pkg/lint/lint.go b/pkg/lint/lint.go index 3816cae63..1d7f33dd6 100644 --- a/pkg/lint/lint.go +++ b/pkg/lint/lint.go @@ -1,9 +1,21 @@ package lint +import ( + "k8s.io/helm/pkg/lint/rules" + "k8s.io/helm/pkg/lint/support" + "os" + "path/filepath" +) + // All runs all of the available linters on the given base directory. -func All(basedir string) []Message { - out := Chartfile(basedir) - out = append(out, Templates(basedir)...) - out = append(out, Values(basedir)...) - return out +func All(basedir string) []support.Message { + // Using abs path to get directory context + current, _ := os.Getwd() + chartDir := filepath.Join(current, basedir) + + linter := support.Linter{ChartDir: chartDir} + rules.Chartfile(&linter) + rules.Values(&linter) + rules.Templates(&linter) + return linter.Messages } diff --git a/pkg/lint/lint_test.go b/pkg/lint/lint_test.go index 634b10145..4d807f5eb 100644 --- a/pkg/lint/lint_test.go +++ b/pkg/lint/lint_test.go @@ -1,39 +1,44 @@ package lint import ( + "k8s.io/helm/pkg/lint/support" "strings" "testing" ) -const badChartDir = "testdata/badchartfile" -const badValuesFileDir = "testdata/badvaluesfile" -const badYamlFileDir = "testdata/albatross" -const goodChartDir = "testdata/goodone" +const badChartDir = "rules/testdata/badchartfile" +const badValuesFileDir = "rules/testdata/badvaluesfile" +const badYamlFileDir = "rules/testdata/albatross" +const goodChartDir = "rules/testdata/goodone" func TestBadChart(t *testing.T) { m := All(badChartDir) - if len(m) != 3 { + if len(m) != 4 { + t.Errorf("Number of errors %v", len(m)) t.Errorf("All didn't fail with expected errors, got %#v", m) } // There should be 2 WARNINGs and one ERROR messages, check for them - var w, e, e2 = false, false, false + var w, e, e2, e3 bool for _, msg := range m { - if msg.Severity == WarningSev { - if strings.Contains(msg.Text, "No templates") { + if msg.Severity == support.WarningSev { + if strings.Contains(msg.Text, "Templates directory not found") { w = true } } - if msg.Severity == ErrorSev { - if strings.Contains(msg.Text, "must be greater than 0.0.0") { + if msg.Severity == support.ErrorSev { + if strings.Contains(msg.Text, "'version' 0.0.0 is less than or equal to 0") { e = true } if strings.Contains(msg.Text, "'name' is required") { e2 = true } + if strings.Contains(msg.Text, "'name' and directory do not match") { + e3 = true + } } } - if !e || !e2 || !w { + if !e || !e2 || !e3 || !w { t.Errorf("Didn't find all the expected errors, got %#v", m) } } diff --git a/pkg/lint/rules/chartfile.go b/pkg/lint/rules/chartfile.go new file mode 100644 index 000000000..e3593ee9a --- /dev/null +++ b/pkg/lint/rules/chartfile.go @@ -0,0 +1,153 @@ +package rules + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/Masterminds/semver" + "github.com/asaskevich/govalidator" + "k8s.io/helm/pkg/chartutil" + "k8s.io/helm/pkg/lint/support" + "k8s.io/helm/pkg/proto/hapi/chart" +) + +// Chartfile runs a set of linter rules related to Chart.yaml file +func Chartfile(linter *support.Linter) { + chartPath := filepath.Join(linter.ChartDir, "Chart.yaml") + + linter.RunLinterRule(support.ErrorSev, validateChartYamlFileExistence(linter, chartPath)) + linter.RunLinterRule(support.ErrorSev, validateChartYamlNotDirectory(linter, chartPath)) + + chartFile, err := chartutil.LoadChartfile(chartPath) + validChartFile := linter.RunLinterRule(support.ErrorSev, validateChartYamlFormat(linter, err)) + + // Guard clause. Following linter rules require a parseable ChartFile + if !validChartFile { + return + } + + linter.RunLinterRule(support.ErrorSev, validateChartName(linter, chartFile)) + linter.RunLinterRule(support.ErrorSev, validateChartNameDirMatch(linter, chartFile)) + + // Chart metadata + linter.RunLinterRule(support.ErrorSev, validateChartVersion(linter, chartFile)) + linter.RunLinterRule(support.ErrorSev, validateChartEngine(linter, chartFile)) + linter.RunLinterRule(support.ErrorSev, validateChartMaintainer(linter, chartFile)) + linter.RunLinterRule(support.ErrorSev, validateChartSources(linter, chartFile)) + linter.RunLinterRule(support.ErrorSev, validateChartHome(linter, chartFile)) +} + +// Auxiliar validation methods +func validateChartYamlFileExistence(linter *support.Linter, chartPath string) (lintError support.LintError) { + _, err := os.Stat(chartPath) + if err != nil { + lintError = fmt.Errorf("Chart.yaml file does not exists") + } + return +} + +func validateChartYamlNotDirectory(linter *support.Linter, chartPath string) (lintError support.LintError) { + fi, err := os.Stat(chartPath) + + if err == nil && fi.IsDir() { + lintError = fmt.Errorf("Chart.yaml is a directory") + } + return +} + +func validateChartYamlFormat(linter *support.Linter, chartFileError error) (lintError support.LintError) { + if chartFileError != nil { + lintError = fmt.Errorf("Chart.yaml is malformed: %s", chartFileError.Error()) + } + return +} + +func validateChartName(linter *support.Linter, cf *chart.Metadata) (lintError support.LintError) { + if cf.Name == "" { + lintError = fmt.Errorf("Chart.yaml: 'name' is required") + } + return +} + +func validateChartNameDirMatch(linter *support.Linter, cf *chart.Metadata) (lintError support.LintError) { + if cf.Name != filepath.Base(linter.ChartDir) { + lintError = fmt.Errorf("Chart.yaml: 'name' and directory do not match") + } + return +} + +func validateChartVersion(linter *support.Linter, cf *chart.Metadata) (lintError support.LintError) { + if cf.Version == "" { + lintError = fmt.Errorf("Chart.yaml: 'version' value is required") + return + } + + version, err := semver.NewVersion(cf.Version) + + if err != nil { + lintError = fmt.Errorf("Chart.yaml: version '%s' is not a valid SemVer", cf.Version) + return + } + + c, err := semver.NewConstraint("> 0") + valid, msg := c.Validate(version) + + if !valid && len(msg) > 0 { + lintError = fmt.Errorf("Chart.yaml: 'version' %v", msg[0]) + } + + return +} + +func validateChartEngine(linter *support.Linter, cf *chart.Metadata) (lintError support.LintError) { + if cf.Engine == "" { + return + } + + keys := make([]string, 0, len(chart.Metadata_Engine_value)) + for engine := range chart.Metadata_Engine_value { + str := strings.ToLower(engine) + + if str == "unknown" { + continue + } + + if str == cf.Engine { + return + } + + keys = append(keys, str) + } + + lintError = fmt.Errorf("Chart.yaml: 'engine %v not valid. Valid options are %v", cf.Engine, keys) + return +} + +func validateChartMaintainer(linter *support.Linter, cf *chart.Metadata) (lintError support.LintError) { + for _, maintainer := range cf.Maintainers { + if maintainer.Name == "" { + lintError = fmt.Errorf("Chart.yaml: maintainer requires a name") + } else if maintainer.Email != "" && !govalidator.IsEmail(maintainer.Email) { + lintError = fmt.Errorf("Chart.yaml: maintainer invalid email") + } + } + return +} + +func validateChartSources(linter *support.Linter, cf *chart.Metadata) (lintError support.LintError) { + for _, source := range cf.Sources { + if source == "" || !govalidator.IsRequestURL(source) { + lintError = fmt.Errorf("Chart.yaml: 'source' invalid URL %s", source) + } + } + return +} + +func validateChartHome(linter *support.Linter, cf *chart.Metadata) (lintError support.LintError) { + if cf.Home != "" && !govalidator.IsRequestURL(cf.Home) { + lintError = fmt.Errorf("Chart.yaml: 'home' invalid URL %s", cf.Home) + } + return +} diff --git a/pkg/lint/rules/chartfile_test.go b/pkg/lint/rules/chartfile_test.go new file mode 100644 index 000000000..95b22f536 --- /dev/null +++ b/pkg/lint/rules/chartfile_test.go @@ -0,0 +1,31 @@ +package rules + +import ( + "k8s.io/helm/pkg/lint/support" + "strings" + "testing" +) + +const badchartfile = "testdata/badchartfile" + +func TestChartfile(t *testing.T) { + linter := support.Linter{ChartDir: badchartfile} + Chartfile(&linter) + msgs := linter.Messages + + if len(msgs) != 3 { + t.Errorf("Expected 3 errors, got %d", len(msgs)) + } + + if !strings.Contains(msgs[0].Text, "'name' is required") { + t.Errorf("Unexpected message 0: %s", msgs[0].Text) + } + + if !strings.Contains(msgs[1].Text, "'name' and directory do not match") { + t.Errorf("Unexpected message 1: %s", msgs[1].Text) + } + + if !strings.Contains(msgs[2].Text, "'version' 0.0.0 is less than or equal to 0") { + t.Errorf("Unexpected message 2: %s", msgs[2].Text) + } +} diff --git a/pkg/lint/rules/template.go b/pkg/lint/rules/template.go new file mode 100644 index 000000000..face9c6ff --- /dev/null +++ b/pkg/lint/rules/template.go @@ -0,0 +1,70 @@ +package rules + +import ( + "fmt" + "github.com/Masterminds/sprig" + "io/ioutil" + "k8s.io/helm/pkg/lint/support" + "os" + "path/filepath" + "text/template" +) + +// Templates lints a chart's templates. +func Templates(linter *support.Linter) { + templatespath := filepath.Join(linter.ChartDir, "templates") + + templatesExist := linter.RunLinterRule(support.WarningSev, validateTemplatesExistence(linter, templatespath)) + + // Templates directory is optional for now + if !templatesExist { + return + } + + linter.RunLinterRule(support.ErrorSev, validateTemplatesDir(linter, templatespath)) + linter.RunLinterRule(support.ErrorSev, validateTemplatesParseable(linter, templatespath)) +} + +func validateTemplatesExistence(linter *support.Linter, templatesPath string) (lintError support.LintError) { + if _, err := os.Stat(templatesPath); err != nil { + lintError = fmt.Errorf("Templates directory not found") + } + return +} + +func validateTemplatesDir(linter *support.Linter, templatesPath string) (lintError support.LintError) { + fi, err := os.Stat(templatesPath) + if err == nil && !fi.IsDir() { + lintError = fmt.Errorf("'templates' is not a directory") + } + return +} + +func validateTemplatesParseable(linter *support.Linter, templatesPath string) (lintError support.LintError) { + tpl := template.New("tpl").Funcs(sprig.TxtFuncMap()) + + lintError = filepath.Walk(templatesPath, func(name string, fi os.FileInfo, e error) error { + if e != nil { + return e + } + if fi.IsDir() { + return nil + } + + data, err := ioutil.ReadFile(name) + if err != nil { + lintError = fmt.Errorf("cannot read %s: %s", name, err) + return lintError + } + + newtpl, err := tpl.Parse(string(data)) + if err != nil { + lintError = fmt.Errorf("error processing %s: %s", name, err) + return lintError + } + tpl = newtpl + return nil + }) + + return +} diff --git a/pkg/lint/template_test.go b/pkg/lint/rules/template_test.go similarity index 55% rename from pkg/lint/template_test.go rename to pkg/lint/rules/template_test.go index b8c7eadd4..5f2b727ab 100644 --- a/pkg/lint/template_test.go +++ b/pkg/lint/rules/template_test.go @@ -1,6 +1,7 @@ -package lint +package rules import ( + "k8s.io/helm/pkg/lint/support" "strings" "testing" ) @@ -8,10 +9,12 @@ import ( const templateTestBasedir = "./testdata/albatross" func TestTemplate(t *testing.T) { - res := Templates(templateTestBasedir) + linter := support.Linter{ChartDir: templateTestBasedir} + Templates(&linter) + res := linter.Messages if len(res) != 1 { - t.Fatalf("Expected one error, got %d", len(res)) + t.Fatalf("Expected one error, got %d, %v", len(res), res) } if !strings.Contains(res[0].Text, "deliberateSyntaxError") { diff --git a/pkg/lint/testdata/albatross/Chart.yaml b/pkg/lint/rules/testdata/albatross/Chart.yaml similarity index 100% rename from pkg/lint/testdata/albatross/Chart.yaml rename to pkg/lint/rules/testdata/albatross/Chart.yaml diff --git a/pkg/lint/testdata/albatross/templates/albatross.yaml b/pkg/lint/rules/testdata/albatross/templates/albatross.yaml similarity index 100% rename from pkg/lint/testdata/albatross/templates/albatross.yaml rename to pkg/lint/rules/testdata/albatross/templates/albatross.yaml diff --git a/pkg/lint/testdata/albatross/templates/fail.yaml b/pkg/lint/rules/testdata/albatross/templates/fail.yaml similarity index 100% rename from pkg/lint/testdata/albatross/templates/fail.yaml rename to pkg/lint/rules/testdata/albatross/templates/fail.yaml diff --git a/pkg/lint/testdata/albatross/values.yaml b/pkg/lint/rules/testdata/albatross/values.yaml similarity index 100% rename from pkg/lint/testdata/albatross/values.yaml rename to pkg/lint/rules/testdata/albatross/values.yaml diff --git a/pkg/lint/testdata/badchartfile/Chart.yaml b/pkg/lint/rules/testdata/badchartfile/Chart.yaml similarity index 100% rename from pkg/lint/testdata/badchartfile/Chart.yaml rename to pkg/lint/rules/testdata/badchartfile/Chart.yaml diff --git a/pkg/lint/testdata/badchartfile/values.yaml b/pkg/lint/rules/testdata/badchartfile/values.yaml similarity index 100% rename from pkg/lint/testdata/badchartfile/values.yaml rename to pkg/lint/rules/testdata/badchartfile/values.yaml diff --git a/pkg/lint/testdata/badvaluesfile/Chart.yaml b/pkg/lint/rules/testdata/badvaluesfile/Chart.yaml similarity index 100% rename from pkg/lint/testdata/badvaluesfile/Chart.yaml rename to pkg/lint/rules/testdata/badvaluesfile/Chart.yaml diff --git a/pkg/lint/testdata/badvaluesfile/templates/badvaluesfile.yaml b/pkg/lint/rules/testdata/badvaluesfile/templates/badvaluesfile.yaml similarity index 100% rename from pkg/lint/testdata/badvaluesfile/templates/badvaluesfile.yaml rename to pkg/lint/rules/testdata/badvaluesfile/templates/badvaluesfile.yaml diff --git a/pkg/lint/testdata/badvaluesfile/values.yaml b/pkg/lint/rules/testdata/badvaluesfile/values.yaml similarity index 100% rename from pkg/lint/testdata/badvaluesfile/values.yaml rename to pkg/lint/rules/testdata/badvaluesfile/values.yaml diff --git a/pkg/lint/testdata/goodone/Chart.yaml b/pkg/lint/rules/testdata/goodone/Chart.yaml similarity index 100% rename from pkg/lint/testdata/goodone/Chart.yaml rename to pkg/lint/rules/testdata/goodone/Chart.yaml diff --git a/pkg/lint/testdata/goodone/templates/goodone.yaml b/pkg/lint/rules/testdata/goodone/templates/goodone.yaml similarity index 100% rename from pkg/lint/testdata/goodone/templates/goodone.yaml rename to pkg/lint/rules/testdata/goodone/templates/goodone.yaml diff --git a/pkg/lint/testdata/goodone/values.yaml b/pkg/lint/rules/testdata/goodone/values.yaml similarity index 100% rename from pkg/lint/testdata/goodone/values.yaml rename to pkg/lint/rules/testdata/goodone/values.yaml diff --git a/pkg/lint/rules/values.go b/pkg/lint/rules/values.go new file mode 100644 index 000000000..56c23532b --- /dev/null +++ b/pkg/lint/rules/values.go @@ -0,0 +1,37 @@ +package rules + +import ( + "fmt" + "k8s.io/helm/pkg/chartutil" + "k8s.io/helm/pkg/lint/support" + "os" + "path/filepath" +) + +// Values lints a chart's values.yaml file. +func Values(linter *support.Linter) { + vf := filepath.Join(linter.ChartDir, "values.yaml") + fileExists := linter.RunLinterRule(support.InfoSev, validateValuesFileExistence(linter, vf)) + + if !fileExists { + return + } + + linter.RunLinterRule(support.ErrorSev, validateValuesFile(linter, vf)) +} + +func validateValuesFileExistence(linter *support.Linter, valuesPath string) (lintError support.LintError) { + _, err := os.Stat(valuesPath) + if err != nil { + lintError = fmt.Errorf("values.yaml file does not exists") + } + return +} + +func validateValuesFile(linter *support.Linter, valuesPath string) (lintError support.LintError) { + _, err := chartutil.ReadValuesFile(valuesPath) + if err != nil { + lintError = fmt.Errorf("values.yaml is malformed: %s", err.Error()) + } + return +} diff --git a/pkg/lint/doc.go b/pkg/lint/support/doc.go similarity index 91% rename from pkg/lint/doc.go rename to pkg/lint/support/doc.go index f2cc19670..36bb7a248 100644 --- a/pkg/lint/doc.go +++ b/pkg/lint/support/doc.go @@ -3,4 +3,4 @@ Linting is the process of testing charts for errors or warnings regarding formatting, compilation, or standards compliance. */ -package lint +package support diff --git a/pkg/lint/message.go b/pkg/lint/support/message.go similarity index 67% rename from pkg/lint/message.go rename to pkg/lint/support/message.go index 62bf9cf58..e1efb52c2 100644 --- a/pkg/lint/message.go +++ b/pkg/lint/support/message.go @@ -1,4 +1,4 @@ -package lint +package support import "fmt" @@ -22,14 +22,33 @@ var sev = []string{"UNKNOWN", "INFO", "WARNING", "ERROR"} // Message is a linting output message type Message struct { // Severity is one of the *Sev constants - Severity int + Severity Severity // Text contains the message text Text string } +type Linter struct { + Messages []Message + ChartDir string +} + +type LintError interface { + error +} + +type ValidationFunc func(*Linter) LintError + // String prints a string representation of this Message. // // Implements fmt.Stringer. func (m Message) String() string { return fmt.Sprintf("[%s] %s", sev[m.Severity], m.Text) } + +// Returns true if the validation passed +func (l *Linter) RunLinterRule(severity Severity, lintError LintError) bool { + if lintError != nil { + l.Messages = append(l.Messages, Message{Text: lintError.Error(), Severity: severity}) + } + return lintError == nil +} diff --git a/pkg/lint/message_test.go b/pkg/lint/support/message_test.go similarity index 96% rename from pkg/lint/message_test.go rename to pkg/lint/support/message_test.go index 08ab12ad8..2cba98dc3 100644 --- a/pkg/lint/message_test.go +++ b/pkg/lint/support/message_test.go @@ -1,4 +1,4 @@ -package lint +package support import ( "fmt" diff --git a/pkg/lint/template.go b/pkg/lint/template.go deleted file mode 100644 index 6a5760835..000000000 --- a/pkg/lint/template.go +++ /dev/null @@ -1,64 +0,0 @@ -package lint - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "text/template" - - "github.com/Masterminds/sprig" -) - -// Templates lints a chart's templates. -func Templates(basepath string) (messages []Message) { - messages = []Message{} - path := filepath.Join(basepath, "templates") - if fi, err := os.Stat(path); err != nil { - messages = append(messages, Message{Severity: WarningSev, Text: "No templates"}) - return - } else if !fi.IsDir() { - messages = append(messages, Message{Severity: ErrorSev, Text: "'templates' is not a directory"}) - return - } - - tpl := template.New("tpl").Funcs(sprig.TxtFuncMap()) - - err := filepath.Walk(basepath, func(name string, fi os.FileInfo, e error) error { - // If an error is returned, we fail. Non-fatal errors should just be - // added directly to messages. - if e != nil { - return e - } - if fi.IsDir() { - return nil - } - - data, err := ioutil.ReadFile(name) - if err != nil { - messages = append(messages, Message{ - Severity: ErrorSev, - Text: fmt.Sprintf("cannot read %s: %s", name, err), - }) - return nil - } - - // An error rendering a file should emit a warning. - newtpl, err := tpl.Parse(string(data)) - if err != nil { - messages = append(messages, Message{ - Severity: ErrorSev, - Text: fmt.Sprintf("error processing %s: %s", name, err), - }) - return nil - } - tpl = newtpl - return nil - }) - - if err != nil { - messages = append(messages, Message{Severity: ErrorSev, Text: err.Error()}) - } - - return -} diff --git a/pkg/lint/values.go b/pkg/lint/values.go deleted file mode 100644 index 2549f2937..000000000 --- a/pkg/lint/values.go +++ /dev/null @@ -1,23 +0,0 @@ -package lint - -import ( - "os" - "path/filepath" - - "k8s.io/helm/pkg/chartutil" -) - -// Values lints a chart's values.yaml file. -func Values(basepath string) (messages []Message) { - vf := filepath.Join(basepath, "values.yaml") - messages = []Message{} - if _, err := os.Stat(vf); err != nil { - messages = append(messages, Message{Severity: InfoSev, Text: "No values.yaml file"}) - return - } - _, err := chartutil.ReadValuesFile(vf) - if err != nil { - messages = append(messages, Message{Severity: ErrorSev, Text: err.Error()}) - } - return messages -} diff --git a/pkg/proto/hapi/chart/metadata.pb.go b/pkg/proto/hapi/chart/metadata.pb.go index 1109e8b44..b753f8608 100644 --- a/pkg/proto/hapi/chart/metadata.pb.go +++ b/pkg/proto/hapi/chart/metadata.pb.go @@ -13,6 +13,27 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +type Metadata_Engine int32 + +const ( + Metadata_UNKNOWN Metadata_Engine = 0 + Metadata_GOTPL Metadata_Engine = 1 +) + +var Metadata_Engine_name = map[int32]string{ + 0: "UNKNOWN", + 1: "GOTPL", +} +var Metadata_Engine_value = map[string]int32{ + "UNKNOWN": 0, + "GOTPL": 1, +} + +func (x Metadata_Engine) String() string { + return proto.EnumName(Metadata_Engine_name, int32(x)) +} +func (Metadata_Engine) EnumDescriptor() ([]byte, []int) { return fileDescriptor2, []int{1, 0} } + // Maintainer describes a Chart maintainer. type Maintainer struct { // Name is a user name or organization name @@ -63,23 +84,26 @@ func (m *Metadata) GetMaintainers() []*Maintainer { func init() { proto.RegisterType((*Maintainer)(nil), "hapi.chart.Maintainer") proto.RegisterType((*Metadata)(nil), "hapi.chart.Metadata") + proto.RegisterEnum("hapi.chart.Metadata_Engine", Metadata_Engine_name, Metadata_Engine_value) } var fileDescriptor2 = []byte{ - // 234 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x90, 0xbd, 0x4f, 0xc3, 0x40, - 0x0c, 0xc5, 0x15, 0xda, 0x7c, 0xe0, 0x6c, 0x16, 0xaa, 0x0c, 0x53, 0xd4, 0x89, 0x29, 0x95, 0x40, - 0x42, 0xcc, 0xec, 0x5d, 0x3a, 0xb2, 0x99, 0xc4, 0x22, 0x27, 0x48, 0x2e, 0xba, 0x3b, 0x40, 0xfc, - 0xe3, 0xcc, 0x5c, 0xdc, 0xaf, 0x0c, 0x1d, 0x22, 0xbd, 0xf7, 0x7e, 0x79, 0x3e, 0xd9, 0x70, 0xdb, - 0xf1, 0x68, 0x36, 0x4d, 0xc7, 0x2e, 0x6c, 0x7a, 0x09, 0xdc, 0x72, 0xe0, 0x7a, 0x74, 0x36, 0x58, - 0x84, 0x09, 0xd5, 0x8a, 0xd6, 0x4f, 0x00, 0x5b, 0x36, 0x43, 0x88, 0x9f, 0x38, 0x44, 0x58, 0x0e, - 0xdc, 0x0b, 0x25, 0x55, 0x72, 0x7f, 0xbd, 0x53, 0x8d, 0x37, 0x90, 0x4a, 0xcf, 0xe6, 0x93, 0xae, - 0x34, 0xdc, 0x9b, 0xf5, 0x5f, 0x02, 0xc5, 0xf6, 0x30, 0xf6, 0x62, 0x2d, 0x66, 0x9d, 0x8d, 0xd9, - 0xbe, 0xa5, 0x1a, 0x09, 0x72, 0x6f, 0xbf, 0x5c, 0x23, 0x9e, 0x16, 0xd5, 0x22, 0xc6, 0x47, 0x3b, - 0x91, 0x6f, 0x71, 0xde, 0xd8, 0x81, 0x96, 0x5a, 0x38, 0x5a, 0xac, 0xa0, 0x6c, 0xc5, 0x37, 0xce, - 0x8c, 0x61, 0xa2, 0xa9, 0xd2, 0x79, 0x84, 0x77, 0x50, 0x7c, 0xc8, 0xef, 0x8f, 0x75, 0xad, 0xa7, - 0x4c, 0xc7, 0x9e, 0x3c, 0x3e, 0x43, 0xd9, 0x9f, 0xd6, 0xf3, 0x94, 0x47, 0x5c, 0x3e, 0xac, 0xea, - 0xf3, 0x01, 0xea, 0xf3, 0xf6, 0xbb, 0xf9, 0xaf, 0xb8, 0x82, 0x4c, 0x86, 0xf7, 0xa8, 0xa9, 0xd0, - 0x27, 0x0f, 0xee, 0x25, 0x7f, 0x4d, 0xb5, 0xf8, 0x96, 0xe9, 0x31, 0x1f, 0xff, 0x03, 0x00, 0x00, - 0xff, 0xff, 0x6f, 0x4a, 0x7b, 0xd0, 0x69, 0x01, 0x00, 0x00, + // 266 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x90, 0x4b, 0x4b, 0xc4, 0x40, + 0x10, 0x84, 0xdd, 0x47, 0x1e, 0xdb, 0xb9, 0x2c, 0x8d, 0x2c, 0xa3, 0xa7, 0x90, 0x93, 0xa7, 0x2c, + 0x28, 0x88, 0x67, 0x41, 0x3c, 0xe8, 0x66, 0x65, 0x51, 0x04, 0x6f, 0x63, 0xd2, 0x98, 0x41, 0x93, + 0x09, 0x33, 0xa3, 0xe2, 0x3f, 0xf1, 0xe7, 0x3a, 0xe9, 0x7d, 0x1e, 0x3c, 0x04, 0xaa, 0xea, 0x4b, + 0xd7, 0xd0, 0x0d, 0x27, 0xb5, 0xec, 0xd4, 0xbc, 0xac, 0xa5, 0x71, 0xf3, 0x86, 0x9c, 0xac, 0xa4, + 0x93, 0x79, 0x67, 0xb4, 0xd3, 0x08, 0x3d, 0xca, 0x19, 0x65, 0x97, 0x00, 0x0b, 0xa9, 0x5a, 0xe7, + 0x3f, 0x32, 0x88, 0x30, 0x6e, 0x65, 0x43, 0x62, 0x90, 0x0e, 0xce, 0x26, 0x2b, 0xd6, 0x78, 0x0c, + 0x01, 0x35, 0x52, 0x7d, 0x88, 0x21, 0x87, 0x6b, 0x93, 0xfd, 0x0e, 0x21, 0x5e, 0x6c, 0x6a, 0xff, + 0x1d, 0xf3, 0x59, 0xad, 0x7d, 0xb6, 0x9e, 0x62, 0x8d, 0x02, 0x22, 0xab, 0x3f, 0x4d, 0x49, 0x56, + 0x8c, 0xd2, 0x91, 0x8f, 0xb7, 0xb6, 0x27, 0x5f, 0x64, 0xac, 0xd2, 0xad, 0x18, 0xf3, 0xc0, 0xd6, + 0x62, 0x0a, 0x49, 0x45, 0xb6, 0x34, 0xaa, 0x73, 0x3d, 0x0d, 0x98, 0x1e, 0x46, 0x78, 0x0a, 0xf1, + 0x3b, 0xfd, 0x7c, 0x6b, 0x53, 0x59, 0x11, 0x72, 0xed, 0xce, 0xe3, 0x15, 0x24, 0xcd, 0x6e, 0x3d, + 0x2b, 0x22, 0x8f, 0x93, 0xf3, 0x59, 0xbe, 0x3f, 0x40, 0xbe, 0xdf, 0x7e, 0x75, 0xf8, 0x2b, 0xce, + 0x20, 0xa4, 0xf6, 0xcd, 0x6b, 0x11, 0xf3, 0x93, 0x1b, 0x97, 0xa5, 0x10, 0xde, 0xb0, 0xc2, 0x04, + 0xa2, 0xa7, 0xe2, 0xae, 0x58, 0x3e, 0x17, 0xd3, 0x23, 0x9c, 0x40, 0x70, 0xbb, 0x7c, 0x7c, 0xb8, + 0x9f, 0x0e, 0xae, 0xa3, 0x97, 0x80, 0xab, 0x5f, 0x43, 0x3e, 0xf7, 0xc5, 0x5f, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xe5, 0xf8, 0x57, 0xee, 0x8b, 0x01, 0x00, 0x00, }