Merge pull request #5218 from paybyphone/paybyphone_set_maxitems
Add MaxItems attribute to Schema
This commit is contained in:
commit
c1ce8ff31a
|
@ -99,7 +99,13 @@ type Schema struct {
|
|||
// TypeList, and represents what the element type is. If it is *Schema,
|
||||
// the element type is just a simple value. If it is *Resource, the
|
||||
// element type is a complex structure, potentially with its own lifecycle.
|
||||
//
|
||||
// MaxItems defines a maximum amount of items that can exist within a
|
||||
// TypeSet or TypeList. Specific use cases would be if a TypeSet is being
|
||||
// used to wrap a complex structure, however more than one instance would
|
||||
// cause instability.
|
||||
Elem interface{}
|
||||
MaxItems int
|
||||
|
||||
// The following fields are only valid for a TypeSet type.
|
||||
//
|
||||
|
@ -541,6 +547,10 @@ func (m schemaMap) InternalValidate(topSchemaMap schemaMap) error {
|
|||
"%s: Elem must have only Type set", k)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if v.MaxItems > 0 {
|
||||
return fmt.Errorf("%s: MaxItems is only supported on lists or sets", k)
|
||||
}
|
||||
}
|
||||
|
||||
if v.ValidateFunc != nil {
|
||||
|
@ -1049,6 +1059,12 @@ func (m schemaMap) validateList(
|
|||
"%s: should be a list", k)}
|
||||
}
|
||||
|
||||
// Validate length
|
||||
if schema.MaxItems > 0 && rawV.Len() > schema.MaxItems {
|
||||
return nil, []error{fmt.Errorf(
|
||||
"%s: attribute supports %d item maximum, config has %d declared", k, schema.MaxItems, rawV.Len())}
|
||||
}
|
||||
|
||||
// Now build the []interface{}
|
||||
raws := make([]interface{}, rawV.Len())
|
||||
for i, _ := range raws {
|
||||
|
|
|
@ -3647,3 +3647,94 @@ func TestSchemaMap_Validate(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchemaSet_ValidateMaxItems(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
Schema map[string]*Schema
|
||||
State *terraform.InstanceState
|
||||
Config map[string]interface{}
|
||||
ConfigVariables map[string]string
|
||||
Diff *terraform.InstanceDiff
|
||||
Err bool
|
||||
Errors []error
|
||||
}{
|
||||
"#0": {
|
||||
Schema: map[string]*Schema{
|
||||
"aliases": &Schema{
|
||||
Type: TypeSet,
|
||||
Optional: true,
|
||||
MaxItems: 1,
|
||||
Elem: &Schema{Type: TypeString},
|
||||
},
|
||||
},
|
||||
State: nil,
|
||||
Config: map[string]interface{}{
|
||||
"aliases": []interface{}{"foo", "bar"},
|
||||
},
|
||||
Diff: nil,
|
||||
Err: true,
|
||||
Errors: []error{
|
||||
fmt.Errorf("aliases: attribute supports 1 item maximum, config has 2 declared"),
|
||||
},
|
||||
},
|
||||
"#1": {
|
||||
Schema: map[string]*Schema{
|
||||
"aliases": &Schema{
|
||||
Type: TypeSet,
|
||||
Optional: true,
|
||||
Elem: &Schema{Type: TypeString},
|
||||
},
|
||||
},
|
||||
State: nil,
|
||||
Config: map[string]interface{}{
|
||||
"aliases": []interface{}{"foo", "bar"},
|
||||
},
|
||||
Diff: nil,
|
||||
Err: false,
|
||||
Errors: nil,
|
||||
},
|
||||
"#2": {
|
||||
Schema: map[string]*Schema{
|
||||
"aliases": &Schema{
|
||||
Type: TypeSet,
|
||||
Optional: true,
|
||||
MaxItems: 1,
|
||||
Elem: &Schema{Type: TypeString},
|
||||
},
|
||||
},
|
||||
State: nil,
|
||||
Config: map[string]interface{}{
|
||||
"aliases": []interface{}{"foo"},
|
||||
},
|
||||
Diff: nil,
|
||||
Err: false,
|
||||
Errors: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for tn, tc := range cases {
|
||||
c, err := config.NewRawConfig(tc.Config)
|
||||
if err != nil {
|
||||
t.Fatalf("%q: err: %s", tn, err)
|
||||
}
|
||||
_, es := schemaMap(tc.Schema).Validate(terraform.NewResourceConfig(c))
|
||||
|
||||
if len(es) > 0 != tc.Err {
|
||||
if len(es) == 0 {
|
||||
t.Errorf("%q: no errors", tn)
|
||||
}
|
||||
|
||||
for _, e := range es {
|
||||
t.Errorf("%q: err: %s", tn, e)
|
||||
}
|
||||
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if tc.Errors != nil {
|
||||
if !reflect.DeepEqual(es, tc.Errors) {
|
||||
t.Fatalf("%q: expected: %q\ngot: %q", tn, tc.Errors, es)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue