Merge pull request #31275 from benoittgt/13414-v2

Extend --skip-schema-validation for lint command
pull/30743/head
Matt Farina 1 week ago committed by GitHub
commit 1a06fe9901
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

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

@ -32,7 +32,7 @@ import (
// they are only tested for well-formedness. // they are only tested for well-formedness.
// //
// If additional values are supplied, they are coalesced into the values in values.yaml. // If additional values are supplied, they are coalesced into the values in values.yaml.
func ValuesWithOverrides(linter *support.Linter, valueOverrides map[string]interface{}) { func ValuesWithOverrides(linter *support.Linter, valueOverrides map[string]interface{}, skipSchemaValidation bool) {
file := "values.yaml" file := "values.yaml"
vf := filepath.Join(linter.ChartDir, file) vf := filepath.Join(linter.ChartDir, file)
fileExists := linter.RunLinterRule(support.InfoSev, file, validateValuesFileExistence(vf)) fileExists := linter.RunLinterRule(support.InfoSev, file, validateValuesFileExistence(vf))
@ -41,7 +41,7 @@ func ValuesWithOverrides(linter *support.Linter, valueOverrides map[string]inter
return return
} }
linter.RunLinterRule(support.ErrorSev, file, validateValuesFile(vf, valueOverrides)) linter.RunLinterRule(support.ErrorSev, file, validateValuesFile(vf, valueOverrides, skipSchemaValidation))
} }
func validateValuesFileExistence(valuesPath string) error { func validateValuesFileExistence(valuesPath string) error {
@ -52,7 +52,7 @@ func validateValuesFileExistence(valuesPath string) error {
return nil return nil
} }
func validateValuesFile(valuesPath string, overrides map[string]interface{}) error { func validateValuesFile(valuesPath string, overrides map[string]interface{}, skipSchemaValidation bool) error {
values, err := common.ReadValuesFile(valuesPath) values, err := common.ReadValuesFile(valuesPath)
if err != nil { if err != nil {
return fmt.Errorf("unable to parse YAML: %w", err) return fmt.Errorf("unable to parse YAML: %w", err)
@ -75,5 +75,10 @@ func validateValuesFile(valuesPath string, overrides map[string]interface{}) err
if err != nil { if err != nil {
return err return err
} }
return util.ValidateAgainstSingleSchema(coalescedValues, schema)
if !skipSchemaValidation {
return util.ValidateAgainstSingleSchema(coalescedValues, schema)
}
return nil
} }

@ -67,7 +67,7 @@ func TestValidateValuesFileWellFormed(t *testing.T) {
` `
tmpdir := ensure.TempFile(t, "values.yaml", []byte(badYaml)) tmpdir := ensure.TempFile(t, "values.yaml", []byte(badYaml))
valfile := filepath.Join(tmpdir, "values.yaml") valfile := filepath.Join(tmpdir, "values.yaml")
if err := validateValuesFile(valfile, map[string]interface{}{}); err == nil { if err := validateValuesFile(valfile, map[string]interface{}{}, false); err == nil {
t.Fatal("expected values file to fail parsing") t.Fatal("expected values file to fail parsing")
} }
} }
@ -78,7 +78,7 @@ func TestValidateValuesFileSchema(t *testing.T) {
createTestingSchema(t, tmpdir) createTestingSchema(t, tmpdir)
valfile := filepath.Join(tmpdir, "values.yaml") valfile := filepath.Join(tmpdir, "values.yaml")
if err := validateValuesFile(valfile, map[string]interface{}{}); err != nil { if err := validateValuesFile(valfile, map[string]interface{}{}, false); err != nil {
t.Fatalf("Failed validation with %s", err) t.Fatalf("Failed validation with %s", err)
} }
} }
@ -91,7 +91,7 @@ func TestValidateValuesFileSchemaFailure(t *testing.T) {
valfile := filepath.Join(tmpdir, "values.yaml") valfile := filepath.Join(tmpdir, "values.yaml")
err := validateValuesFile(valfile, map[string]interface{}{}) err := validateValuesFile(valfile, map[string]interface{}{}, false)
if err == nil { if err == nil {
t.Fatal("expected values file to fail parsing") t.Fatal("expected values file to fail parsing")
} }
@ -99,6 +99,20 @@ func TestValidateValuesFileSchemaFailure(t *testing.T) {
assert.Contains(t, err.Error(), "- at '/username': got number, want string") assert.Contains(t, err.Error(), "- at '/username': got number, want string")
} }
func TestValidateValuesFileSchemaFailureButWithSkipSchemaValidation(t *testing.T) {
// 1234 is an int, not a string. This should fail normally but pass with skipSchemaValidation.
yaml := "username: 1234\npassword: swordfish"
tmpdir := ensure.TempFile(t, "values.yaml", []byte(yaml))
createTestingSchema(t, tmpdir)
valfile := filepath.Join(tmpdir, "values.yaml")
err := validateValuesFile(valfile, map[string]interface{}{}, true)
if err != nil {
t.Fatal("expected values file to pass parsing because of skipSchemaValidation")
}
}
func TestValidateValuesFileSchemaOverrides(t *testing.T) { func TestValidateValuesFileSchemaOverrides(t *testing.T) {
yaml := "username: admin" yaml := "username: admin"
overrides := map[string]interface{}{ overrides := map[string]interface{}{
@ -108,7 +122,7 @@ func TestValidateValuesFileSchemaOverrides(t *testing.T) {
createTestingSchema(t, tmpdir) createTestingSchema(t, tmpdir)
valfile := filepath.Join(tmpdir, "values.yaml") valfile := filepath.Join(tmpdir, "values.yaml")
if err := validateValuesFile(valfile, overrides); err != nil { if err := validateValuesFile(valfile, overrides, false); err != nil {
t.Fatalf("Failed validation with %s", err) t.Fatalf("Failed validation with %s", err)
} }
} }
@ -145,7 +159,7 @@ func TestValidateValuesFile(t *testing.T) {
valfile := filepath.Join(tmpdir, "values.yaml") valfile := filepath.Join(tmpdir, "values.yaml")
err := validateValuesFile(valfile, tt.overrides) err := validateValuesFile(valfile, tt.overrides, false)
switch { switch {
case err != nil && tt.errorMessage == "": case err != nil && tt.errorMessage == "":

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

@ -32,7 +32,7 @@ import (
// they are only tested for well-formedness. // they are only tested for well-formedness.
// //
// If additional values are supplied, they are coalesced into the values in values.yaml. // If additional values are supplied, they are coalesced into the values in values.yaml.
func ValuesWithOverrides(linter *support.Linter, valueOverrides map[string]interface{}) { func ValuesWithOverrides(linter *support.Linter, valueOverrides map[string]interface{}, skipSchemaValidation bool) {
file := "values.yaml" file := "values.yaml"
vf := filepath.Join(linter.ChartDir, file) vf := filepath.Join(linter.ChartDir, file)
fileExists := linter.RunLinterRule(support.InfoSev, file, validateValuesFileExistence(vf)) fileExists := linter.RunLinterRule(support.InfoSev, file, validateValuesFileExistence(vf))
@ -41,7 +41,7 @@ func ValuesWithOverrides(linter *support.Linter, valueOverrides map[string]inter
return return
} }
linter.RunLinterRule(support.ErrorSev, file, validateValuesFile(vf, valueOverrides)) linter.RunLinterRule(support.ErrorSev, file, validateValuesFile(vf, valueOverrides, skipSchemaValidation))
} }
func validateValuesFileExistence(valuesPath string) error { func validateValuesFileExistence(valuesPath string) error {
@ -52,7 +52,7 @@ func validateValuesFileExistence(valuesPath string) error {
return nil return nil
} }
func validateValuesFile(valuesPath string, overrides map[string]interface{}) error { func validateValuesFile(valuesPath string, overrides map[string]interface{}, skipSchemaValidation bool) error {
values, err := common.ReadValuesFile(valuesPath) values, err := common.ReadValuesFile(valuesPath)
if err != nil { if err != nil {
return fmt.Errorf("unable to parse YAML: %w", err) return fmt.Errorf("unable to parse YAML: %w", err)
@ -75,5 +75,10 @@ func validateValuesFile(valuesPath string, overrides map[string]interface{}) err
if err != nil { if err != nil {
return err return err
} }
return util.ValidateAgainstSingleSchema(coalescedValues, schema)
if !skipSchemaValidation {
return util.ValidateAgainstSingleSchema(coalescedValues, schema)
}
return nil
} }

@ -67,7 +67,7 @@ func TestValidateValuesFileWellFormed(t *testing.T) {
` `
tmpdir := ensure.TempFile(t, "values.yaml", []byte(badYaml)) tmpdir := ensure.TempFile(t, "values.yaml", []byte(badYaml))
valfile := filepath.Join(tmpdir, "values.yaml") valfile := filepath.Join(tmpdir, "values.yaml")
if err := validateValuesFile(valfile, map[string]interface{}{}); err == nil { if err := validateValuesFile(valfile, map[string]interface{}{}, false); err == nil {
t.Fatal("expected values file to fail parsing") t.Fatal("expected values file to fail parsing")
} }
} }
@ -78,7 +78,7 @@ func TestValidateValuesFileSchema(t *testing.T) {
createTestingSchema(t, tmpdir) createTestingSchema(t, tmpdir)
valfile := filepath.Join(tmpdir, "values.yaml") valfile := filepath.Join(tmpdir, "values.yaml")
if err := validateValuesFile(valfile, map[string]interface{}{}); err != nil { if err := validateValuesFile(valfile, map[string]interface{}{}, false); err != nil {
t.Fatalf("Failed validation with %s", err) t.Fatalf("Failed validation with %s", err)
} }
} }
@ -91,7 +91,7 @@ func TestValidateValuesFileSchemaFailure(t *testing.T) {
valfile := filepath.Join(tmpdir, "values.yaml") valfile := filepath.Join(tmpdir, "values.yaml")
err := validateValuesFile(valfile, map[string]interface{}{}) err := validateValuesFile(valfile, map[string]interface{}{}, false)
if err == nil { if err == nil {
t.Fatal("expected values file to fail parsing") t.Fatal("expected values file to fail parsing")
} }
@ -99,6 +99,20 @@ func TestValidateValuesFileSchemaFailure(t *testing.T) {
assert.Contains(t, err.Error(), "- at '/username': got number, want string") assert.Contains(t, err.Error(), "- at '/username': got number, want string")
} }
func TestValidateValuesFileSchemaFailureButWithSkipSchemaValidation(t *testing.T) {
// 1234 is an int, not a string. This should fail normally but pass with skipSchemaValidation.
yaml := "username: 1234\npassword: swordfish"
tmpdir := ensure.TempFile(t, "values.yaml", []byte(yaml))
createTestingSchema(t, tmpdir)
valfile := filepath.Join(tmpdir, "values.yaml")
err := validateValuesFile(valfile, map[string]interface{}{}, true)
if err != nil {
t.Fatal("expected values file to pass parsing because of skipSchemaValidation")
}
}
func TestValidateValuesFileSchemaOverrides(t *testing.T) { func TestValidateValuesFileSchemaOverrides(t *testing.T) {
yaml := "username: admin" yaml := "username: admin"
overrides := map[string]interface{}{ overrides := map[string]interface{}{
@ -108,7 +122,7 @@ func TestValidateValuesFileSchemaOverrides(t *testing.T) {
createTestingSchema(t, tmpdir) createTestingSchema(t, tmpdir)
valfile := filepath.Join(tmpdir, "values.yaml") valfile := filepath.Join(tmpdir, "values.yaml")
if err := validateValuesFile(valfile, overrides); err != nil { if err := validateValuesFile(valfile, overrides, false); err != nil {
t.Fatalf("Failed validation with %s", err) t.Fatalf("Failed validation with %s", err)
} }
} }
@ -145,7 +159,7 @@ func TestValidateValuesFile(t *testing.T) {
valfile := filepath.Join(tmpdir, "values.yaml") valfile := filepath.Join(tmpdir, "values.yaml")
err := validateValuesFile(valfile, tt.overrides) err := validateValuesFile(valfile, tt.overrides, false)
switch { switch {
case err != nil && tt.errorMessage == "": case err != nil && tt.errorMessage == "":

Loading…
Cancel
Save