From 084670c2417196e76d2ed73ba1d93ea4e0788d24 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 16 Dec 2016 10:31:02 -0500 Subject: [PATCH] Use flatmap.Expand to extract interpolated values Now that flatmap.Expand will properly expand nested maps, we can use that to extract any lists and maps when interpolating. --- terraform/interpolate.go | 58 ++--------------------------- terraform/interpolate_test.go | 70 ++++++++++++++++++++++++++++------- 2 files changed, 59 insertions(+), 69 deletions(-) diff --git a/terraform/interpolate.go b/terraform/interpolate.go index 152e60971d..4cbfab78ef 100644 --- a/terraform/interpolate.go +++ b/terraform/interpolate.go @@ -4,8 +4,6 @@ import ( "fmt" "log" "os" - "regexp" - "sort" "strconv" "strings" "sync" @@ -620,33 +618,6 @@ func (i *Interpolater) computeResourceMultiVariable( return &variable, err } -type indexKeys []string - -// we need to separate the index integer from the ID, and sort numerically -func (i indexKeys) Less(j, k int) bool { - jDot := strings.LastIndex(i[j], ".") - kDot := strings.LastIndex(i[j], ".") - - // These should all be properly formatted, but check the indexes and return - // a safe value just in case. - if jDot < 0 || kDot < 0 { - return i[j] < i[k] - } - - jIdx, _ := strconv.Atoi(i[j][jDot+1:]) - kIdx, _ := strconv.Atoi(i[k][kDot+1:]) - - return jIdx < kIdx -} - -func (i indexKeys) Swap(j, k int) { - i[j], i[k] = i[k], i[j] -} - -func (i indexKeys) Len() int { - return len(i) -} - func (i *Interpolater) interpolateComplexTypeAttribute( resourceID string, attributes map[string]string) (ast.Variable, error) { @@ -668,23 +639,8 @@ func (i *Interpolater) interpolateComplexTypeAttribute( return unknownVariable(), nil } - keys := make([]string, 0) - listElementKey := regexp.MustCompile("^" + resourceID + "\\.[0-9]+$") - for id := range attributes { - if listElementKey.MatchString(id) { - keys = append(keys, id) - } - } - - // sort the keys by their index number, rather than lexicographically by the key - sort.Sort(indexKeys(keys)) - - var members []string - for _, key := range keys { - members = append(members, attributes[key]) - } - - return hil.InterfaceToVariable(members) + expanded := flatmap.Expand(attributes, resourceID) + return hil.InterfaceToVariable(expanded) } if lengthAttr, isMap := attributes[resourceID+".%"]; isMap { @@ -699,15 +655,7 @@ func (i *Interpolater) interpolateComplexTypeAttribute( return unknownVariable(), nil } - resourceFlatMap := make(map[string]string) - mapElementKey := regexp.MustCompile("^" + resourceID + "\\.([^%]+)$") - for id, val := range attributes { - if mapElementKey.MatchString(id) { - resourceFlatMap[id] = val - } - } - - expanded := flatmap.Expand(resourceFlatMap, resourceID) + expanded := flatmap.Expand(attributes, resourceID) return hil.InterfaceToVariable(expanded) } diff --git a/terraform/interpolate_test.go b/terraform/interpolate_test.go index de24692115..9c6cdc40ed 100644 --- a/terraform/interpolate_test.go +++ b/terraform/interpolate_test.go @@ -4,7 +4,6 @@ import ( "fmt" "os" "reflect" - "sort" "sync" "testing" @@ -675,19 +674,6 @@ func TestInterpolater_selfVarWithoutResource(t *testing.T) { } } -// Verify sorting by key index number -func TestInterpolator_indexKeySort(t *testing.T) { - keys := []string{"a.1", "a.2", "a.10", "a.20", "a.3"} - sorted := []string{"a.1", "a.2", "a.3", "a.10", "a.20"} - - sort.Sort(indexKeys(keys)) - for i := range keys { - if keys[i] != sorted[i] { - t.Fatalf("indexes out of order\nexpected: %q\ngot: %q", sorted, keys) - } - } -} - func TestInterpolator_interpolatedListOrder(t *testing.T) { state := &State{ Modules: []*ModuleState{ @@ -796,6 +782,62 @@ func getInterpolaterFixture(t *testing.T) *Interpolater { } } +func TestInterpolator_nestedMapsAndLists(t *testing.T) { + state := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: map[string]*ResourceState{ + "aws_route53_zone.yada": &ResourceState{ + Type: "aws_route53_zone", + Dependencies: []string{}, + Primary: &InstanceState{ + ID: "null", + Attributes: map[string]string{ + "list_of_map.#": "2", + "list_of_map.0.%": "1", + "list_of_map.0.a": "1", + "list_of_map.1.%": "1", + "list_of_map.1.b": "2", + "map_of_list.%": "2", + "map_of_list.list2.#": "1", + "map_of_list.list2.0": "b", + "map_of_list.list1.#": "1", + "map_of_list.list1.0": "a", + }, + }, + }, + }, + }, + }, + } + + i := &Interpolater{ + Module: testModule(t, "interpolate-multi-vars"), + StateLock: new(sync.RWMutex), + State: state, + } + + scope := &InterpolationScope{ + Path: rootModulePath, + } + + listOfMap := []interface{}{ + map[string]interface{}{"a": "1"}, + map[string]interface{}{"b": "2"}, + } + + mapOfList := map[string]interface{}{ + "list1": []interface{}{"a"}, + "list2": []interface{}{"b"}, + } + + testInterpolate(t, i, scope, "aws_route53_zone.yada.list_of_map", + interfaceToVariableSwallowError(listOfMap)) + testInterpolate(t, i, scope, `aws_route53_zone.yada.map_of_list`, + interfaceToVariableSwallowError(mapOfList)) +} + func testInterpolate( t *testing.T, i *Interpolater, scope *InterpolationScope,