Sort interpolated lists by index

Interpolated lists should be sorted by index number, rather than
lexicographic key order.
pull/10765/head
James Bardin 10 years ago
parent 61982be9c6
commit ec2550dea5

@ -620,6 +620,33 @@ 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) {
@ -648,7 +675,9 @@ func (i *Interpolater) interpolateComplexTypeAttribute(
keys = append(keys, id)
}
}
sort.Strings(keys)
// sort the keys by their index number, rather than lexicographically by the key
sort.Sort(indexKeys(keys))
var members []string
for _, key := range keys {

@ -4,6 +4,7 @@ import (
"fmt"
"os"
"reflect"
"sort"
"sync"
"testing"
@ -674,6 +675,68 @@ 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{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_route53_zone.list": &ResourceState{
Type: "aws_route53_zone",
Dependencies: []string{},
Primary: &InstanceState{
ID: "null",
Attributes: map[string]string{
"foo.#": "12",
"foo.0": "a",
"foo.1": "b",
"foo.2": "c",
"foo.3": "d",
"foo.4": "e",
"foo.5": "f",
"foo.6": "g",
"foo.7": "h",
"foo.8": "i",
"foo.9": "j",
"foo.10": "k",
"foo.11": "l",
},
},
},
},
},
},
}
i := &Interpolater{
Module: testModule(t, "interpolate-multi-vars"),
StateLock: new(sync.RWMutex),
State: state,
}
scope := &InterpolationScope{
Path: rootModulePath,
}
list := []interface{}{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"}
testInterpolate(t, i, scope, "aws_route53_zone.list.foo",
interfaceToVariableSwallowError(list))
}
func getInterpolaterFixture(t *testing.T) *Interpolater {
lock := new(sync.RWMutex)
state := &State{

Loading…
Cancel
Save