diff --git a/terraform/context_plan_test.go b/terraform/context_plan_test.go index aafb74b0764a..9dd6e14f4da8 100644 --- a/terraform/context_plan_test.go +++ b/terraform/context_plan_test.go @@ -1319,6 +1319,31 @@ func TestContext2Plan_computedList(t *testing.T) { } } +// GH-8695. This tests that you can index into a computed list on a +// splatted resource. +func TestContext2Plan_computedMultiIndex(t *testing.T) { + m := testModule(t, "plan-computed-multi-index") + p := testProvider("aws") + p.DiffFn = testDiffFn + ctx := testContext2(t, &ContextOpts{ + Module: m, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + }) + + plan, err := ctx.Plan() + if err != nil { + t.Fatalf("err: %s", err) + } + + actual := strings.TrimSpace(plan.String()) + expected := strings.TrimSpace(testTerraformPlanComputedMultiIndexStr) + if actual != expected { + t.Fatalf("bad:\n%s", actual) + } +} + func TestContext2Plan_count(t *testing.T) { m := testModule(t, "plan-count") p := testProvider("aws") diff --git a/terraform/interpolate.go b/terraform/interpolate.go index 3d88da844542..252fb7637394 100644 --- a/terraform/interpolate.go +++ b/terraform/interpolate.go @@ -587,7 +587,7 @@ func (i *Interpolater) computeResourceMultiVariable( } if multiAttr == unknownVariable { - return &ast.Variable{Type: ast.TypeString, Value: ""}, nil + return &unknownVariable, nil } values = append(values, multiAttr) diff --git a/terraform/interpolate_test.go b/terraform/interpolate_test.go index 4eaf882bc7ca..9613fc776d75 100644 --- a/terraform/interpolate_test.go +++ b/terraform/interpolate_test.go @@ -364,6 +364,55 @@ func TestInterpolater_resourceVariableMulti(t *testing.T) { }) } +// When a splat reference is made to an attribute that is a computed list, +// the result should be unknown. +func TestInterpolater_resourceVariableMultiList(t *testing.T) { + lock := new(sync.RWMutex) + state := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: map[string]*ResourceState{ + "aws_instance.web.0": &ResourceState{ + Type: "aws_instance", + Primary: &InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "ip.#": config.UnknownVariableValue, + }, + }, + }, + + "aws_instance.web.1": &ResourceState{ + Type: "aws_instance", + Primary: &InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "ip.#": "0", + }, + }, + }, + }, + }, + }, + } + + i := &Interpolater{ + Module: testModule(t, "interpolate-resource-variable"), + State: state, + StateLock: lock, + } + + scope := &InterpolationScope{ + Path: rootModulePath, + } + + testInterpolate(t, i, scope, "aws_instance.web.*.ip", ast.Variable{ + Value: config.UnknownVariableValue, + Type: ast.TypeUnknown, + }) +} + func TestInterpolater_resourceVariableMulti_interpolated(t *testing.T) { lock := new(sync.RWMutex) state := &State{ diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index 40e4935acbf7..023da95b170c 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -943,6 +943,24 @@ STATE: ` +const testTerraformPlanComputedMultiIndexStr = ` +DIFF: + +CREATE: aws_instance.bar + foo: "" => "" + type: "" => "aws_instance" +CREATE: aws_instance.foo.0 + ip.#: "" => "" + type: "" => "aws_instance" +CREATE: aws_instance.foo.1 + ip.#: "" => "" + type: "" => "aws_instance" + +STATE: + + +` + const testTerraformPlanCountStr = ` DIFF: diff --git a/terraform/test-fixtures/plan-computed-multi-index/main.tf b/terraform/test-fixtures/plan-computed-multi-index/main.tf new file mode 100644 index 000000000000..2d8a799d0587 --- /dev/null +++ b/terraform/test-fixtures/plan-computed-multi-index/main.tf @@ -0,0 +1,9 @@ +resource "aws_instance" "foo" { + count = 2 + compute = "ip.#" +} + +resource "aws_instance" "bar" { + count = 1 + foo = "${aws_instance.foo.*.ip[count.index]}" +}