Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support lists validation in resources schema definition #3641

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions builtin/providers/aws/resource_aws_elb.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ func resourceAwsElb() *schema.Resource {
},
},
Set: resourceAwsElbHealthCheckHash,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
vs := v.([]interface{})
if len(vs) > 1 {
errors = append(errors, fmt.Errorf("ELB doesn't support multiple health checks"))
}
return
},
},

"dns_name": &schema.Schema{
Expand Down
24 changes: 17 additions & 7 deletions helper/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,13 +542,6 @@ func (m schemaMap) InternalValidate(topSchemaMap schemaMap) error {
}
}
}

if v.ValidateFunc != nil {
switch v.Type {
case TypeList, TypeSet:
return fmt.Errorf("ValidateFunc is not yet supported on lists or sets.")
}
}
}

return nil
Expand Down Expand Up @@ -1078,6 +1071,23 @@ func (m schemaMap) validateList(
}
}

if schema.ValidateFunc != nil {
validatableList := make([]interface{}, 0, len(raws))
for _, raw := range raws {
switch schema.Elem.(type) {
case *Resource:
validatableMap := make(map[string]interface{})
for k, v := range raw.(map[string]interface{}) {
validatableMap[k] = v
}
validatableList = append(validatableList, validatableMap)
case *Schema:
validatableList = append(validatableList, raw)
}
}
return schema.ValidateFunc(validatableList, k)
}

return ws, es
}

Expand Down
91 changes: 91 additions & 0 deletions helper/schema/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2829,6 +2829,9 @@ func TestSchemaMap_InternalValidate(t *testing.T) {
"foo": &Schema{
Type: TypeList,
Optional: true,
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
return
},
Elem: &Resource{
Schema: map[string]*Schema{
"foo": &Schema{
Expand Down Expand Up @@ -3550,6 +3553,94 @@ func TestSchemaMap_Validate(t *testing.T) {
},
},

"Good set with ValidateFunc": {
Schema: map[string]*Schema{
"validate_me": &Schema{
Type: TypeSet,
Required: true,
Elem: &Schema{Type: TypeInt},
Set: func(a interface{}) int {
return a.(int)
},
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
if _, ok := v.([]interface{}); !ok {
t.Fatalf("Expected []interface{}, got: %#v", v)
}
return
},
},
},
Config: map[string]interface{}{
"validate_me": []interface{}{1},
},
Err: false,
},

"Bad set with ValidateFunc": {
Schema: map[string]*Schema{
"validate_me": &Schema{
Type: TypeSet,
Required: true,
Elem: &Schema{Type: TypeInt},
Set: func(a interface{}) int {
return a.(int)
},
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
es = append(es, fmt.Errorf("something is not right here"))
return
},
},
},
Config: map[string]interface{}{
"validate_me": []interface{}{1},
},
Err: true,
Errors: []error{
fmt.Errorf(`something is not right here`),
},
},

"Good list with ValidateFunc": {
Schema: map[string]*Schema{
"validate_me": &Schema{
Type: TypeList,
Required: true,
Elem: &Schema{Type: TypeInt},
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
if _, ok := v.([]interface{}); !ok {
t.Fatalf("Expected []interface{}, got: %#v", v)
}
return
},
},
},
Config: map[string]interface{}{
"validate_me": []interface{}{1, 2, 3},
},
Err: false,
},

"Bad list with ValidateFunc": {
Schema: map[string]*Schema{
"validate_me": &Schema{
Type: TypeList,
Required: true,
Elem: &Schema{Type: TypeInt},
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
es = append(es, fmt.Errorf("something is not right here"))
return
},
},
},
Config: map[string]interface{}{
"validate_me": []interface{}{1, 2, 3},
},
Err: true,
Errors: []error{
fmt.Errorf(`something is not right here`),
},
},

"ValidateFunc not called when type does not match": {
Schema: map[string]*Schema{
"number": &Schema{
Expand Down