mirror of https://github.com/helm/helm.git
New Chart linter structure
Fixed tests Adding chart name linter Add lint error Moving to blocks Moving to method Moved lint rules to functions Semantic version validation Linting engine Adding sources and home validations Sharing file loading Sharing file loading Rolling back readme Rewriting other linters Fixing tests Typo Using chart.Metadata Fixing format Adding UNKNOWN in Engine Adding tabs Fixing tabs
This commit is contained in:
parent
7a227440f7
commit
c2459c06bf
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,5 +4,3 @@ version: 0.1.0
|
|||
home: https://k8s.io/helm
|
||||
sources:
|
||||
- https://github.com/kubernetes/helm
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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") {
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package lint
|
||||
package support
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue