diff --git a/flatmap/expand.go b/flatmap/expand.go index b2072a62f..0e3ebe003 100644 --- a/flatmap/expand.go +++ b/flatmap/expand.go @@ -2,6 +2,8 @@ package flatmap import ( "fmt" + "regexp" + "sort" "strconv" "strings" ) @@ -42,9 +44,27 @@ func expandArray(m map[string]string, prefix string) []interface{} { panic(err) } + keySet := make(map[int]struct{}) + listElementKey := regexp.MustCompile("^" + prefix + "\\.([0-9]+)(?:\\..*)?$") + for key := range m { + if matches := listElementKey.FindStringSubmatch(key); matches != nil { + k, err := strconv.ParseInt(matches[1], 0, 0) + if err != nil { + panic(err) + } + keySet[int(k)] = struct{}{} + } + } + + keysList := make([]int, 0, num) + for key := range keySet { + keysList = append(keysList, key) + } + sort.Ints(keysList) + result := make([]interface{}, num) - for i := 0; i < int(num); i++ { - result[i] = Expand(m, fmt.Sprintf("%s.%d", prefix, i)) + for i, key := range keysList { + result[i] = Expand(m, fmt.Sprintf("%s.%d", prefix, key)) } return result diff --git a/terraform/interpolate_test.go b/terraform/interpolate_test.go index 9c6cdc40e..54f762fe7 100644 --- a/terraform/interpolate_test.go +++ b/terraform/interpolate_test.go @@ -838,6 +838,44 @@ func TestInterpolator_nestedMapsAndLists(t *testing.T) { interfaceToVariableSwallowError(mapOfList)) } +func TestInterpolator_sets(t *testing.T) { + state := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: map[string]*ResourceState{ + "aws_network_interface.set": &ResourceState{ + Type: "aws_network_interface", + Dependencies: []string{}, + Primary: &InstanceState{ + ID: "null", + Attributes: map[string]string{ + "private_ips.#": "1", + "private_ips.3977356764": "10.42.16.179", + }, + }, + }, + }, + }, + }, + } + + i := &Interpolater{ + Module: testModule(t, "interpolate-multi-vars"), + StateLock: new(sync.RWMutex), + State: state, + } + + scope := &InterpolationScope{ + Path: rootModulePath, + } + + set := []interface{}{"10.42.16.179"} + + testInterpolate(t, i, scope, "aws_network_interface.set.private_ips", + interfaceToVariableSwallowError(set)) +} + func testInterpolate( t *testing.T, i *Interpolater, scope *InterpolationScope,