2017-10-04 20:27:51 +02:00
|
|
|
package schema
|
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
|
|
|
|
2018-07-05 19:33:29 +02:00
|
|
|
"github.com/hashicorp/terraform/configs/configschema"
|
2017-10-04 20:27:51 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestSchemaMapCoreConfigSchema(t *testing.T) {
|
|
|
|
tests := map[string]struct {
|
|
|
|
Schema map[string]*Schema
|
|
|
|
Want *configschema.Block
|
|
|
|
}{
|
|
|
|
"empty": {
|
|
|
|
map[string]*Schema{},
|
2017-10-14 03:43:08 +02:00
|
|
|
&configschema.Block{},
|
2017-10-04 20:27:51 +02:00
|
|
|
},
|
|
|
|
"primitives": {
|
|
|
|
map[string]*Schema{
|
|
|
|
"int": {
|
2018-03-16 18:43:35 +01:00
|
|
|
Type: TypeInt,
|
|
|
|
Required: true,
|
|
|
|
Description: "foo bar baz",
|
2017-10-04 20:27:51 +02:00
|
|
|
},
|
|
|
|
"float": {
|
|
|
|
Type: TypeFloat,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"bool": {
|
|
|
|
Type: TypeBool,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"string": {
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"int": {
|
2018-03-16 18:43:35 +01:00
|
|
|
Type: cty.Number,
|
|
|
|
Required: true,
|
|
|
|
Description: "foo bar baz",
|
2017-10-04 20:27:51 +02:00
|
|
|
},
|
|
|
|
"float": {
|
|
|
|
Type: cty.Number,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"bool": {
|
|
|
|
Type: cty.Bool,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"string": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
BlockTypes: map[string]*configschema.NestedBlock{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"simple collections": {
|
|
|
|
map[string]*Schema{
|
|
|
|
"list": {
|
|
|
|
Type: TypeList,
|
|
|
|
Required: true,
|
|
|
|
Elem: &Schema{
|
|
|
|
Type: TypeInt,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"set": {
|
|
|
|
Type: TypeSet,
|
|
|
|
Optional: true,
|
|
|
|
Elem: &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"map": {
|
|
|
|
Type: TypeMap,
|
|
|
|
Optional: true,
|
|
|
|
Elem: &Schema{
|
|
|
|
Type: TypeBool,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"map_default_type": {
|
|
|
|
Type: TypeMap,
|
|
|
|
Optional: true,
|
|
|
|
// Maps historically don't have elements because we
|
|
|
|
// assumed they would be strings, so this needs to work
|
|
|
|
// for pre-existing schemas.
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"list": {
|
|
|
|
Type: cty.List(cty.Number),
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
"set": {
|
|
|
|
Type: cty.Set(cty.String),
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"map": {
|
|
|
|
Type: cty.Map(cty.Bool),
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"map_default_type": {
|
|
|
|
Type: cty.Map(cty.String),
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
BlockTypes: map[string]*configschema.NestedBlock{},
|
|
|
|
},
|
|
|
|
},
|
2018-06-02 02:32:01 +02:00
|
|
|
"incorrectly-specified collections": {
|
|
|
|
// Historically we tolerated setting a type directly as the Elem
|
|
|
|
// attribute, rather than a Schema object. This is common enough
|
|
|
|
// in existing provider code that we must support it as an alias
|
|
|
|
// for a schema object with the given type.
|
|
|
|
map[string]*Schema{
|
|
|
|
"list": {
|
|
|
|
Type: TypeList,
|
|
|
|
Required: true,
|
|
|
|
Elem: TypeInt,
|
|
|
|
},
|
|
|
|
"set": {
|
|
|
|
Type: TypeSet,
|
|
|
|
Optional: true,
|
|
|
|
Elem: TypeString,
|
|
|
|
},
|
|
|
|
"map": {
|
|
|
|
Type: TypeMap,
|
|
|
|
Optional: true,
|
|
|
|
Elem: TypeBool,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"list": {
|
|
|
|
Type: cty.List(cty.Number),
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
"set": {
|
|
|
|
Type: cty.Set(cty.String),
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"map": {
|
|
|
|
Type: cty.Map(cty.Bool),
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
BlockTypes: map[string]*configschema.NestedBlock{},
|
|
|
|
},
|
|
|
|
},
|
2017-10-04 20:27:51 +02:00
|
|
|
"sub-resource collections": {
|
|
|
|
map[string]*Schema{
|
|
|
|
"list": {
|
|
|
|
Type: TypeList,
|
|
|
|
Required: true,
|
|
|
|
Elem: &Resource{
|
|
|
|
Schema: map[string]*Schema{},
|
|
|
|
},
|
|
|
|
MinItems: 1,
|
|
|
|
MaxItems: 2,
|
|
|
|
},
|
|
|
|
"set": {
|
|
|
|
Type: TypeSet,
|
|
|
|
Required: true,
|
|
|
|
Elem: &Resource{
|
|
|
|
Schema: map[string]*Schema{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"map": {
|
|
|
|
Type: TypeMap,
|
|
|
|
Optional: true,
|
|
|
|
Elem: &Resource{
|
|
|
|
Schema: map[string]*Schema{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{},
|
|
|
|
BlockTypes: map[string]*configschema.NestedBlock{
|
|
|
|
"list": {
|
|
|
|
Nesting: configschema.NestingList,
|
|
|
|
Block: configschema.Block{},
|
|
|
|
MinItems: 1,
|
|
|
|
MaxItems: 2,
|
|
|
|
},
|
|
|
|
"set": {
|
|
|
|
Nesting: configschema.NestingSet,
|
|
|
|
Block: configschema.Block{},
|
|
|
|
MinItems: 1, // because schema is Required
|
|
|
|
},
|
|
|
|
"map": {
|
|
|
|
Nesting: configschema.NestingMap,
|
|
|
|
Block: configschema.Block{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"nested attributes and blocks": {
|
|
|
|
map[string]*Schema{
|
|
|
|
"foo": {
|
|
|
|
Type: TypeList,
|
|
|
|
Required: true,
|
|
|
|
Elem: &Resource{
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"bar": {
|
|
|
|
Type: TypeList,
|
|
|
|
Required: true,
|
|
|
|
Elem: &Schema{
|
|
|
|
Type: TypeList,
|
|
|
|
Elem: &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"baz": {
|
|
|
|
Type: TypeSet,
|
|
|
|
Optional: true,
|
|
|
|
Elem: &Resource{
|
|
|
|
Schema: map[string]*Schema{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{},
|
|
|
|
BlockTypes: map[string]*configschema.NestedBlock{
|
|
|
|
"foo": &configschema.NestedBlock{
|
|
|
|
Nesting: configschema.NestingList,
|
|
|
|
Block: configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"bar": {
|
|
|
|
Type: cty.List(cty.List(cty.String)),
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
BlockTypes: map[string]*configschema.NestedBlock{
|
|
|
|
"baz": {
|
|
|
|
Nesting: configschema.NestingSet,
|
|
|
|
Block: configschema.Block{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
MinItems: 1, // because schema is Required
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2017-10-04 20:38:04 +02:00
|
|
|
"sensitive": {
|
|
|
|
map[string]*Schema{
|
|
|
|
"string": {
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Sensitive: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&configschema.Block{
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
"string": {
|
|
|
|
Type: cty.String,
|
|
|
|
Optional: true,
|
|
|
|
Sensitive: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
BlockTypes: map[string]*configschema.NestedBlock{},
|
|
|
|
},
|
|
|
|
},
|
2017-10-04 20:27:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for name, test := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
got := schemaMap(test.Schema).CoreConfigSchema()
|
|
|
|
if !reflect.DeepEqual(got, test.Want) {
|
|
|
|
t.Errorf("wrong result\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(test.Want))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|