Revert "helper/schema: Make nested Set(s) in List(s) work" (#7436)
This commit is contained in:
parent
079e1f9a56
commit
a84aa5e914
|
@ -130,6 +130,60 @@ func addrToSchema(addr []string, schemaMap map[string]*Schema) []*Schema {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readListField is a generic method for reading a list field out of a
|
||||||
|
// a FieldReader. It does this based on the assumption that there is a key
|
||||||
|
// "foo.#" for a list "foo" and that the indexes are "foo.0", "foo.1", etc.
|
||||||
|
// after that point.
|
||||||
|
func readListField(
|
||||||
|
r FieldReader, addr []string, schema *Schema) (FieldReadResult, error) {
|
||||||
|
addrPadded := make([]string, len(addr)+1)
|
||||||
|
copy(addrPadded, addr)
|
||||||
|
addrPadded[len(addrPadded)-1] = "#"
|
||||||
|
|
||||||
|
// Get the number of elements in the list
|
||||||
|
countResult, err := r.ReadField(addrPadded)
|
||||||
|
if err != nil {
|
||||||
|
return FieldReadResult{}, err
|
||||||
|
}
|
||||||
|
if !countResult.Exists {
|
||||||
|
// No count, means we have no list
|
||||||
|
countResult.Value = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have an empty list, then return an empty list
|
||||||
|
if countResult.Computed || countResult.Value.(int) == 0 {
|
||||||
|
return FieldReadResult{
|
||||||
|
Value: []interface{}{},
|
||||||
|
Exists: countResult.Exists,
|
||||||
|
Computed: countResult.Computed,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through each count, and get the item value out of it
|
||||||
|
result := make([]interface{}, countResult.Value.(int))
|
||||||
|
for i, _ := range result {
|
||||||
|
is := strconv.FormatInt(int64(i), 10)
|
||||||
|
addrPadded[len(addrPadded)-1] = is
|
||||||
|
rawResult, err := r.ReadField(addrPadded)
|
||||||
|
if err != nil {
|
||||||
|
return FieldReadResult{}, err
|
||||||
|
}
|
||||||
|
if !rawResult.Exists {
|
||||||
|
// This should never happen, because by the time the data
|
||||||
|
// gets to the FieldReaders, all the defaults should be set by
|
||||||
|
// Schema.
|
||||||
|
rawResult.Value = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result[i] = rawResult.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
return FieldReadResult{
|
||||||
|
Value: result,
|
||||||
|
Exists: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// readObjectField is a generic method for reading objects out of FieldReaders
|
// readObjectField is a generic method for reading objects out of FieldReaders
|
||||||
// based on the assumption that building an address of []string{k, FIELD}
|
// based on the assumption that building an address of []string{k, FIELD}
|
||||||
// will result in the proper field data.
|
// will result in the proper field data.
|
||||||
|
|
|
@ -83,7 +83,7 @@ func (r *ConfigFieldReader) readField(
|
||||||
case TypeBool, TypeFloat, TypeInt, TypeString:
|
case TypeBool, TypeFloat, TypeInt, TypeString:
|
||||||
return r.readPrimitive(k, schema)
|
return r.readPrimitive(k, schema)
|
||||||
case TypeList:
|
case TypeList:
|
||||||
return r.readList(address, schema)
|
return readListField(&nestedConfigFieldReader{r}, address, schema)
|
||||||
case TypeMap:
|
case TypeMap:
|
||||||
return r.readMap(k)
|
return r.readMap(k)
|
||||||
case TypeSet:
|
case TypeSet:
|
||||||
|
@ -216,65 +216,13 @@ func (r *ConfigFieldReader) readPrimitive(
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ConfigFieldReader) readList(
|
|
||||||
address []string, schema *Schema) (FieldReadResult, error) {
|
|
||||||
|
|
||||||
addrPadded := make([]string, len(address)+1)
|
|
||||||
copy(addrPadded, address)
|
|
||||||
|
|
||||||
// Get the number of elements in the list
|
|
||||||
addrPadded[len(addrPadded)-1] = "#"
|
|
||||||
countResult, err := r.readPrimitive(
|
|
||||||
strings.Join(addrPadded, "."), &Schema{Type: TypeInt})
|
|
||||||
if err != nil {
|
|
||||||
return FieldReadResult{}, err
|
|
||||||
}
|
|
||||||
if !countResult.Exists {
|
|
||||||
// No count, means we have no list
|
|
||||||
countResult.Value = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have an empty list, then return an empty list
|
|
||||||
if countResult.Computed || countResult.Value.(int) == 0 {
|
|
||||||
return FieldReadResult{
|
|
||||||
Value: []interface{}{},
|
|
||||||
Exists: countResult.Exists,
|
|
||||||
Computed: countResult.Computed,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through each count, and get the item value out of it
|
|
||||||
result := make([]interface{}, countResult.Value.(int))
|
|
||||||
for i, _ := range result {
|
|
||||||
idx := strconv.Itoa(i)
|
|
||||||
addrPadded[len(addrPadded)-1] = idx
|
|
||||||
rawResult, err := r.readField(addrPadded, true)
|
|
||||||
if err != nil {
|
|
||||||
return FieldReadResult{}, err
|
|
||||||
}
|
|
||||||
if !rawResult.Exists {
|
|
||||||
// This should never happen, because by the time the data
|
|
||||||
// gets to the FieldReaders, all the defaults should be set by
|
|
||||||
// Schema.
|
|
||||||
panic("missing field in list: " + strings.Join(addrPadded, "."))
|
|
||||||
}
|
|
||||||
|
|
||||||
result[i] = rawResult.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
return FieldReadResult{
|
|
||||||
Value: result,
|
|
||||||
Exists: true,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ConfigFieldReader) readSet(
|
func (r *ConfigFieldReader) readSet(
|
||||||
address []string, schema *Schema) (FieldReadResult, error) {
|
address []string, schema *Schema) (FieldReadResult, error) {
|
||||||
indexMap := make(map[string]int)
|
indexMap := make(map[string]int)
|
||||||
// Create the set that will be our result
|
// Create the set that will be our result
|
||||||
set := schema.ZeroValue().(*Set)
|
set := schema.ZeroValue().(*Set)
|
||||||
|
|
||||||
raw, err := r.readList(address, schema)
|
raw, err := readListField(&nestedConfigFieldReader{r}, address, schema)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return FieldReadResult{}, err
|
return FieldReadResult{}, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ package schema
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
@ -14,8 +12,8 @@ import (
|
||||||
//
|
//
|
||||||
// It also requires access to a Reader that reads fields from the structure
|
// It also requires access to a Reader that reads fields from the structure
|
||||||
// that the diff was derived from. This is usually the state. This is required
|
// that the diff was derived from. This is usually the state. This is required
|
||||||
// because a diff on its own doesn't have complete data about non-primitive
|
// because a diff on its own doesn't have complete data about full objects
|
||||||
// objects such as maps, lists and sets.
|
// such as maps.
|
||||||
//
|
//
|
||||||
// The Source MUST be the data that the diff was derived from. If it isn't,
|
// The Source MUST be the data that the diff was derived from. If it isn't,
|
||||||
// the behavior of this struct is undefined.
|
// the behavior of this struct is undefined.
|
||||||
|
@ -44,7 +42,7 @@ func (r *DiffFieldReader) ReadField(address []string) (FieldReadResult, error) {
|
||||||
case TypeBool, TypeInt, TypeFloat, TypeString:
|
case TypeBool, TypeInt, TypeFloat, TypeString:
|
||||||
return r.readPrimitive(address, schema)
|
return r.readPrimitive(address, schema)
|
||||||
case TypeList:
|
case TypeList:
|
||||||
return r.readList(address, schema)
|
return readListField(r, address, schema)
|
||||||
case TypeMap:
|
case TypeMap:
|
||||||
return r.readMap(address, schema)
|
return r.readMap(address, schema)
|
||||||
case TypeSet:
|
case TypeSet:
|
||||||
|
@ -59,7 +57,7 @@ func (r *DiffFieldReader) ReadField(address []string) (FieldReadResult, error) {
|
||||||
func (r *DiffFieldReader) readMap(
|
func (r *DiffFieldReader) readMap(
|
||||||
address []string, schema *Schema) (FieldReadResult, error) {
|
address []string, schema *Schema) (FieldReadResult, error) {
|
||||||
result := make(map[string]interface{})
|
result := make(map[string]interface{})
|
||||||
exists := false
|
resultSet := false
|
||||||
|
|
||||||
// First read the map from the underlying source
|
// First read the map from the underlying source
|
||||||
source, err := r.Source.ReadField(address)
|
source, err := r.Source.ReadField(address)
|
||||||
|
@ -68,7 +66,7 @@ func (r *DiffFieldReader) readMap(
|
||||||
}
|
}
|
||||||
if source.Exists {
|
if source.Exists {
|
||||||
result = source.Value.(map[string]interface{})
|
result = source.Value.(map[string]interface{})
|
||||||
exists = true
|
resultSet = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next, read all the elements we have in our diff, and apply
|
// Next, read all the elements we have in our diff, and apply
|
||||||
|
@ -83,7 +81,7 @@ func (r *DiffFieldReader) readMap(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
exists = true
|
resultSet = true
|
||||||
|
|
||||||
k = k[len(prefix):]
|
k = k[len(prefix):]
|
||||||
if v.NewRemoved {
|
if v.NewRemoved {
|
||||||
|
@ -95,13 +93,13 @@ func (r *DiffFieldReader) readMap(
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultVal interface{}
|
var resultVal interface{}
|
||||||
if exists {
|
if resultSet {
|
||||||
resultVal = result
|
resultVal = result
|
||||||
}
|
}
|
||||||
|
|
||||||
return FieldReadResult{
|
return FieldReadResult{
|
||||||
Value: resultVal,
|
Value: resultVal,
|
||||||
Exists: exists,
|
Exists: resultSet,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,99 +136,6 @@ func (r *DiffFieldReader) readPrimitive(
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DiffFieldReader) readList(
|
|
||||||
address []string, schema *Schema) (FieldReadResult, error) {
|
|
||||||
prefix := strings.Join(address, ".") + "."
|
|
||||||
|
|
||||||
addrPadded := make([]string, len(address)+1)
|
|
||||||
copy(addrPadded, address)
|
|
||||||
|
|
||||||
// Get the number of elements in the list
|
|
||||||
addrPadded[len(addrPadded)-1] = "#"
|
|
||||||
countResult, err := r.readPrimitive(addrPadded, &Schema{Type: TypeInt})
|
|
||||||
if err != nil {
|
|
||||||
return FieldReadResult{}, err
|
|
||||||
}
|
|
||||||
if !countResult.Exists {
|
|
||||||
// No count, means we have no list
|
|
||||||
countResult.Value = 0
|
|
||||||
}
|
|
||||||
// If we have an empty list, then return an empty list
|
|
||||||
if countResult.Computed || countResult.Value.(int) == 0 {
|
|
||||||
return FieldReadResult{
|
|
||||||
Value: []interface{}{},
|
|
||||||
Exists: countResult.Exists,
|
|
||||||
Computed: countResult.Computed,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bail out if diff doesn't contain the given field at all
|
|
||||||
// This has to be a separate loop because we're only
|
|
||||||
// iterating over raw list items (list.idx).
|
|
||||||
// Other fields (list.idx.*) are left for other read* methods
|
|
||||||
// which can deal with these fields appropriately.
|
|
||||||
diffContainsField := false
|
|
||||||
for k, _ := range r.Diff.Attributes {
|
|
||||||
if strings.HasPrefix(k, address[0]+".") {
|
|
||||||
diffContainsField = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !diffContainsField {
|
|
||||||
return FieldReadResult{
|
|
||||||
Value: []interface{}{},
|
|
||||||
Exists: false,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the list that will be our result
|
|
||||||
list := []interface{}{}
|
|
||||||
|
|
||||||
// Go through the diff and find all the list items
|
|
||||||
// We are not iterating over the diff directly as some indexes
|
|
||||||
// may be missing and we expect the whole list to be returned.
|
|
||||||
for i := 0; i < countResult.Value.(int); i++ {
|
|
||||||
idx := strconv.Itoa(i)
|
|
||||||
addrString := prefix + idx
|
|
||||||
|
|
||||||
d, ok := r.Diff.Attributes[addrString]
|
|
||||||
if ok && d.NewRemoved {
|
|
||||||
// If the field is being removed, we ignore it
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
addrPadded[len(addrPadded)-1] = idx
|
|
||||||
raw, err := r.ReadField(addrPadded)
|
|
||||||
if err != nil {
|
|
||||||
return FieldReadResult{}, err
|
|
||||||
}
|
|
||||||
if !raw.Exists {
|
|
||||||
// This should never happen, because by the time the data
|
|
||||||
// gets to the FieldReaders, all the defaults should be set by
|
|
||||||
// Schema.
|
|
||||||
panic("missing field in set: " + addrString + "." + idx)
|
|
||||||
}
|
|
||||||
list = append(list, raw.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine if the list "exists". It exists if there are items or if
|
|
||||||
// the diff explicitly wanted it empty.
|
|
||||||
exists := len(list) > 0
|
|
||||||
if !exists {
|
|
||||||
// We could check if the diff value is "0" here but I think the
|
|
||||||
// existence of "#" on its own is enough to show it existed. This
|
|
||||||
// protects us in the future from the zero value changing from
|
|
||||||
// "0" to "" breaking us (if that were to happen).
|
|
||||||
if _, ok := r.Diff.Attributes[prefix+"#"]; ok {
|
|
||||||
exists = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FieldReadResult{
|
|
||||||
Value: list,
|
|
||||||
Exists: exists,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *DiffFieldReader) readSet(
|
func (r *DiffFieldReader) readSet(
|
||||||
address []string, schema *Schema) (FieldReadResult, error) {
|
address []string, schema *Schema) (FieldReadResult, error) {
|
||||||
prefix := strings.Join(address, ".") + "."
|
prefix := strings.Join(address, ".") + "."
|
||||||
|
@ -238,60 +143,10 @@ func (r *DiffFieldReader) readSet(
|
||||||
// Create the set that will be our result
|
// Create the set that will be our result
|
||||||
set := schema.ZeroValue().(*Set)
|
set := schema.ZeroValue().(*Set)
|
||||||
|
|
||||||
// Check if we're supposed to remove it
|
|
||||||
v, ok := r.Diff.Attributes[prefix+"#"]
|
|
||||||
if ok && v.New == "0" {
|
|
||||||
// I'm not entirely sure what's the point of
|
|
||||||
// returning empty set w/ Exists: true
|
|
||||||
return FieldReadResult{
|
|
||||||
Value: set,
|
|
||||||
Exists: true,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compose list of all keys (diff + source)
|
|
||||||
var keys []string
|
|
||||||
|
|
||||||
// Add keys from diff
|
|
||||||
diffContainsField := false
|
|
||||||
for k, _ := range r.Diff.Attributes {
|
|
||||||
if strings.HasPrefix(k, address[0]+".") {
|
|
||||||
diffContainsField = true
|
|
||||||
}
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
// Bail out if diff doesn't contain the given field at all
|
|
||||||
if !diffContainsField {
|
|
||||||
return FieldReadResult{
|
|
||||||
Value: set,
|
|
||||||
Exists: false,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
// Add keys from source
|
|
||||||
sourceResult, err := r.Source.ReadField(address)
|
|
||||||
if err == nil && sourceResult.Exists {
|
|
||||||
sourceSet := sourceResult.Value.(*Set)
|
|
||||||
sourceMap := sourceSet.Map()
|
|
||||||
|
|
||||||
for k, _ := range sourceMap {
|
|
||||||
key := prefix + k
|
|
||||||
_, ok := r.Diff.Attributes[key]
|
|
||||||
if !ok {
|
|
||||||
keys = append(keys, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep the order consistent for hashing functions
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
// Go through the map and find all the set items
|
// Go through the map and find all the set items
|
||||||
// We are not iterating over the diff directly as some indexes
|
for k, d := range r.Diff.Attributes {
|
||||||
// may be missing and we expect the whole set to be returned.
|
if d.NewRemoved {
|
||||||
for _, k := range keys {
|
// If the field is removed, we always ignore it
|
||||||
d, ok := r.Diff.Attributes[k]
|
|
||||||
if ok && d.NewRemoved {
|
|
||||||
// If the field is being removed, we ignore it
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !strings.HasPrefix(k, prefix) {
|
if !strings.HasPrefix(k, prefix) {
|
||||||
|
|
|
@ -245,7 +245,7 @@ func TestDiffFieldReader_extra(t *testing.T) {
|
||||||
out.Value = s.List()
|
out.Value = s.List()
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(tc.Result, out) {
|
if !reflect.DeepEqual(tc.Result, out) {
|
||||||
t.Fatalf("Case %q:\ngiven: %#v\nexpected: %#v", name, out, tc.Result)
|
t.Fatalf("%s: bad: %#v", name, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,616 +376,3 @@ func TestDiffFieldReader(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDiffFieldReader_SetInSet(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
"inner_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var readers = make(map[string]FieldReader)
|
|
||||||
readers["state"] = &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_set.#": "1",
|
|
||||||
"main_set.2476980464.inner_string_set.#": "2",
|
|
||||||
"main_set.2476980464.inner_string_set.2654390964": "blue",
|
|
||||||
"main_set.2476980464.inner_string_set.3499814433": "green",
|
|
||||||
"main_set.2476980464.inner_int": "4",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're only changing main_int
|
|
||||||
dfr := &DiffFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Diff: &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "9",
|
|
||||||
New: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Source: &MultiLevelFieldReader{
|
|
||||||
Levels: []string{"state", "config"},
|
|
||||||
Readers: readers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// main_list should NOT be in the diff at all
|
|
||||||
result, err := dfr.ReadField([]string{"main_set"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadField failed: %s", err)
|
|
||||||
}
|
|
||||||
expectedResult := NewSet(HashString, []interface{}{})
|
|
||||||
if !expectedResult.Equal(result.Value) {
|
|
||||||
t.Fatalf("ReadField returned unexpected result.\nGiven: %#v\nexpected: %#v",
|
|
||||||
result, expectedResult)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDiffFieldReader_SetInList(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
"inner_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var readers = make(map[string]FieldReader)
|
|
||||||
readers["state"] = &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_list.#": "1",
|
|
||||||
"main_list.0.inner_string_set.#": "2",
|
|
||||||
"main_list.0.inner_string_set.2654390964": "blue",
|
|
||||||
"main_list.0.inner_string_set.3499814433": "green",
|
|
||||||
"main_list.0.inner_int": "4",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're only changing main_int
|
|
||||||
dfr := &DiffFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Diff: &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "9",
|
|
||||||
New: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Source: &MultiLevelFieldReader{
|
|
||||||
Levels: []string{"state", "config"},
|
|
||||||
Readers: readers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// main_list should NOT be in the diff at all
|
|
||||||
result, err := dfr.ReadField([]string{"main_list"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadField failed: %s", err)
|
|
||||||
}
|
|
||||||
expectedResult := FieldReadResult{
|
|
||||||
Value: []interface{}{},
|
|
||||||
ValueProcessed: nil,
|
|
||||||
Exists: false,
|
|
||||||
Computed: false,
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(result, expectedResult) {
|
|
||||||
t.Fatalf("ReadField returned unexpected result.\nGiven: %#v\nexpected: %#v",
|
|
||||||
result, expectedResult)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDiffFieldReader_SetInList_singleInstance(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
MaxItems: 1,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
"inner_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var readers = make(map[string]FieldReader)
|
|
||||||
readers["state"] = &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_list.#": "1",
|
|
||||||
"main_list.0.inner_string_set.#": "2",
|
|
||||||
"main_list.0.inner_string_set.2654390964": "blue",
|
|
||||||
"main_list.0.inner_string_set.3499814433": "green",
|
|
||||||
"main_list.0.inner_int": "4",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. NEGATIVE (diff doesn't contain list)
|
|
||||||
// If we're only changing main_int
|
|
||||||
dfrNegative := &DiffFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Diff: &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "9",
|
|
||||||
New: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Source: &MultiLevelFieldReader{
|
|
||||||
Levels: []string{"state", "config"},
|
|
||||||
Readers: readers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// main_list should NOT be in the diff at all
|
|
||||||
resultNegative, err := dfrNegative.ReadField([]string{"main_list"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadField failed: %s", err)
|
|
||||||
}
|
|
||||||
expectedNegativeResult := FieldReadResult{
|
|
||||||
Value: []interface{}{},
|
|
||||||
ValueProcessed: nil,
|
|
||||||
Exists: false,
|
|
||||||
Computed: false,
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(resultNegative, expectedNegativeResult) {
|
|
||||||
t.Fatalf("ReadField returned unexpected resultNegative.\nGiven: %#v\nexpected: %#v",
|
|
||||||
resultNegative, expectedNegativeResult)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. POSITIVE (diff contains list)
|
|
||||||
dfrPositive := &DiffFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Diff: &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_list.0.inner_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "4",
|
|
||||||
New: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Source: &MultiLevelFieldReader{
|
|
||||||
Levels: []string{"state", "config"},
|
|
||||||
Readers: readers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
resultPositive, err := dfrPositive.ReadField([]string{"main_list"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadField failed: %s", err)
|
|
||||||
}
|
|
||||||
if !resultPositive.Exists {
|
|
||||||
t.Fatal("Expected resultPositive to exist")
|
|
||||||
}
|
|
||||||
list := resultPositive.Value.([]interface{})
|
|
||||||
if len(list) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 list instance, %d given", len(list))
|
|
||||||
}
|
|
||||||
|
|
||||||
m := list[0].(map[string]interface{})
|
|
||||||
|
|
||||||
m_expectedInnerInt := 2
|
|
||||||
m_innerInt, ok := m["inner_int"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected inner_int key to exist in map")
|
|
||||||
}
|
|
||||||
if m_innerInt != m_expectedInnerInt {
|
|
||||||
t.Fatalf("Expected inner_int (%d) doesn't match w/ given: %d", m_expectedInnerInt, m_innerInt)
|
|
||||||
}
|
|
||||||
|
|
||||||
m_expectedStringSet := NewSet(HashString, []interface{}{"blue", "green"})
|
|
||||||
m_StringSet, ok := m["inner_string_set"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected inner_string_set key to exist in map")
|
|
||||||
}
|
|
||||||
if !m_expectedStringSet.Equal(m_StringSet) {
|
|
||||||
t.Fatalf("Expected inner_string_set (%q) doesn't match w/ given: %q",
|
|
||||||
m_expectedStringSet.List(), m_StringSet.(*Set).List())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDiffFieldReader_SetInList_multipleInstances(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
"inner_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var readers = make(map[string]FieldReader)
|
|
||||||
readers["state"] = &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_list.#": "3",
|
|
||||||
"main_list.0.inner_string_set.#": "2",
|
|
||||||
"main_list.0.inner_string_set.2654390964": "blue",
|
|
||||||
"main_list.0.inner_string_set.3499814433": "green",
|
|
||||||
"main_list.0.inner_int": "4",
|
|
||||||
"main_list.1.inner_string_set.#": "2",
|
|
||||||
"main_list.1.inner_string_set.1830392916": "brown",
|
|
||||||
"main_list.1.inner_string_set.4200685455": "red",
|
|
||||||
"main_list.1.inner_int": "4",
|
|
||||||
"main_list.2.inner_string_set.#": "3",
|
|
||||||
"main_list.2.inner_string_set.2053932785": "one",
|
|
||||||
"main_list.2.inner_string_set.298486374": "two",
|
|
||||||
"main_list.2.inner_string_set.1187371253": "three",
|
|
||||||
"main_list.2.inner_int": "914",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
dfr := &DiffFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Diff: &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_list.0.inner_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "4",
|
|
||||||
New: "5",
|
|
||||||
},
|
|
||||||
"main_list.1.inner_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "4",
|
|
||||||
New: "34",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Source: &MultiLevelFieldReader{
|
|
||||||
Levels: []string{"state", "config"},
|
|
||||||
Readers: readers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := dfr.ReadField([]string{"main_list"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadField 2 failed: %s", err)
|
|
||||||
}
|
|
||||||
if !result.Exists {
|
|
||||||
t.Fatal("Expected result to exist")
|
|
||||||
}
|
|
||||||
list := result.Value.([]interface{})
|
|
||||||
if len(list) != 3 {
|
|
||||||
t.Fatalf("Expected exactly 3 list instances, %d given", len(list))
|
|
||||||
}
|
|
||||||
|
|
||||||
// First
|
|
||||||
m1 := list[0].(map[string]interface{})
|
|
||||||
|
|
||||||
m1_expectedInnerInt := 5
|
|
||||||
m1_innerInt, ok := m1["inner_int"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected 1st inner_int key to exist in map")
|
|
||||||
}
|
|
||||||
if m1_innerInt != m1_expectedInnerInt {
|
|
||||||
t.Fatalf("Expected 1st inner_int (%d) doesn't match w/ given: %d", m1_expectedInnerInt, m1_innerInt)
|
|
||||||
}
|
|
||||||
|
|
||||||
m1_expectedStringSet := NewSet(HashString, []interface{}{"blue", "green"})
|
|
||||||
m1_StringSet, ok := m1["inner_string_set"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected 1st inner_string_set key to exist in map")
|
|
||||||
}
|
|
||||||
if !m1_expectedStringSet.Equal(m1_StringSet) {
|
|
||||||
t.Fatalf("Expected 1st inner_string_set (%q) doesn't match w/ given: %q",
|
|
||||||
m1_expectedStringSet.List(), m1_StringSet.(*Set).List())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second
|
|
||||||
m2 := list[1].(map[string]interface{})
|
|
||||||
|
|
||||||
m2_expectedInnerInt := 34
|
|
||||||
m2_innerInt, ok := m2["inner_int"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected 2nd inner_int key to exist in map")
|
|
||||||
}
|
|
||||||
if m2_innerInt != m2_expectedInnerInt {
|
|
||||||
t.Fatalf("Expected 2nd inner_int (%d) doesn't match w/ given: %d", m2_expectedInnerInt, m2_innerInt)
|
|
||||||
}
|
|
||||||
|
|
||||||
m2_expectedStringSet := NewSet(HashString, []interface{}{"brown", "red"})
|
|
||||||
m2_StringSet, ok := m2["inner_string_set"].(*Set)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected 2nd inner_string_set key to exist in map")
|
|
||||||
}
|
|
||||||
if !m2_expectedStringSet.Equal(m2_StringSet) {
|
|
||||||
t.Fatalf("Expected 2nd inner_string_set (%q) doesn't match w/ given: %q",
|
|
||||||
m2_expectedStringSet.List(), m2_StringSet.List())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Third
|
|
||||||
m3 := list[2].(map[string]interface{})
|
|
||||||
|
|
||||||
m3_expectedInnerInt := 914
|
|
||||||
m3_innerInt, ok := m3["inner_int"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected 3rd inner_int key to exist in map")
|
|
||||||
}
|
|
||||||
if m3_innerInt != m3_expectedInnerInt {
|
|
||||||
t.Fatalf("Expected 3rd inner_int (%d) doesn't match w/ given: %d", m3_expectedInnerInt, m3_innerInt)
|
|
||||||
}
|
|
||||||
|
|
||||||
m3_expectedStringSet := NewSet(HashString, []interface{}{"one", "two", "three"})
|
|
||||||
m3_StringSet, ok := m3["inner_string_set"].(*Set)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected 3rd inner_string_set key to exist in map")
|
|
||||||
}
|
|
||||||
if !m3_expectedStringSet.Equal(m3_StringSet) {
|
|
||||||
t.Fatalf("Expected 3rd inner_string_set (%q) doesn't match w/ given: %q",
|
|
||||||
m3_expectedStringSet.List(), m3_StringSet.List())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDiffFieldReader_SetInList_deeplyNested_singleInstance(t *testing.T) {
|
|
||||||
inInnerSetResource := &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"in_in_inner_string": &Schema{
|
|
||||||
Type: TypeString,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
"in_in_inner_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
innerSetResource := &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"in_inner_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
MaxItems: 1,
|
|
||||||
Elem: inInnerSetResource,
|
|
||||||
},
|
|
||||||
"in_inner_string_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
"in_inner_bool": &Schema{
|
|
||||||
Type: TypeBool,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
"inner_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
MaxItems: 1,
|
|
||||||
Elem: innerSetResource,
|
|
||||||
},
|
|
||||||
"inner_bool": &Schema{
|
|
||||||
Type: TypeBool,
|
|
||||||
Optional: true,
|
|
||||||
Default: false,
|
|
||||||
},
|
|
||||||
"inner_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var readers = make(map[string]FieldReader)
|
|
||||||
readers["state"] = &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "5",
|
|
||||||
"main_list.#": "1",
|
|
||||||
"main_list.0.inner_bool": "true",
|
|
||||||
"main_list.0.inner_int": "2",
|
|
||||||
"main_list.0.inner_set.#": "1",
|
|
||||||
"main_list.0.inner_set.2496801729.in_inner_bool": "false",
|
|
||||||
"main_list.0.inner_set.2496801729.in_inner_set.#": "1",
|
|
||||||
"main_list.0.inner_set.2496801729.in_inner_set.1989773763.in_in_inner_list.#": "1",
|
|
||||||
"main_list.0.inner_set.2496801729.in_inner_set.1989773763.in_in_inner_list.0": "alpha",
|
|
||||||
"main_list.0.inner_set.2496801729.in_inner_set.1989773763.in_in_inner_string": "delta",
|
|
||||||
"main_list.0.inner_set.2496801729.in_inner_string_list.#": "3",
|
|
||||||
"main_list.0.inner_set.2496801729.in_inner_string_list.0": "one",
|
|
||||||
"main_list.0.inner_set.2496801729.in_inner_string_list.1": "two",
|
|
||||||
"main_list.0.inner_set.2496801729.in_inner_string_list.2": "three",
|
|
||||||
"main_list.0.inner_string_set.#": "2",
|
|
||||||
"main_list.0.inner_string_set.1830392916": "brown",
|
|
||||||
"main_list.0.inner_string_set.4200685455": "red",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're only changing main_int
|
|
||||||
dfr := &DiffFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Diff: &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_list.0.inner_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "2",
|
|
||||||
New: "78",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Source: &MultiLevelFieldReader{
|
|
||||||
Levels: []string{"state", "config"},
|
|
||||||
Readers: readers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// main_list should NOT be in the diff at all
|
|
||||||
result, err := dfr.ReadField([]string{"main_list"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadField failed: %s", err)
|
|
||||||
}
|
|
||||||
if !result.Exists {
|
|
||||||
t.Fatal("Expected result to exist")
|
|
||||||
}
|
|
||||||
list := result.Value.([]interface{})
|
|
||||||
if len(list) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 list instance, %d given", len(list))
|
|
||||||
}
|
|
||||||
|
|
||||||
// One day we may have a custom comparison function for nested sets
|
|
||||||
// Until that day comes it will look as ridiculous as below
|
|
||||||
m1 := list[0].(map[string]interface{})
|
|
||||||
|
|
||||||
m1_expectedInnerInt := 78
|
|
||||||
m1_innerInt, ok := m1["inner_int"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected inner_int key to exist in map")
|
|
||||||
}
|
|
||||||
if m1_innerInt != m1_expectedInnerInt {
|
|
||||||
t.Fatalf("Expected inner_int (%d) doesn't match w/ given: %d", m1_expectedInnerInt, m1_innerInt)
|
|
||||||
}
|
|
||||||
|
|
||||||
m1_expectedInnerBool := true
|
|
||||||
m1_innerBool, ok := m1["inner_bool"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected inner_bool key to exist in map")
|
|
||||||
}
|
|
||||||
if m1_innerBool != m1_expectedInnerBool {
|
|
||||||
t.Fatalf("Expected inner_bool (%t) doesn't match w/ given: %t", m1_expectedInnerBool, m1_innerBool)
|
|
||||||
}
|
|
||||||
|
|
||||||
m1_expectedStringSet := NewSet(HashString, []interface{}{"brown", "red"})
|
|
||||||
m1_StringSet, ok := m1["inner_string_set"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected inner_string_set key to exist in map")
|
|
||||||
}
|
|
||||||
if !m1_expectedStringSet.Equal(m1_StringSet) {
|
|
||||||
t.Fatalf("Expected inner_string_set (%q) doesn't match w/ given: %q",
|
|
||||||
m1_expectedStringSet.List(), m1_StringSet.(*Set).List())
|
|
||||||
}
|
|
||||||
|
|
||||||
m1_InnerSet, ok := m1["inner_set"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected inner_set key to exist in map")
|
|
||||||
}
|
|
||||||
m1_InnerSet_list := m1_InnerSet.(*Set).List()
|
|
||||||
m := m1_InnerSet_list[0].(map[string]interface{})
|
|
||||||
|
|
||||||
expectedInInnerBool := false
|
|
||||||
inInnerBool, ok := m["in_inner_bool"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected in_inner_bool key to exist in map")
|
|
||||||
}
|
|
||||||
if inInnerBool != expectedInInnerBool {
|
|
||||||
t.Fatalf("Expected inner_set[0].in_inner_bool (%#v) doesn't match w/ given: %#v",
|
|
||||||
expectedInInnerBool, inInnerBool)
|
|
||||||
}
|
|
||||||
expectedInInnerStringList := []interface{}{"one", "two", "three"}
|
|
||||||
inInnerStringList, ok := m["in_inner_string_list"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected in_inner_string_list key to exist in map")
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(inInnerStringList, expectedInInnerStringList) {
|
|
||||||
t.Fatalf("Expected inner_set[0].in_inner_string_list (%#v) doesn't match w/ given: %#v",
|
|
||||||
expectedInInnerStringList, inInnerStringList)
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedInInnerSet := map[string]interface{}{
|
|
||||||
"in_in_inner_string": "delta",
|
|
||||||
"in_in_inner_list": []interface{}{"alpha"},
|
|
||||||
}
|
|
||||||
inInnerSet, ok := m["in_inner_set"]
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected in_inner_set key to exist in map")
|
|
||||||
}
|
|
||||||
inInnerSet_list := inInnerSet.(*Set).List()
|
|
||||||
m2 := inInnerSet_list[0].(map[string]interface{})
|
|
||||||
if !reflect.DeepEqual(expectedInInnerSet, m2) {
|
|
||||||
t.Fatalf("Expected in_inner_set to match:\nGiven: %#v\nExpected: %#v\n",
|
|
||||||
m2, expectedInInnerSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package schema
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,7 +24,7 @@ func (r *MapFieldReader) ReadField(address []string) (FieldReadResult, error) {
|
||||||
case TypeBool, TypeInt, TypeFloat, TypeString:
|
case TypeBool, TypeInt, TypeFloat, TypeString:
|
||||||
return r.readPrimitive(address, schema)
|
return r.readPrimitive(address, schema)
|
||||||
case TypeList:
|
case TypeList:
|
||||||
return r.readList(address, schema)
|
return readListField(r, address, schema)
|
||||||
case TypeMap:
|
case TypeMap:
|
||||||
return r.readMap(k)
|
return r.readMap(k)
|
||||||
case TypeSet:
|
case TypeSet:
|
||||||
|
@ -92,57 +91,6 @@ func (r *MapFieldReader) readPrimitive(
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *MapFieldReader) readList(
|
|
||||||
address []string, schema *Schema) (FieldReadResult, error) {
|
|
||||||
|
|
||||||
addrPadded := make([]string, len(address)+1)
|
|
||||||
copy(addrPadded, address)
|
|
||||||
|
|
||||||
// Get the number of elements in the list
|
|
||||||
addrPadded[len(addrPadded)-1] = "#"
|
|
||||||
countResult, err := r.readPrimitive(addrPadded, &Schema{Type: TypeInt})
|
|
||||||
if err != nil {
|
|
||||||
return FieldReadResult{}, err
|
|
||||||
}
|
|
||||||
if !countResult.Exists {
|
|
||||||
// No count, means we have no list
|
|
||||||
countResult.Value = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have an empty list, then return an empty list
|
|
||||||
if countResult.Computed || countResult.Value.(int) == 0 {
|
|
||||||
return FieldReadResult{
|
|
||||||
Value: []interface{}{},
|
|
||||||
Exists: countResult.Exists,
|
|
||||||
Computed: countResult.Computed,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through each count, and get the item value out of it
|
|
||||||
result := make([]interface{}, countResult.Value.(int))
|
|
||||||
for i, _ := range result {
|
|
||||||
idx := strconv.Itoa(i)
|
|
||||||
addrPadded[len(addrPadded)-1] = idx
|
|
||||||
rawResult, err := r.ReadField(addrPadded)
|
|
||||||
if err != nil {
|
|
||||||
return FieldReadResult{}, err
|
|
||||||
}
|
|
||||||
if !rawResult.Exists {
|
|
||||||
// This should never happen, because by the time the data
|
|
||||||
// gets to the FieldReaders, all the defaults should be set by
|
|
||||||
// Schema.
|
|
||||||
panic("missing field in list: " + strings.Join(addrPadded, "."))
|
|
||||||
}
|
|
||||||
|
|
||||||
result[i] = rawResult.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
return FieldReadResult{
|
|
||||||
Value: result,
|
|
||||||
Exists: true,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *MapFieldReader) readSet(
|
func (r *MapFieldReader) readSet(
|
||||||
address []string, schema *Schema) (FieldReadResult, error) {
|
address []string, schema *Schema) (FieldReadResult, error) {
|
||||||
// Get the number of elements in the list
|
// Get the number of elements in the list
|
||||||
|
|
|
@ -106,252 +106,3 @@ func TestMapFieldReader_extra(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMapFieldReader_SetInSet(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
r := &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_set.#": "1",
|
|
||||||
"main_set.2813616083.inner_string_set.#": "2",
|
|
||||||
"main_set.2813616083.inner_string_set.2654390964": "blue",
|
|
||||||
"main_set.2813616083.inner_string_set.3499814433": "green",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := r.ReadField([]string{"main_set"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadField failed: %#v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := result.Value
|
|
||||||
if v == nil {
|
|
||||||
t.Fatal("Expected Value to be not nil")
|
|
||||||
}
|
|
||||||
list := v.(*Set).List()
|
|
||||||
if len(list) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance, got %d", len(list))
|
|
||||||
}
|
|
||||||
if list[0] == nil {
|
|
||||||
t.Fatalf("Expected value to be not nil: %#v", list)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := list[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMapFieldReader_SetInList(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
r := &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_list.#": "1",
|
|
||||||
"main_list.0.inner_string_set.#": "2",
|
|
||||||
"main_list.0.inner_string_set.2654390964": "blue",
|
|
||||||
"main_list.0.inner_string_set.3499814433": "green",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := r.ReadField([]string{"main_list"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadField failed: %#v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := result.Value
|
|
||||||
if v == nil {
|
|
||||||
t.Fatal("Expected Value to be not nil")
|
|
||||||
}
|
|
||||||
list := v.([]interface{})
|
|
||||||
if len(list) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance, got %d", len(list))
|
|
||||||
}
|
|
||||||
if list[0] == nil {
|
|
||||||
t.Fatalf("Expected value to be not nil: %#v", list)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := list[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMapFieldReader_SetInList_complex(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
"inner_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
r := &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_list.#": "1",
|
|
||||||
"main_list.0.inner_string_set.#": "2",
|
|
||||||
"main_list.0.inner_string_set.2654390964": "blue",
|
|
||||||
"main_list.0.inner_string_set.3499814433": "green",
|
|
||||||
"main_list.0.inner_int": "4",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := r.ReadField([]string{"main_list"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadField failed: %#v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := result.Value
|
|
||||||
if v == nil {
|
|
||||||
t.Fatal("Expected Value to be not nil")
|
|
||||||
}
|
|
||||||
list := v.([]interface{})
|
|
||||||
if len(list) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance, got %d", len(list))
|
|
||||||
}
|
|
||||||
if list[0] == nil {
|
|
||||||
t.Fatalf("Expected value to be not nil: %#v", list)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := list[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMapFieldReader_readSet_SetInSet(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
r := &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_set.#": "1",
|
|
||||||
"main_set.2813616083.inner_string_set.#": "2",
|
|
||||||
"main_set.2813616083.inner_string_set.2654390964": "blue",
|
|
||||||
"main_set.2813616083.inner_string_set.3499814433": "green",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := r.readSet([]string{"main_set"}, schema["main_set"])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("readSet failed: %#v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := result.Value
|
|
||||||
if v == nil {
|
|
||||||
t.Fatal("Expected Value to be not nil")
|
|
||||||
}
|
|
||||||
list := v.(*Set).List()
|
|
||||||
if len(list) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance, got %d", len(list))
|
|
||||||
}
|
|
||||||
if list[0] == nil {
|
|
||||||
t.Fatalf("Expected value to be not nil: %#v", list)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := list[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -264,361 +264,7 @@ func TestMultiLevelFieldReaderReadFieldMerge(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(tc.Result, out) {
|
if !reflect.DeepEqual(tc.Result, out) {
|
||||||
t.Fatalf("Case %s:\ngiven: %#v\nexpected: %#v", name, out, tc.Result)
|
t.Fatalf("%s: bad: %#v", name, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMultiLevelFieldReader_ReadField_SetInSet(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var readers = make(map[string]FieldReader)
|
|
||||||
readers["state"] = &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_set.#": "1",
|
|
||||||
"main_set.2813616083.inner_string_set.#": "2",
|
|
||||||
"main_set.2813616083.inner_string_set.2654390964": "blue",
|
|
||||||
"main_set.2813616083.inner_string_set.3499814433": "green",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
readers["diff"] = &DiffFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Diff: &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "9",
|
|
||||||
New: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Source: &MultiLevelFieldReader{
|
|
||||||
Levels: []string{"state", "config"},
|
|
||||||
Readers: readers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
mr := &MultiLevelFieldReader{
|
|
||||||
Levels: []string{
|
|
||||||
"state",
|
|
||||||
"diff",
|
|
||||||
},
|
|
||||||
|
|
||||||
Readers: readers,
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := mr.ReadField([]string{"main_set"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadField failed: %#v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := result.Value
|
|
||||||
if v == nil {
|
|
||||||
t.Fatal("Expected Value to be not nil")
|
|
||||||
}
|
|
||||||
list := v.(*Set).List()
|
|
||||||
if len(list) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance, got %d", len(list))
|
|
||||||
}
|
|
||||||
if list[0] == nil {
|
|
||||||
t.Fatalf("Expected value to be not nil: %#v", list)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := list[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMultiLevelFieldReader_ReadField_SetInSet_complex(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
"inner_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var readers = make(map[string]FieldReader)
|
|
||||||
readers["state"] = &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_set.#": "1",
|
|
||||||
"main_set.2476980464.inner_string_set.#": "2",
|
|
||||||
"main_set.2476980464.inner_string_set.2654390964": "blue",
|
|
||||||
"main_set.2476980464.inner_string_set.3499814433": "green",
|
|
||||||
"main_set.2476980464.inner_int": "4",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
readers["diff"] = &DiffFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Diff: &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "9",
|
|
||||||
New: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Source: &MultiLevelFieldReader{
|
|
||||||
Levels: []string{"state", "config"},
|
|
||||||
Readers: readers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
mr := &MultiLevelFieldReader{
|
|
||||||
Levels: []string{
|
|
||||||
"state",
|
|
||||||
"diff",
|
|
||||||
},
|
|
||||||
|
|
||||||
Readers: readers,
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := mr.ReadFieldMerge([]string{"main_set"}, "diff")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadFieldMerge failed: %#v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := result.Value
|
|
||||||
if v == nil {
|
|
||||||
t.Fatal("Expected Value to be not nil")
|
|
||||||
}
|
|
||||||
list := v.(*Set).List()
|
|
||||||
if len(list) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance, got %d", len(list))
|
|
||||||
}
|
|
||||||
if list[0] == nil {
|
|
||||||
t.Fatalf("Expected value to be not nil: %#v", list)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := list[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMultiLevelFieldReader_ReadField_SetInList_simple(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var readers = make(map[string]FieldReader)
|
|
||||||
readers["state"] = &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_list.#": "1",
|
|
||||||
"main_list.0.inner_string_set.#": "2",
|
|
||||||
"main_list.0.inner_string_set.2654390964": "blue",
|
|
||||||
"main_list.0.inner_string_set.3499814433": "green",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
readers["diff"] = &DiffFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Diff: &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "9",
|
|
||||||
New: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Source: &MultiLevelFieldReader{
|
|
||||||
Levels: []string{"state", "config"},
|
|
||||||
Readers: readers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
mr := &MultiLevelFieldReader{
|
|
||||||
Levels: []string{
|
|
||||||
"state",
|
|
||||||
"diff",
|
|
||||||
},
|
|
||||||
|
|
||||||
Readers: readers,
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := mr.ReadField([]string{"main_list"})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadField failed: %#v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := result.Value
|
|
||||||
if v == nil {
|
|
||||||
t.Fatal("Expected Value to be not nil")
|
|
||||||
}
|
|
||||||
list := v.([]interface{})
|
|
||||||
if len(list) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance, got %d", len(list))
|
|
||||||
}
|
|
||||||
if list[0] == nil {
|
|
||||||
t.Fatalf("Expected value to be not nil: %#v", list)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := list[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMultiLevelFieldReader_ReadField_SetInList_complex(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
"inner_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var readers = make(map[string]FieldReader)
|
|
||||||
readers["state"] = &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_list.#": "1",
|
|
||||||
"main_list.0.inner_string_set.#": "2",
|
|
||||||
"main_list.0.inner_string_set.2654390964": "blue",
|
|
||||||
"main_list.0.inner_string_set.3499814433": "green",
|
|
||||||
"main_list.0.inner_int": "4",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
readers["diff"] = &DiffFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Diff: &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "9",
|
|
||||||
New: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Source: &MultiLevelFieldReader{
|
|
||||||
Levels: []string{"state", "config"},
|
|
||||||
Readers: readers,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
mr := &MultiLevelFieldReader{
|
|
||||||
Levels: []string{
|
|
||||||
"state",
|
|
||||||
"diff",
|
|
||||||
},
|
|
||||||
|
|
||||||
Readers: readers,
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := mr.ReadFieldMerge([]string{"main_list"}, "diff")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ReadFieldMerge failed: %#v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := result.Value
|
|
||||||
if v == nil {
|
|
||||||
t.Fatal("Expected Value to be not nil")
|
|
||||||
}
|
|
||||||
list := v.([]interface{})
|
|
||||||
if len(list) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance, got %d", len(list))
|
|
||||||
}
|
|
||||||
if list[0] == nil {
|
|
||||||
t.Fatalf("Expected value to be not nil: %#v", list)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := list[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -395,68 +395,7 @@ func testFieldReader(t *testing.T, f func(map[string]*Schema) FieldReader) {
|
||||||
out.Value = s.List()
|
out.Value = s.List()
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(tc.Result, out) {
|
if !reflect.DeepEqual(tc.Result, out) {
|
||||||
t.Fatalf("%s: Unexpected field result:\nGiven: %#v\nExpected: %#v", name, out, tc.Result)
|
t.Fatalf("%s: bad: %#v", name, out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadList_SetInList(t *testing.T) {
|
|
||||||
schema := map[string]*Schema{
|
|
||||||
"main_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
r := &MapFieldReader{
|
|
||||||
Schema: schema,
|
|
||||||
Map: BasicMapReader(map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_list.#": "1",
|
|
||||||
"main_list.0.inner_string_set.#": "2",
|
|
||||||
"main_list.0.inner_string_set.2654390964": "blue",
|
|
||||||
"main_list.0.inner_string_set.3499814433": "green",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := r.readList([]string{"main_list"}, schema["main_list"])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("readListField failed: %#v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := result.Value
|
|
||||||
if v == nil {
|
|
||||||
t.Fatal("Expected Value to be not nil")
|
|
||||||
}
|
|
||||||
list := v.([]interface{})
|
|
||||||
if len(list) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance, got %d", len(list))
|
|
||||||
}
|
|
||||||
if list[0] == nil {
|
|
||||||
t.Fatalf("Expected value to be not nil: %#v", list)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := list[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -751,212 +751,6 @@ func TestResourceDataGet(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetInsideSet(t *testing.T) {
|
|
||||||
_schema := map[string]*Schema{
|
|
||||||
"main_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
existingState := &terraform.InstanceState{
|
|
||||||
ID: "8395051352714003426",
|
|
||||||
Attributes: map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_set.#": "1",
|
|
||||||
"main_set.2813616083.inner_string_set.#": "2",
|
|
||||||
"main_set.2813616083.inner_string_set.2654390964": "blue",
|
|
||||||
"main_set.2813616083.inner_string_set.3499814433": "green",
|
|
||||||
},
|
|
||||||
Meta: map[string]string{},
|
|
||||||
Tainted: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
suggestedDiff := &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "9",
|
|
||||||
New: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
d := &ResourceData{
|
|
||||||
schema: _schema,
|
|
||||||
state: existingState,
|
|
||||||
diff: suggestedDiff,
|
|
||||||
}
|
|
||||||
|
|
||||||
v := d.Get("main_set").(*Set).List()
|
|
||||||
if len(v) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance of main_set, got %d", len(v))
|
|
||||||
}
|
|
||||||
if v[0] == nil {
|
|
||||||
t.Fatalf("Expected main_set to be not nil: %#v", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := v[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetInsideList_simple(t *testing.T) {
|
|
||||||
_schema := map[string]*Schema{
|
|
||||||
"main_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
existingState := &terraform.InstanceState{
|
|
||||||
ID: "8395051352714003426",
|
|
||||||
Attributes: map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_list.#": "1",
|
|
||||||
"main_list.0.inner_string_set.#": "2",
|
|
||||||
"main_list.0.inner_string_set.2654390964": "blue",
|
|
||||||
"main_list.0.inner_string_set.3499814433": "green",
|
|
||||||
},
|
|
||||||
Meta: map[string]string{},
|
|
||||||
Tainted: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
suggestedDiff := &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "9",
|
|
||||||
New: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
d := &ResourceData{
|
|
||||||
schema: _schema,
|
|
||||||
state: existingState,
|
|
||||||
diff: suggestedDiff,
|
|
||||||
}
|
|
||||||
|
|
||||||
v := d.Get("main_list").([]interface{})
|
|
||||||
if len(v) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance of main_list, got %d", len(v))
|
|
||||||
}
|
|
||||||
if v[0] == nil {
|
|
||||||
t.Fatalf("Expected main_list to be not nil: %#v", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := v[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetInsideList_complex(t *testing.T) {
|
|
||||||
_schema := map[string]*Schema{
|
|
||||||
"main_list": &Schema{
|
|
||||||
Type: TypeList,
|
|
||||||
Optional: true,
|
|
||||||
Elem: &Resource{
|
|
||||||
Schema: map[string]*Schema{
|
|
||||||
"inner_string_set": &Schema{
|
|
||||||
Type: TypeSet,
|
|
||||||
Required: true,
|
|
||||||
Set: HashString,
|
|
||||||
Elem: &Schema{Type: TypeString},
|
|
||||||
},
|
|
||||||
"inner_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"main_int": &Schema{
|
|
||||||
Type: TypeInt,
|
|
||||||
Optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
existingState := &terraform.InstanceState{
|
|
||||||
ID: "8395051352714003426",
|
|
||||||
Attributes: map[string]string{
|
|
||||||
"id": "8395051352714003426",
|
|
||||||
"main_int": "9",
|
|
||||||
"main_list.#": "1",
|
|
||||||
"main_list.0.inner_string_set.#": "2",
|
|
||||||
"main_list.0.inner_string_set.2654390964": "blue",
|
|
||||||
"main_list.0.inner_string_set.3499814433": "green",
|
|
||||||
"main_list.0.inner_int": "4",
|
|
||||||
},
|
|
||||||
Meta: map[string]string{},
|
|
||||||
Tainted: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
suggestedDiff := &terraform.InstanceDiff{
|
|
||||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
||||||
"main_int": &terraform.ResourceAttrDiff{
|
|
||||||
Old: "9",
|
|
||||||
New: "2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
d := &ResourceData{
|
|
||||||
schema: _schema,
|
|
||||||
state: existingState,
|
|
||||||
diff: suggestedDiff,
|
|
||||||
}
|
|
||||||
|
|
||||||
v := d.Get("main_list").([]interface{})
|
|
||||||
if len(v) != 1 {
|
|
||||||
t.Fatalf("Expected exactly 1 instance of main_list, got %d", len(v))
|
|
||||||
}
|
|
||||||
if v[0] == nil {
|
|
||||||
t.Fatalf("Expected main_list to be not nil: %#v", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := v[0].(map[string]interface{})
|
|
||||||
set := m["inner_string_set"].(*Set).List()
|
|
||||||
expectedSet := NewSet(HashString, []interface{}{"blue", "green"}).List()
|
|
||||||
if !reflect.DeepEqual(set, expectedSet) {
|
|
||||||
t.Fatalf("Given: %#v\n\nExpected: %#v", set, expectedSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestResourceDataGetChange(t *testing.T) {
|
func TestResourceDataGetChange(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
Schema map[string]*Schema
|
Schema map[string]*Schema
|
||||||
|
|
|
@ -98,10 +98,6 @@ func (s *Set) List() []interface{} {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Set) Map() map[string]interface{} {
|
|
||||||
return s.m
|
|
||||||
}
|
|
||||||
|
|
||||||
// Difference performs a set difference of the two sets, returning
|
// Difference performs a set difference of the two sets, returning
|
||||||
// a new third set that has only the elements unique to this set.
|
// a new third set that has only the elements unique to this set.
|
||||||
func (s *Set) Difference(other *Set) *Set {
|
func (s *Set) Difference(other *Set) *Set {
|
||||||
|
|
Loading…
Reference in New Issue