Skip to content

Commit

Permalink
Fix string representation of sets during interpolation
Browse files Browse the repository at this point in the history
The change in hashicorp#10787 used flatmap.Expand to fix interpolation of nested
maps, but it broke interpolation of sets such that their elements were
not represented. For example, the expected string representation of a
splatted aws_network_interface.whatever.*.private_ips should be:

```
[{Variable (TypeList): [{Variable (TypeString): 10.41.17.25}]} {Variable (TypeList): [{Variable (TypeString): 10.41.22.236}]}]
```

But instead it became:

```
[{Variable (TypeList): [{Variable (TypeString): }]} {Variable (TypeList): [{Variable (TypeString): }]}]
```

This is because the expandArray function of expand.go treated arrays to
exclusively be lists, e.g. not sets. The old code used to match for
numeric keys, so it would work for sets, whereas expandArray just
assumed keys started at 0 and ascended incrementally. Remember that
sets' keys are numeric, but since they are hashes, they can be any
integer. The result of assuming that the keys start at 0 led to the
recursive call to flatmap.Expand not matching any keys of the set, and
returning nil, which is why the above example has nothing where the IP
addresses used to be.

So we bring back that matching behavior, but we move it to expandArray
instead. We've modified it to not reconstruct the data structures like
it used to when it was in the Interpolator, and to use the standard int
sorter rather than implementing a custom sorter since a custom one is no
longer necessary thanks to the use of flatmap.Expand.

Fixes hashicorp#10908, and restores the viability of the workaround I posted in hashicorp#8696.

Big thanks to @jszwedko for helping me with this fix. I was able to
diagnose the problem along, but couldn't fix it without his help.
  • Loading branch information
2rs2ts authored and Jesse Szwedko committed Dec 23, 2016
1 parent 2d894ba commit 497010c
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 2 deletions.
24 changes: 22 additions & 2 deletions flatmap/expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package flatmap

import (
"fmt"
"regexp"
"sort"
"strconv"
"strings"
)
Expand Down Expand Up @@ -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
Expand Down
38 changes: 38 additions & 0 deletions terraform/interpolate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 497010c

Please sign in to comment.