core: treat refs to unknown set resource attrs as unknown
References to computed list-ish attributes (set, list, map) were being improperly resolved as an empty list `[]` during the plan phase (when the value of the reference is not yet known) instead of as an UnknownValue. A "diffs didn't match" failure in an AWS DirectoryServices test led to this discovery (and this commit fixes the failing test): https://travis-ci.org/hashicorp/terraform/jobs/104812951 Refs #2157 which has the original work to support computed list attributes at all. This is just a simple tweak to that work. /cc @radeksimko
This commit is contained in:
parent
da4e7753e7
commit
48b172aa86
|
@ -519,6 +519,16 @@ func (i *Interpolater) interpolateListAttribute(
|
||||||
log.Printf("[DEBUG] Interpolating computed list attribute %s (%s)",
|
log.Printf("[DEBUG] Interpolating computed list attribute %s (%s)",
|
||||||
resourceID, attr)
|
resourceID, attr)
|
||||||
|
|
||||||
|
// In Terraform's internal dotted representation of list-like attributes, the
|
||||||
|
// ".#" count field is marked as unknown to indicate "this whole list is
|
||||||
|
// unknown". We must honor that meaning here so computed references can be
|
||||||
|
// treated properly during the plan phase.
|
||||||
|
if attr == config.UnknownVariableValue {
|
||||||
|
return attr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we gather the values from the list-like attribute and return
|
||||||
|
// them.
|
||||||
var members []string
|
var members []string
|
||||||
numberedListMember := regexp.MustCompile("^" + resourceID + "\\.[0-9]+$")
|
numberedListMember := regexp.MustCompile("^" + resourceID + "\\.[0-9]+$")
|
||||||
for id, value := range attributes {
|
for id, value := range attributes {
|
||||||
|
|
|
@ -348,6 +348,44 @@ func TestInterpolator_resourceMultiAttributesWithResourceCount(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInterpolator_resourceMultiAttributesComputed(t *testing.T) {
|
||||||
|
lock := new(sync.RWMutex)
|
||||||
|
// The state would never be written with an UnknownVariableValue in it, but
|
||||||
|
// it can/does exist that way in memory during the plan phase.
|
||||||
|
state := &State{
|
||||||
|
Modules: []*ModuleState{
|
||||||
|
&ModuleState{
|
||||||
|
Path: rootModulePath,
|
||||||
|
Resources: map[string]*ResourceState{
|
||||||
|
"aws_route53_zone.yada": &ResourceState{
|
||||||
|
Type: "aws_route53_zone",
|
||||||
|
Primary: &InstanceState{
|
||||||
|
ID: "z-abc123",
|
||||||
|
Attributes: map[string]string{
|
||||||
|
"name_servers.#": config.UnknownVariableValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
i := &Interpolater{
|
||||||
|
Module: testModule(t, "interpolate-multi-vars"),
|
||||||
|
StateLock: lock,
|
||||||
|
State: state,
|
||||||
|
}
|
||||||
|
|
||||||
|
scope := &InterpolationScope{
|
||||||
|
Path: rootModulePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
testInterpolate(t, i, scope, "aws_route53_zone.yada.name_servers", ast.Variable{
|
||||||
|
Value: config.UnknownVariableValue,
|
||||||
|
Type: ast.TypeString,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func getInterpolaterFixture(t *testing.T) *Interpolater {
|
func getInterpolaterFixture(t *testing.T) *Interpolater {
|
||||||
lock := new(sync.RWMutex)
|
lock := new(sync.RWMutex)
|
||||||
state := &State{
|
state := &State{
|
||||||
|
|
Loading…
Reference in New Issue