diff --git a/helper/schema/schema.go b/helper/schema/schema.go index 558871ddb..0a79e1281 100644 --- a/helper/schema/schema.go +++ b/helper/schema/schema.go @@ -136,6 +136,8 @@ type Schema struct { // logic. It is yielded the provided config value as an interface{} that is // guaranteed to be of the proper Schema type, and it can yield warnings or // errors based on inspection of that value. + // + // ValidateFunc currently only works for primitive types. ValidateFunc SchemaValidateFunc } @@ -513,6 +515,13 @@ func (m schemaMap) InternalValidate(topSchemaMap schemaMap) error { } } } + + if v.ValidateFunc != nil { + switch v.Type { + case TypeList, TypeSet, TypeMap: + return fmt.Errorf("ValidateFunc is only supported on primitives.") + } + } } return nil @@ -1128,6 +1137,7 @@ func (m schemaMap) validatePrimitive( return nil, nil } + var decoded interface{} switch schema.Type { case TypeBool: // Verify that we can parse this as the correct type @@ -1135,28 +1145,36 @@ func (m schemaMap) validatePrimitive( if err := mapstructure.WeakDecode(raw, &n); err != nil { return nil, []error{err} } + decoded = n case TypeInt: // Verify that we can parse this as an int var n int if err := mapstructure.WeakDecode(raw, &n); err != nil { return nil, []error{err} } + decoded = n case TypeFloat: // Verify that we can parse this as an int var n float64 if err := mapstructure.WeakDecode(raw, &n); err != nil { return nil, []error{err} } + decoded = n case TypeString: // Verify that we can parse this as a string var n string if err := mapstructure.WeakDecode(raw, &n); err != nil { return nil, []error{err} } + decoded = n default: panic(fmt.Sprintf("Unknown validation type: %#v", schema.Type)) } + if schema.ValidateFunc != nil { + return schema.ValidateFunc(decoded) + } + return nil, nil } @@ -1186,16 +1204,6 @@ func (m schemaMap) validateType( "%q: [REMOVED] %s", k, schema.Removed)) } - if len(es) == 0 && schema.ValidateFunc != nil { - ws2, es2 := schema.ValidateFunc(raw) - for _, w := range ws2 { - ws = append(ws, fmt.Sprintf("%q: %s", k, w)) - } - for _, e := range es2 { - es = append(es, fmt.Errorf("%q: %s", k, e)) - } - } - return ws, es } diff --git a/helper/schema/schema_test.go b/helper/schema/schema_test.go index 36aa2e137..5ea108380 100644 --- a/helper/schema/schema_test.go +++ b/helper/schema/schema_test.go @@ -2796,6 +2796,20 @@ func TestSchemaMap_InternalValidate(t *testing.T) { }, false, }, + + // ValidateFunc on non-primitive + { + map[string]*Schema{ + "foo": &Schema{ + Type: TypeMap, + Required: true, + ValidateFunc: func(v interface{}) (ws []string, es []error) { + return + }, + }, + }, + true, + }, } for i, tc := range cases { @@ -3435,7 +3449,7 @@ func TestSchemaMap_Validate(t *testing.T) { }, Err: true, Errors: []error{ - fmt.Errorf(`"validate_me": something is not right here`), + fmt.Errorf(`something is not right here`), }, }, @@ -3455,6 +3469,23 @@ func TestSchemaMap_Validate(t *testing.T) { }, Err: true, }, + "ValidateFunc gets decoded type": { + Schema: map[string]*Schema{ + "maybe": &Schema{ + Type: TypeBool, + Required: true, + ValidateFunc: func(v interface{}) (ws []string, es []error) { + if _, ok := v.(bool); !ok { + t.Fatalf("Expected bool, got: %#v", v) + } + return + }, + }, + }, + Config: map[string]interface{}{ + "maybe": "true", + }, + }, } for tn, tc := range cases {