diff --git a/terraform/context_test.go b/terraform/context_test.go index 0e076cd79..46c41d0ae 100644 --- a/terraform/context_test.go +++ b/terraform/context_test.go @@ -3766,6 +3766,52 @@ func TestContext2Apply_provisionerResourceRef(t *testing.T) { } } +func TestContext2Apply_provisionerSelfRef(t *testing.T) { + m := testModule(t, "apply-provisioner-self-ref") + p := testProvider("aws") + pr := testProvisioner() + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { + val, ok := c.Config["command"] + if !ok || val != "bar" { + t.Fatalf("bad value for command: %v %#v", val, c) + } + + return nil + } + + ctx := testContext2(t, &ContextOpts{ + Module: m, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + Provisioners: map[string]ResourceProvisionerFactory{ + "shell": testProvisionerFuncFixed(pr), + }, + }) + + if _, err := ctx.Plan(nil); err != nil { + t.Fatalf("err: %s", err) + } + + state, err := ctx.Apply() + if err != nil { + t.Fatalf("err: %s", err) + } + + actual := strings.TrimSpace(state.String()) + expected := strings.TrimSpace(testTerraformApplyProvisionerSelfRefStr) + if actual != expected { + t.Fatalf("bad: \n%s", actual) + } + + // Verify apply was invoked + if !pr.ApplyCalled { + t.Fatalf("provisioner not invoked") + } +} + // Provisioner should NOT run on a diff, only create func TestContext2Apply_Provisioner_Diff(t *testing.T) { m := testModule(t, "apply-provisioner-diff") diff --git a/terraform/interpolate.go b/terraform/interpolate.go index 2d5798aa0..cf88ad825 100644 --- a/terraform/interpolate.go +++ b/terraform/interpolate.go @@ -62,6 +62,8 @@ func (i *Interpolater) Values( err = i.valuePathVar(scope, n, v, result) case *config.ResourceVariable: err = i.valueResourceVar(scope, n, v, result) + case *config.SelfVariable: + err = i.valueSelfVar(scope, n, v, result) case *config.UserVariable: err = i.valueUserVar(scope, n, v, result) default: @@ -217,6 +219,24 @@ func (i *Interpolater) valueResourceVar( return nil } +func (i *Interpolater) valueSelfVar( + scope *InterpolationScope, + n string, + v *config.SelfVariable, + result map[string]ast.Variable) error { + rv, err := config.NewResourceVariable(fmt.Sprintf( + "%s.%s.%d.%s", + scope.Resource.Type, + scope.Resource.Name, + scope.Resource.CountIndex, + v.Field)) + if err != nil { + return err + } + + return i.valueResourceVar(scope, n, rv, result) +} + func (i *Interpolater) valueUserVar( scope *InterpolationScope, n string, diff --git a/terraform/resource.go b/terraform/resource.go index 7775ab789..9dacbc7c5 100644 --- a/terraform/resource.go +++ b/terraform/resource.go @@ -26,6 +26,13 @@ type ResourceProvisionerConfig struct { // its current state, and potentially a desired diff from the state it // wants to reach. type Resource struct { + // These are all used by the new EvalNode stuff. + Name string + Type string + CountIndex int + + // These aren't really used anymore anywhere, but we keep them around + // since we haven't done a proper cleanup yet. Id string Info *InstanceInfo Config *ResourceConfig @@ -34,7 +41,6 @@ type Resource struct { Provider ResourceProvider State *InstanceState Provisioners []*ResourceProvisionerConfig - CountIndex int Flags ResourceFlag TaintedIndex int } diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index 75f65c36e..397a23b5e 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -359,6 +359,13 @@ aws_instance.bar: type = aws_instance ` +const testTerraformApplyProvisionerSelfRefStr = ` +aws_instance.foo: + ID = foo + foo = bar + type = aws_instance +` + const testTerraformApplyProvisionerDiffStr = ` aws_instance.bar: ID = foo diff --git a/terraform/test-fixtures/apply-provisioner-self-ref/main.tf b/terraform/test-fixtures/apply-provisioner-self-ref/main.tf new file mode 100644 index 000000000..5f401f7c0 --- /dev/null +++ b/terraform/test-fixtures/apply-provisioner-self-ref/main.tf @@ -0,0 +1,7 @@ +resource "aws_instance" "foo" { + foo = "bar" + + provisioner "shell" { + command = "${self.foo}" + } +} diff --git a/terraform/transform_resource.go b/terraform/transform_resource.go index 8c9c16a15..0ce4f4cd7 100644 --- a/terraform/transform_resource.go +++ b/terraform/transform_resource.go @@ -109,7 +109,11 @@ func (n *graphNodeExpandedResource) EvalTree() EvalNode { if index < 0 { index = 0 } - resource := &Resource{CountIndex: index} + resource := &Resource{ + Name: n.Resource.Name, + Type: n.Resource.Type, + CountIndex: index, + } seq := &EvalSequence{Nodes: make([]EvalNode, 0, 5)}