cleanup: Remove extra lint/rules.Template functions

Signed-off-by: George Jenkins <gvjenkins@gmail.com>
pull/30712/head
George Jenkins 6 months ago
parent 5b43b744b8
commit efcb5735e5

@ -58,7 +58,12 @@ func RunAll(baseDir string, values map[string]interface{}, namespace string, opt
rules.Chartfile(&result) rules.Chartfile(&result)
rules.ValuesWithOverrides(&result, values, lo.SkipSchemaValidation) rules.ValuesWithOverrides(&result, values, lo.SkipSchemaValidation)
rules.TemplatesWithSkipSchemaValidation(&result, values, namespace, lo.KubeVersion, lo.SkipSchemaValidation) rules.Templates(
&result,
namespace,
values,
rules.TemplateLinterKubeVersion(lo.KubeVersion),
rules.TemplateLinterSkipSchemaValidation(lo.SkipSchemaValidation))
rules.Dependencies(&result) rules.Dependencies(&result)
rules.Crds(&result) rules.Crds(&result)

@ -42,35 +42,66 @@ import (
) )
// Templates lints the templates in the Linter. // Templates lints the templates in the Linter.
func Templates(linter *support.Linter, values map[string]interface{}, namespace string, _ bool) { func Templates(linter *support.Linter, namespace string, values map[string]any, options ...TemplateLinterOption) {
TemplatesWithKubeVersion(linter, values, namespace, nil) templateLinter := newTemplateLinter(linter, namespace, values, options...)
templateLinter.Lint()
} }
// TemplatesWithKubeVersion lints the templates in the Linter, allowing to specify the kubernetes version. type TemplateLinterOption func(*templateLinter)
func TemplatesWithKubeVersion(linter *support.Linter, values map[string]interface{}, namespace string, kubeVersion *common.KubeVersion) {
TemplatesWithSkipSchemaValidation(linter, values, namespace, kubeVersion, false) func TemplateLinterKubeVersion(kubeVersion *common.KubeVersion) TemplateLinterOption {
return func(tl *templateLinter) {
tl.kubeVersion = kubeVersion
}
}
func TemplateLinterSkipSchemaValidation(skipSchemaValidation bool) TemplateLinterOption {
return func(tl *templateLinter) {
tl.skipSchemaValidation = skipSchemaValidation
}
} }
// TemplatesWithSkipSchemaValidation lints the templates in the Linter, allowing to specify the kubernetes version and if schema validation is enabled or not. func newTemplateLinter(linter *support.Linter, namespace string, values map[string]any, options ...TemplateLinterOption) templateLinter {
func TemplatesWithSkipSchemaValidation(linter *support.Linter, values map[string]interface{}, namespace string, kubeVersion *common.KubeVersion, skipSchemaValidation bool) {
fpath := "templates/" result := templateLinter{
templatesPath := filepath.Join(linter.ChartDir, fpath) linter: linter,
values: values,
namespace: namespace,
}
// Templates directory is optional for now for _, o := range options {
templatesDirExists := linter.RunLinterRule(support.WarningSev, fpath, templatesDirExists(templatesPath)) o(&result)
}
return result
}
type templateLinter struct {
linter *support.Linter
values map[string]any
namespace string
kubeVersion *common.KubeVersion
skipSchemaValidation bool
}
func (t *templateLinter) Lint() {
templatesDir := "templates/"
templatesPath := filepath.Join(t.linter.ChartDir, templatesDir)
templatesDirExists := t.linter.RunLinterRule(support.WarningSev, templatesDir, templatesDirExists(templatesPath))
if !templatesDirExists { if !templatesDirExists {
return return
} }
validTemplatesDir := linter.RunLinterRule(support.ErrorSev, fpath, validateTemplatesDir(templatesPath)) validTemplatesDir := t.linter.RunLinterRule(support.ErrorSev, templatesDir, validateTemplatesDir(templatesPath))
if !validTemplatesDir { if !validTemplatesDir {
return return
} }
// Load chart and parse templates // Load chart and parse templates
chart, err := loader.Load(linter.ChartDir) chart, err := loader.Load(t.linter.ChartDir)
chartLoaded := linter.RunLinterRule(support.ErrorSev, fpath, err) chartLoaded := t.linter.RunLinterRule(support.ErrorSev, templatesDir, err)
if !chartLoaded { if !chartLoaded {
return return
@ -78,35 +109,35 @@ func TemplatesWithSkipSchemaValidation(linter *support.Linter, values map[string
options := common.ReleaseOptions{ options := common.ReleaseOptions{
Name: "test-release", Name: "test-release",
Namespace: namespace, Namespace: t.namespace,
} }
caps := common.DefaultCapabilities.Copy() caps := common.DefaultCapabilities.Copy()
if kubeVersion != nil { if t.kubeVersion != nil {
caps.KubeVersion = *kubeVersion caps.KubeVersion = *t.kubeVersion
} }
// lint ignores import-values // lint ignores import-values
// See https://github.com/helm/helm/issues/9658 // See https://github.com/helm/helm/issues/9658
if err := chartutil.ProcessDependencies(chart, values); err != nil { if err := chartutil.ProcessDependencies(chart, t.values); err != nil {
return return
} }
cvals, err := util.CoalesceValues(chart, values) cvals, err := util.CoalesceValues(chart, t.values)
if err != nil { if err != nil {
return return
} }
valuesToRender, err := util.ToRenderValuesWithSchemaValidation(chart, cvals, options, caps, skipSchemaValidation) valuesToRender, err := util.ToRenderValuesWithSchemaValidation(chart, cvals, options, caps, t.skipSchemaValidation)
if err != nil { if err != nil {
linter.RunLinterRule(support.ErrorSev, fpath, err) t.linter.RunLinterRule(support.ErrorSev, templatesDir, err)
return return
} }
var e engine.Engine var e engine.Engine
e.LintMode = true e.LintMode = true
renderedContentMap, err := e.Render(chart, valuesToRender) renderedContentMap, err := e.Render(chart, valuesToRender)
renderOk := linter.RunLinterRule(support.ErrorSev, fpath, err) renderOk := t.linter.RunLinterRule(support.ErrorSev, templatesDir, err)
if !renderOk { if !renderOk {
return return
@ -121,9 +152,8 @@ func TemplatesWithSkipSchemaValidation(linter *support.Linter, values map[string
*/ */
for _, template := range chart.Templates { for _, template := range chart.Templates {
fileName := template.Name fileName := template.Name
fpath = fileName
linter.RunLinterRule(support.ErrorSev, fpath, validateAllowedExtension(fileName)) t.linter.RunLinterRule(support.ErrorSev, fileName, validateAllowedExtension(fileName))
// We only apply the following lint rules to yaml files // We only apply the following lint rules to yaml files
if filepath.Ext(fileName) != ".yaml" || filepath.Ext(fileName) == ".yml" { if filepath.Ext(fileName) != ".yaml" || filepath.Ext(fileName) == ".yml" {
@ -139,7 +169,7 @@ func TemplatesWithSkipSchemaValidation(linter *support.Linter, values map[string
renderedContent := renderedContentMap[path.Join(chart.Name(), fileName)] renderedContent := renderedContentMap[path.Join(chart.Name(), fileName)]
if strings.TrimSpace(renderedContent) != "" { if strings.TrimSpace(renderedContent) != "" {
linter.RunLinterRule(support.WarningSev, fpath, validateTopIndentLevel(renderedContent)) t.linter.RunLinterRule(support.WarningSev, fileName, validateTopIndentLevel(renderedContent))
decoder := yaml.NewYAMLOrJSONDecoder(strings.NewReader(renderedContent), 4096) decoder := yaml.NewYAMLOrJSONDecoder(strings.NewReader(renderedContent), 4096)
@ -156,17 +186,17 @@ func TemplatesWithSkipSchemaValidation(linter *support.Linter, values map[string
// If YAML linting fails here, it will always fail in the next block as well, so we should return here. // If YAML linting fails here, it will always fail in the next block as well, so we should return here.
// fix https://github.com/helm/helm/issues/11391 // fix https://github.com/helm/helm/issues/11391
if !linter.RunLinterRule(support.ErrorSev, fpath, validateYamlContent(err)) { if !t.linter.RunLinterRule(support.ErrorSev, fileName, validateYamlContent(err)) {
return return
} }
if yamlStruct != nil { if yamlStruct != nil {
// NOTE: set to warnings to allow users to support out-of-date kubernetes // NOTE: set to warnings to allow users to support out-of-date kubernetes
// Refs https://github.com/helm/helm/issues/8596 // Refs https://github.com/helm/helm/issues/8596
linter.RunLinterRule(support.WarningSev, fpath, validateMetadataName(yamlStruct)) t.linter.RunLinterRule(support.WarningSev, fileName, validateMetadataName(yamlStruct))
linter.RunLinterRule(support.WarningSev, fpath, validateNoDeprecations(yamlStruct, kubeVersion)) t.linter.RunLinterRule(support.WarningSev, fileName, validateNoDeprecations(yamlStruct, t.kubeVersion))
linter.RunLinterRule(support.ErrorSev, fpath, validateMatchSelector(yamlStruct, renderedContent)) t.linter.RunLinterRule(support.ErrorSev, fileName, validateMatchSelector(yamlStruct, renderedContent))
linter.RunLinterRule(support.ErrorSev, fpath, validateListAnnotations(yamlStruct, renderedContent)) t.linter.RunLinterRule(support.ErrorSev, fileName, validateListAnnotations(yamlStruct, renderedContent))
} }
} }
} }
@ -234,6 +264,7 @@ func validateYamlContent(err error) error {
if err != nil { if err != nil {
return fmt.Errorf("unable to parse YAML: %w", err) return fmt.Errorf("unable to parse YAML: %w", err)
} }
return nil return nil
} }

@ -51,11 +51,14 @@ func TestValidateAllowedExtension(t *testing.T) {
var values = map[string]interface{}{"nameOverride": "", "httpPort": 80} var values = map[string]interface{}{"nameOverride": "", "httpPort": 80}
const namespace = "testNamespace" const namespace = "testNamespace"
const strict = false
func TestTemplateParsing(t *testing.T) { func TestTemplateParsing(t *testing.T) {
linter := support.Linter{ChartDir: templateTestBasedir} linter := support.Linter{ChartDir: templateTestBasedir}
Templates(&linter, values, namespace, strict) Templates(
&linter,
namespace,
values,
TemplateLinterSkipSchemaValidation(false))
res := linter.Messages res := linter.Messages
if len(res) != 1 { if len(res) != 1 {
@ -78,7 +81,11 @@ func TestTemplateIntegrationHappyPath(t *testing.T) {
defer os.Rename(ignoredTemplatePath, wrongTemplatePath) defer os.Rename(ignoredTemplatePath, wrongTemplatePath)
linter := support.Linter{ChartDir: templateTestBasedir} linter := support.Linter{ChartDir: templateTestBasedir}
Templates(&linter, values, namespace, strict) Templates(
&linter,
namespace,
values,
TemplateLinterSkipSchemaValidation(false))
res := linter.Messages res := linter.Messages
if len(res) != 0 { if len(res) != 0 {
@ -88,7 +95,11 @@ func TestTemplateIntegrationHappyPath(t *testing.T) {
func TestMultiTemplateFail(t *testing.T) { func TestMultiTemplateFail(t *testing.T) {
linter := support.Linter{ChartDir: "./testdata/multi-template-fail"} linter := support.Linter{ChartDir: "./testdata/multi-template-fail"}
Templates(&linter, values, namespace, strict) Templates(
&linter,
namespace,
values,
TemplateLinterSkipSchemaValidation(false))
res := linter.Messages res := linter.Messages
if len(res) != 1 { if len(res) != 1 {
@ -208,7 +219,11 @@ func TestDeprecatedAPIFails(t *testing.T) {
} }
linter := support.Linter{ChartDir: filepath.Join(tmpdir, mychart.Name())} linter := support.Linter{ChartDir: filepath.Join(tmpdir, mychart.Name())}
Templates(&linter, values, namespace, strict) Templates(
&linter,
namespace,
values,
TemplateLinterSkipSchemaValidation(false))
if l := len(linter.Messages); l != 1 { if l := len(linter.Messages); l != 1 {
for i, msg := range linter.Messages { for i, msg := range linter.Messages {
t.Logf("Message %d: %s", i, msg) t.Logf("Message %d: %s", i, msg)
@ -264,7 +279,11 @@ func TestStrictTemplateParsingMapError(t *testing.T) {
linter := &support.Linter{ linter := &support.Linter{
ChartDir: filepath.Join(dir, ch.Metadata.Name), ChartDir: filepath.Join(dir, ch.Metadata.Name),
} }
Templates(linter, ch.Values, namespace, strict) Templates(
linter,
namespace,
ch.Values,
TemplateLinterSkipSchemaValidation(false))
if len(linter.Messages) != 0 { if len(linter.Messages) != 0 {
t.Errorf("expected zero messages, got %d", len(linter.Messages)) t.Errorf("expected zero messages, got %d", len(linter.Messages))
for i, msg := range linter.Messages { for i, msg := range linter.Messages {
@ -393,7 +412,11 @@ func TestEmptyWithCommentsManifests(t *testing.T) {
} }
linter := support.Linter{ChartDir: filepath.Join(tmpdir, mychart.Name())} linter := support.Linter{ChartDir: filepath.Join(tmpdir, mychart.Name())}
Templates(&linter, values, namespace, strict) Templates(
&linter,
namespace,
values,
TemplateLinterSkipSchemaValidation(false))
if l := len(linter.Messages); l > 0 { if l := len(linter.Messages); l > 0 {
for i, msg := range linter.Messages { for i, msg := range linter.Messages {
t.Logf("Message %d: %s", i, msg) t.Logf("Message %d: %s", i, msg)

Loading…
Cancel
Save