helper/schema: limit ValidateFunc to primitives for now

I couldn't see a simple path get this working for Maps, Sets,
and Lists, so lets land it as a primitive-only schema feature.

I think validation on primitives comprises 80% of the use cases anyways.
This commit is contained in:
Paul Hinze 2015-06-11 07:06:30 -05:00
parent 49352db26f
commit a4912cc51f
2 changed files with 50 additions and 11 deletions

View File

@ -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
}

View File

@ -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 {