diff --git a/pkg/lint/rules/values.go b/pkg/lint/rules/values.go index c596687c5..79a294326 100644 --- a/pkg/lint/rules/values.go +++ b/pkg/lint/rules/values.go @@ -70,8 +70,9 @@ func validateValuesFile(valuesPath string, overrides map[string]interface{}) err // level values against the top-level expectations. Subchart values are not linted. // We could change that. For now, though, we retain that strategy, and thus can // coalesce tables (like reuse-values does) instead of doing the full chart - // CoalesceValues. - values = chartutil.CoalesceTables(values, overrides) + // CoalesceValues + coalescedValues := chartutil.CoalesceTables(make(map[string]interface{}, len(overrides)), overrides) + coalescedValues = chartutil.CoalesceTables(coalescedValues, values) ext := filepath.Ext(valuesPath) schemaPath := valuesPath[:len(valuesPath)-len(ext)] + ".schema.json" @@ -82,5 +83,5 @@ func validateValuesFile(valuesPath string, overrides map[string]interface{}) err if err != nil { return err } - return chartutil.ValidateAgainstSingleSchema(values, schema) + return chartutil.ValidateAgainstSingleSchema(coalescedValues, schema) } diff --git a/pkg/lint/rules/values_test.go b/pkg/lint/rules/values_test.go index 6d93d630e..23335cc01 100644 --- a/pkg/lint/rules/values_test.go +++ b/pkg/lint/rules/values_test.go @@ -118,6 +118,53 @@ func TestValidateValuesFileSchemaOverrides(t *testing.T) { } } +func TestValidateValuesFile(t *testing.T) { + tests := []struct { + name string + yaml string + overrides map[string]interface{} + errorMessage string + }{ + { + name: "value added", + yaml: "username: admin", + overrides: map[string]interface{}{"password": "swordfish"}, + }, + { + name: "value not overridden", + yaml: "username: admin\npassword:", + overrides: map[string]interface{}{"username": "anotherUser"}, + errorMessage: "Expected: string, given: null", + }, + { + name: "value overridden", + yaml: "username: admin\npassword:", + overrides: map[string]interface{}{"username": "anotherUser", "password": "swordfish"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmpdir := ensure.TempFile(t, "values.yaml", []byte(tt.yaml)) + defer os.RemoveAll(tmpdir) + createTestingSchema(t, tmpdir) + + valfile := filepath.Join(tmpdir, "values.yaml") + + err := validateValuesFile(valfile, tt.overrides) + + switch { + case err != nil && tt.errorMessage == "": + t.Errorf("Failed validation with %s", err) + case err == nil && tt.errorMessage != "": + t.Error("expected values file to fail parsing") + case err != nil && tt.errorMessage != "": + assert.Contains(t, err.Error(), tt.errorMessage, "Failed with unexpected error") + } + }) + } +} + func createTestingSchema(t *testing.T, dir string) string { t.Helper() schemafile := filepath.Join(dir, "values.schema.json")