terraform: inner-count dependencies work [GH-1540]

This commit is contained in:
Mitchell Hashimoto 2015-04-18 15:56:43 -07:00
parent 897e0f1e45
commit 2fffec9545
5 changed files with 80 additions and 6 deletions

View File

@ -279,6 +279,25 @@ func (n *GraphNodeConfigResource) DependentOn() []string {
return result
}
// VarWalk calls a callback for all the variables that this resource
// depends on.
func (n *GraphNodeConfigResource) VarWalk(fn func(config.InterpolatedVariable)) {
for _, v := range n.Resource.RawCount.Variables {
fn(v)
}
for _, v := range n.Resource.RawConfig.Variables {
fn(v)
}
for _, p := range n.Resource.Provisioners {
for _, v := range p.ConnInfo.Variables {
fn(v)
}
for _, v := range p.RawConfig.Variables {
fn(v)
}
}
}
func (n *GraphNodeConfigResource) Name() string {
result := n.Resource.Id()
switch n.DestroyMode {

View File

@ -1,4 +1,3 @@
resource "aws_instance" "foo" {
count = 3
value = "${aws_instance.foo.0.value}"
}

View File

@ -0,0 +1,8 @@
resource "aws_instance" "foo" {
count = 2
provisioner "local-exec" {
command = "echo ${aws_instance.foo.0.id}"
other = "echo ${aws_instance.foo.id}"
}
}

View File

@ -134,8 +134,34 @@ func (n *graphNodeExpandedResource) DependableName() []string {
// GraphNodeDependent impl.
func (n *graphNodeExpandedResource) DependentOn() []string {
config := &GraphNodeConfigResource{Resource: n.Resource}
return config.DependentOn()
configNode := &GraphNodeConfigResource{Resource: n.Resource}
result := configNode.DependentOn()
// Walk the variables to find any count-specific variables we depend on.
configNode.VarWalk(func(v config.InterpolatedVariable) {
rv, ok := v.(*config.ResourceVariable)
if !ok {
return
}
// We only want ourselves
if rv.ResourceId() != n.Resource.Id() {
return
}
// If this isn't a multi-access (which shouldn't be allowed but
// is verified elsewhere), then we depend on the specific count
// of this resource, ignoring ourself (which again should be
// validated elsewhere).
if rv.Index > -1 {
id := fmt.Sprintf("%s.%d", rv.ResourceId(), rv.Index)
if id != n.stateId() && id != n.stateId()+".0" {
result = append(result, id)
}
}
})
return result
}
// GraphNodeProviderConsumer

View File

@ -37,11 +37,33 @@ func TestResourceCountTransformer_countNegative(t *testing.T) {
}
}
func TestResourceCountTransformer_deps(t *testing.T) {
cfg := testModule(t, "transform-resource-count-deps").Config()
resource := cfg.Resources[0]
g := Graph{Path: RootModulePath}
{
tf := &ResourceCountTransformer{Resource: resource}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}
actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(testResourceCountTransformDepsStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}
}
const testResourceCountTransformStr = `
aws_instance.foo #0
aws_instance.foo #2
aws_instance.foo #1
aws_instance.foo #2
aws_instance.foo #2
aws_instance.foo #2
`
const testResourceCountTransformDepsStr = `
aws_instance.foo #0
aws_instance.foo #1
aws_instance.foo #0
`