From f1a292652dd437a5bf1561324f77e0b832d973ea Mon Sep 17 00:00:00 2001 From: Alisdair McDiarmid Date: Tue, 16 Feb 2021 15:32:36 -0500 Subject: [PATCH] terraform: Fix missing deposed key for PreApply The PreApply hook was always being called with a nil generation argument, instead of the deposed key of the resource (if present). This commit passes the deposed key from the change to the PreApply hook, and adds a context test to cover this. --- terraform/context_apply2_test.go | 70 ++++++++++++++++++++ terraform/node_resource_abstract_instance.go | 2 +- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/terraform/context_apply2_test.go b/terraform/context_apply2_test.go index cc3ee2f47..a9e816fc4 100644 --- a/terraform/context_apply2_test.go +++ b/terraform/context_apply2_test.go @@ -1 +1,71 @@ package terraform + +import ( + "testing" + + "github.com/hashicorp/terraform/addrs" + "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/states" +) + +// Test that the PreApply hook is called with the correct deposed key +func TestContext2Apply_createBeforeDestroy_deposedKeyPreApply(t *testing.T) { + m := testModule(t, "apply-cbd-deposed-only") + p := testProvider("aws") + p.PlanResourceChangeFn = testDiffFn + p.ApplyResourceChangeFn = testApplyFn + + deposedKey := states.NewDeposedKey() + + state := states.NewState() + root := state.EnsureModule(addrs.RootModuleInstance) + root.SetResourceInstanceCurrent( + mustResourceInstanceAddr("aws_instance.bar").Resource, + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectReady, + AttrsJSON: []byte(`{"id":"bar"}`), + }, + mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`), + ) + root.SetResourceInstanceDeposed( + mustResourceInstanceAddr("aws_instance.bar").Resource, + deposedKey, + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectTainted, + AttrsJSON: []byte(`{"id":"foo"}`), + }, + mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`), + ) + + hook := new(MockHook) + ctx := testContext2(t, &ContextOpts{ + Config: m, + Hooks: []Hook{hook}, + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), + }, + State: state, + }) + + if p, diags := ctx.Plan(); diags.HasErrors() { + t.Fatalf("diags: %s", diags.Err()) + } else { + t.Logf(legacyDiffComparisonString(p.Changes)) + } + + state, diags := ctx.Apply() + if diags.HasErrors() { + t.Fatalf("diags: %s", diags.Err()) + } + + // Verify PreApply was called correctly + if !hook.PreApplyCalled { + t.Fatalf("PreApply hook not called") + } + if addr, wantAddr := hook.PreApplyAddr, mustResourceInstanceAddr("aws_instance.bar"); !addr.Equal(wantAddr) { + t.Errorf("expected addr to be %s, but was %s", wantAddr, addr) + } + if gen := hook.PreApplyGen; gen != deposedKey { + t.Errorf("expected gen to be %q, but was %q", deposedKey, gen) + } +} diff --git a/terraform/node_resource_abstract_instance.go b/terraform/node_resource_abstract_instance.go index 5bc1a4468..9a5892a92 100644 --- a/terraform/node_resource_abstract_instance.go +++ b/terraform/node_resource_abstract_instance.go @@ -221,7 +221,7 @@ func (n *NodeAbstractResourceInstance) preApplyHook(ctx EvalContext, change *pla plannedNewState := change.After diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) { - return h.PreApply(n.Addr, nil, change.Action, priorState, plannedNewState) + return h.PreApply(n.Addr, change.DeposedKey.Generation(), change.Action, priorState, plannedNewState) })) if diags.HasErrors() { return diags