core: Fix interpolation of complex structures
This commit makes two changes: map interpolation can now read flatmapped structures, such as those present in remote state outputs, and lists are sorted by the index instead of the value.
This commit is contained in:
parent
dbf725bd68
commit
f51c9d5efd
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/hashicorp/hil/ast"
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/config/module"
|
||||
"github.com/hashicorp/terraform/flatmap"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -213,6 +214,7 @@ func (i *Interpolater) valueResourceVar(
|
|||
result map[string]ast.Variable) error {
|
||||
// If we're computing all dynamic fields, then module vars count
|
||||
// and we mark it as computed.
|
||||
|
||||
if i.Operation == walkValidate {
|
||||
result[n] = ast.Variable{
|
||||
Value: config.UnknownVariableValue,
|
||||
|
@ -343,6 +345,7 @@ func (i *Interpolater) valueUserVar(
|
|||
func (i *Interpolater) computeResourceVariable(
|
||||
scope *InterpolationScope,
|
||||
v *config.ResourceVariable) (*ast.Variable, error) {
|
||||
|
||||
id := v.ResourceId()
|
||||
if v.Multi {
|
||||
id = fmt.Sprintf("%s.%d", id, v.Index)
|
||||
|
@ -589,21 +592,19 @@ func (i *Interpolater) interpolateComplexTypeAttribute(
|
|||
return unknownVariable(), nil
|
||||
}
|
||||
|
||||
var keys []string
|
||||
keys := make([]string, 0)
|
||||
listElementKey := regexp.MustCompile("^" + resourceID + "\\.[0-9]+$")
|
||||
for id, _ := range attributes {
|
||||
if listElementKey.MatchString(id) {
|
||||
keys = append(keys, id)
|
||||
}
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
var members []string
|
||||
for _, key := range keys {
|
||||
members = append(members, attributes[key])
|
||||
}
|
||||
// This behaviour still seems very broken to me... it retains BC but is
|
||||
// probably going to cause problems in future
|
||||
sort.Strings(members)
|
||||
|
||||
return hil.InterfaceToVariable(members)
|
||||
}
|
||||
|
@ -620,19 +621,16 @@ func (i *Interpolater) interpolateComplexTypeAttribute(
|
|||
return unknownVariable(), nil
|
||||
}
|
||||
|
||||
var keys []string
|
||||
resourceFlatMap := make(map[string]string)
|
||||
mapElementKey := regexp.MustCompile("^" + resourceID + "\\.([^%]+)$")
|
||||
for id, _ := range attributes {
|
||||
if submatches := mapElementKey.FindAllStringSubmatch(id, -1); len(submatches) > 0 {
|
||||
keys = append(keys, submatches[0][1])
|
||||
for id, val := range attributes {
|
||||
if mapElementKey.MatchString(id) {
|
||||
resourceFlatMap[id] = val
|
||||
}
|
||||
}
|
||||
|
||||
members := make(map[string]interface{})
|
||||
for _, key := range keys {
|
||||
members[key] = attributes[resourceID+"."+key]
|
||||
}
|
||||
return hil.InterfaceToVariable(members)
|
||||
expanded := flatmap.Expand(resourceFlatMap, resourceID)
|
||||
return hil.InterfaceToVariable(expanded)
|
||||
}
|
||||
|
||||
return ast.Variable{}, fmt.Errorf("No complex type %s found", resourceID)
|
||||
|
|
|
@ -141,6 +141,95 @@ func TestInterpolater_pathRoot(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestInterpolater_resourceVariableMap(t *testing.T) {
|
||||
lock := new(sync.RWMutex)
|
||||
state := &State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: rootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.web": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "bar",
|
||||
Attributes: map[string]string{
|
||||
"amap.%": "3",
|
||||
"amap.key1": "value1",
|
||||
"amap.key2": "value2",
|
||||
"amap.key3": "value3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
i := &Interpolater{
|
||||
Module: testModule(t, "interpolate-resource-variable"),
|
||||
State: state,
|
||||
StateLock: lock,
|
||||
}
|
||||
|
||||
scope := &InterpolationScope{
|
||||
Path: rootModulePath,
|
||||
}
|
||||
|
||||
expected := map[string]interface{}{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
"key3": "value3",
|
||||
}
|
||||
|
||||
testInterpolate(t, i, scope, "aws_instance.web.amap",
|
||||
interfaceToVariableSwallowError(expected))
|
||||
}
|
||||
|
||||
func TestInterpolater_resourceVariableComplexMap(t *testing.T) {
|
||||
lock := new(sync.RWMutex)
|
||||
state := &State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
Path: rootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_instance.web": &ResourceState{
|
||||
Type: "aws_instance",
|
||||
Primary: &InstanceState{
|
||||
ID: "bar",
|
||||
Attributes: map[string]string{
|
||||
"amap.%": "2",
|
||||
"amap.key1.#": "2",
|
||||
"amap.key1.0": "hello",
|
||||
"amap.key1.1": "world",
|
||||
"amap.key2.#": "1",
|
||||
"amap.key2.0": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
i := &Interpolater{
|
||||
Module: testModule(t, "interpolate-resource-variable"),
|
||||
State: state,
|
||||
StateLock: lock,
|
||||
}
|
||||
|
||||
scope := &InterpolationScope{
|
||||
Path: rootModulePath,
|
||||
}
|
||||
|
||||
expected := map[string]interface{}{
|
||||
"key1": []interface{}{"hello", "world"},
|
||||
"key2": []interface{}{"foo"},
|
||||
}
|
||||
|
||||
testInterpolate(t, i, scope, "aws_instance.web.amap",
|
||||
interfaceToVariableSwallowError(expected))
|
||||
}
|
||||
|
||||
func TestInterpolater_resourceVariable(t *testing.T) {
|
||||
lock := new(sync.RWMutex)
|
||||
state := &State{
|
||||
|
@ -278,10 +367,10 @@ func TestInterpolator_resourceMultiAttributes(t *testing.T) {
|
|||
lock := new(sync.RWMutex)
|
||||
state := &State{
|
||||
Modules: []*ModuleState{
|
||||
&ModuleState{
|
||||
{
|
||||
Path: rootModulePath,
|
||||
Resources: map[string]*ResourceState{
|
||||
"aws_route53_zone.yada": &ResourceState{
|
||||
"aws_route53_zone.yada": {
|
||||
Type: "aws_route53_zone",
|
||||
Dependencies: []string{},
|
||||
Primary: &InstanceState{
|
||||
|
@ -354,8 +443,8 @@ func TestInterpolator_resourceMultiAttributesWithResourceCount(t *testing.T) {
|
|||
"ns-601.awsdns-11.net",
|
||||
"ns-000.awsdns-38.org",
|
||||
"ns-444.awsdns-18.co.uk",
|
||||
"ns-666.awsdns-11.net",
|
||||
"ns-999.awsdns-62.com",
|
||||
"ns-666.awsdns-11.net",
|
||||
}
|
||||
|
||||
// More than 1 element
|
||||
|
|
Loading…
Reference in New Issue