refactoring

Signed-off-by: bartem <bartem@ozon.ru>
pull/12280/head
bartem 2 years ago
parent a9694a1dcc
commit 799f34f673

@ -22,7 +22,6 @@ import (
"strings" "strings"
"github.com/pkg/errors" "github.com/pkg/errors"
"helm.sh/helm/v3/pkg/lint/rules"
"helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/lint" "helm.sh/helm/v3/pkg/lint"
@ -127,5 +126,8 @@ func lintChart(path string, vals map[string]interface{}, releaseName, namespace
return linter, errors.Wrap(err, "unable to check Chart.yaml file in chart") return linter, errors.Wrap(err, "unable to check Chart.yaml file in chart")
} }
return lint.AllWithKubeVersion(chartPath, vals, namespace, kubeVersion, rules.WithReleaseName(releaseName)), nil return lint.AllWithOptions(chartPath, vals, namespace,
lint.WithReleaseName(releaseName),
lint.WithKubeVersion(kubeVersion),
), nil
} }

@ -25,19 +25,32 @@ 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 map[string]interface{}, namespace string, _ bool, opts ...rules.TemplateOption) support.Linter { // Deprecated, use AllWithOptions instead.
return AllWithKubeVersion(basedir, values, namespace, nil, opts...) func All(basedir string, values map[string]interface{}, namespace string, _ bool) support.Linter {
return AllWithOptions(basedir, values, namespace, nil)
} }
// AllWithKubeVersion runs all the available linters on the given base directory, allowing to specify the kubernetes version. // AllWithKubeVersion runs all the available linters on the given base directory, allowing to specify the kubernetes version.
func AllWithKubeVersion(basedir string, values map[string]interface{}, namespace string, kubeVersion *chartutil.KubeVersion, opts ...rules.TemplateOption) support.Linter { // Deprecated, use AllWithOptions instead.
func AllWithKubeVersion(basedir string, values map[string]interface{}, namespace string, kubeVersion *chartutil.KubeVersion) support.Linter {
return AllWithOptions(basedir, values, namespace, WithKubeVersion(kubeVersion))
}
// AllWithOptions runs all the available linters on the given base directory, allowing to specify different options.
func AllWithOptions(basedir string, values map[string]interface{}, namespace string, options ...LinterOption) 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}
for _, optFn := range options {
optFn(&linter)
}
rules.Chartfile(&linter) rules.Chartfile(&linter)
rules.ValuesWithOverrides(&linter, values) rules.ValuesWithOverrides(&linter, values)
rules.TemplatesWithKubeVersion(&linter, values, namespace, kubeVersion, opts...) rules.TemplatesV2(&linter, values, namespace)
rules.Dependencies(&linter) rules.Dependencies(&linter)
return linter return linter
} }

@ -0,0 +1,22 @@
package lint
import (
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/lint/support"
)
type LinterOption func(linter *support.Linter)
// WithReleaseName specifies chart release name
func WithReleaseName(name string) LinterOption {
return func(linter *support.Linter) {
linter.ReleaseName = name
}
}
// WithKubeVersion specifies kube version
func WithKubeVersion(version *chartutil.KubeVersion) LinterOption {
return func(linter *support.Linter) {
linter.KubeVersion = version
}
}

@ -39,7 +39,7 @@ const subChartValuesDir = "rules/testdata/withsubchart"
const malformedTemplate = "rules/testdata/malformed-template" const malformedTemplate = "rules/testdata/malformed-template"
func TestBadChart(t *testing.T) { func TestBadChart(t *testing.T) {
m := All(badChartDir, values, defaultName, namespace, strict).Messages m := AllWithOptions(badChartDir, values, namespace, WithReleaseName(defaultName)).Messages
if len(m) != 8 { if len(m) != 8 {
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)
@ -83,7 +83,7 @@ func TestBadChart(t *testing.T) {
} }
func TestInvalidYaml(t *testing.T) { func TestInvalidYaml(t *testing.T) {
m := All(badYamlFileDir, values, defaultName, namespace, strict).Messages m := AllWithOptions(badYamlFileDir, values, namespace, WithReleaseName(defaultName)).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)
} }
@ -93,7 +93,7 @@ func TestInvalidYaml(t *testing.T) {
} }
func TestBadValues(t *testing.T) { func TestBadValues(t *testing.T) {
m := All(badValuesFileDir, values, defaultName, namespace, strict).Messages m := AllWithOptions(badValuesFileDir, values, namespace, WithReleaseName(defaultName)).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)
} }
@ -103,7 +103,7 @@ func TestBadValues(t *testing.T) {
} }
func TestGoodChart(t *testing.T) { func TestGoodChart(t *testing.T) {
m := All(goodChartDir, values, defaultName, namespace, strict).Messages m := AllWithOptions(goodChartDir, values, namespace, WithReleaseName(defaultName)).Messages
if len(m) != 0 { if len(m) != 0 {
t.Error("All returned linter messages when it shouldn't have") t.Error("All returned linter messages when it shouldn't have")
for i, msg := range m { for i, msg := range m {
@ -127,7 +127,7 @@ func TestHelmCreateChart(t *testing.T) {
// Note: we test with strict=true here, even though others have // Note: we test with strict=true here, even though others have
// strict = false. // strict = false.
m := All(createdChart, values, defaultName, namespace, true).Messages m := AllWithOptions(createdChart, values, namespace, WithReleaseName(defaultName)).Messages
if ll := len(m); ll != 1 { if ll := len(m); ll != 1 {
t.Errorf("All should have had exactly 1 error. Got %d", ll) t.Errorf("All should have had exactly 1 error. Got %d", ll)
for i, msg := range m { for i, msg := range m {
@ -141,7 +141,7 @@ func TestHelmCreateChart(t *testing.T) {
// lint ignores import-values // lint ignores import-values
// See https://github.com/helm/helm/issues/9658 // See https://github.com/helm/helm/issues/9658
func TestSubChartValuesChart(t *testing.T) { func TestSubChartValuesChart(t *testing.T) {
m := All(subChartValuesDir, values, defaultName, namespace, strict).Messages m := AllWithOptions(subChartValuesDir, values, namespace, WithReleaseName(defaultName)).Messages
if len(m) != 0 { if len(m) != 0 {
t.Error("All returned linter messages when it shouldn't have") t.Error("All returned linter messages when it shouldn't have")
for i, msg := range m { for i, msg := range m {
@ -157,7 +157,7 @@ func TestMalformedTemplate(t *testing.T) {
ch := make(chan int, 1) ch := make(chan int, 1)
var m []support.Message var m []support.Message
go func() { go func() {
m = All(malformedTemplate, values, defaultName, namespace, strict).Messages m = AllWithOptions(malformedTemplate, values, namespace, WithReleaseName(defaultName)).Messages
ch <- 1 ch <- 1
}() }()
select { select {

@ -45,12 +45,20 @@ var (
) )
// 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, opts ...TemplateOption) { // Deprecated, use TemplatesV2 instead.
TemplatesWithKubeVersion(linter, values, namespace, nil, opts...) func Templates(linter *support.Linter, values map[string]interface{}, namespace string, _ bool) {
TemplatesV2(linter, values, namespace)
} }
// TemplatesWithKubeVersion lints the templates in the Linter, allowing to specify the kubernetes version. // TemplatesWithKubeVersion lints the templates in the Linter, allowing to specify the kubernetes version.
func TemplatesWithKubeVersion(linter *support.Linter, values map[string]interface{}, namespace string, kubeVersion *chartutil.KubeVersion, opts ...TemplateOption) { // Deprecated, use TemplatesV2 instead.
func TemplatesWithKubeVersion(linter *support.Linter, values map[string]interface{}, namespace string, kubeVersion *chartutil.KubeVersion) {
linter.KubeVersion = kubeVersion
TemplatesV2(linter, values, namespace)
}
// TemplatesV2 lints the templates in the Linter.
func TemplatesV2(linter *support.Linter, values map[string]interface{}, namespace string) {
fpath := "templates/" fpath := "templates/"
templatesPath := filepath.Join(linter.ChartDir, fpath) templatesPath := filepath.Join(linter.ChartDir, fpath)
@ -70,19 +78,14 @@ func TemplatesWithKubeVersion(linter *support.Linter, values map[string]interfac
return return
} }
o := defaultTemplateOptions
for _, optFn := range opts {
optFn(o)
}
options := chartutil.ReleaseOptions{ options := chartutil.ReleaseOptions{
Name: o.releaseName, Name: linter.ReleaseName,
Namespace: namespace, Namespace: namespace,
} }
caps := chartutil.DefaultCapabilities.Copy() caps := chartutil.DefaultCapabilities.Copy()
if kubeVersion != nil { if linter.KubeVersion != nil {
caps.KubeVersion = *kubeVersion caps.KubeVersion = *linter.KubeVersion
} }
// lint ignores import-values // lint ignores import-values
@ -166,7 +169,7 @@ func TemplatesWithKubeVersion(linter *support.Linter, values map[string]interfac
// 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)) linter.RunLinterRule(support.WarningSev, fpath, validateMetadataName(yamlStruct))
linter.RunLinterRule(support.WarningSev, fpath, validateNoDeprecations(yamlStruct, kubeVersion)) linter.RunLinterRule(support.WarningSev, fpath, validateNoDeprecations(yamlStruct, linter.KubeVersion))
linter.RunLinterRule(support.ErrorSev, fpath, validateMatchSelector(yamlStruct, renderedContent)) linter.RunLinterRule(support.ErrorSev, fpath, validateMatchSelector(yamlStruct, renderedContent))
linter.RunLinterRule(support.ErrorSev, fpath, validateListAnnotations(yamlStruct, renderedContent)) linter.RunLinterRule(support.ErrorSev, fpath, validateListAnnotations(yamlStruct, renderedContent))

@ -1,20 +0,0 @@
package rules
type (
templateOptions struct {
releaseName string
}
TemplateOption func(o *templateOptions)
)
var defaultTemplateOptions = &templateOptions{
releaseName: "test-release",
}
// WithReleaseName specify release name for linter
func WithReleaseName(name string) TemplateOption {
return func(o *templateOptions) {
o.releaseName = name
}
}

@ -51,11 +51,10 @@ var values = map[string]interface{}{"nameOverride": "", "httpPort": 80}
const defaultName = "test-release" const defaultName = "test-release"
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, ReleaseName: defaultName}
Templates(&linter, values, defaultName, namespace, strict) TemplatesV2(&linter, values, namespace)
res := linter.Messages res := linter.Messages
if len(res) != 1 { if len(res) != 1 {
@ -77,8 +76,8 @@ func TestTemplateIntegrationHappyPath(t *testing.T) {
os.Rename(wrongTemplatePath, ignoredTemplatePath) os.Rename(wrongTemplatePath, ignoredTemplatePath)
defer os.Rename(ignoredTemplatePath, wrongTemplatePath) defer os.Rename(ignoredTemplatePath, wrongTemplatePath)
linter := support.Linter{ChartDir: templateTestBasedir} linter := support.Linter{ChartDir: templateTestBasedir, ReleaseName: defaultName}
Templates(&linter, values, defaultName, namespace, strict) TemplatesV2(&linter, values, namespace)
res := linter.Messages res := linter.Messages
if len(res) != 0 { if len(res) != 0 {
@ -87,8 +86,8 @@ func TestTemplateIntegrationHappyPath(t *testing.T) {
} }
func TestV3Fail(t *testing.T) { func TestV3Fail(t *testing.T) {
linter := support.Linter{ChartDir: "./testdata/v3-fail"} linter := support.Linter{ChartDir: "./testdata/v3-fail", ReleaseName: defaultName}
Templates(&linter, values, defaultName, namespace, strict) TemplatesV2(&linter, values, namespace)
res := linter.Messages res := linter.Messages
if len(res) != 3 { if len(res) != 3 {
@ -107,8 +106,8 @@ func TestV3Fail(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", ReleaseName: defaultName}
Templates(&linter, values, defaultName, namespace, strict) TemplatesV2(&linter, values, namespace)
res := linter.Messages res := linter.Messages
if len(res) != 1 { if len(res) != 1 {
@ -227,8 +226,8 @@ func TestDeprecatedAPIFails(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
linter := support.Linter{ChartDir: filepath.Join(tmpdir, mychart.Name())} linter := support.Linter{ChartDir: filepath.Join(tmpdir, mychart.Name()), ReleaseName: defaultName}
Templates(&linter, values, defaultName, namespace, strict) TemplatesV2(&linter, values, namespace)
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)
@ -282,9 +281,10 @@ func TestStrictTemplateParsingMapError(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
linter := &support.Linter{ linter := &support.Linter{
ChartDir: filepath.Join(dir, ch.Metadata.Name), ChartDir: filepath.Join(dir, ch.Metadata.Name),
ReleaseName: defaultName,
} }
Templates(linter, ch.Values, defaultName, namespace, strict) TemplatesV2(linter, ch.Values, namespace)
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 {
@ -412,8 +412,8 @@ func TestEmptyWithCommentsManifests(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
linter := support.Linter{ChartDir: filepath.Join(tmpdir, mychart.Name())} linter := support.Linter{ChartDir: filepath.Join(tmpdir, mychart.Name()), ReleaseName: defaultName}
Templates(&linter, values, defaultName, namespace, strict) TemplatesV2(&linter, values, namespace)
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)

@ -16,7 +16,11 @@ limitations under the License.
package support package support
import "fmt" import (
"fmt"
"helm.sh/helm/v3/pkg/chartutil"
)
// Severity indicates the severity of a Message. // Severity indicates the severity of a Message.
const ( const (
@ -39,6 +43,8 @@ type Linter struct {
// The highest severity of all the failing lint rules // The highest severity of all the failing lint rules
HighestSeverity int HighestSeverity int
ChartDir string ChartDir string
ReleaseName string
KubeVersion *chartutil.KubeVersion
} }
// Message describes an error encountered while linting. // Message describes an error encountered while linting.

Loading…
Cancel
Save