From d1cf0279fafe7791f6cf149045c0dc9ca9e1aa62 Mon Sep 17 00:00:00 2001 From: Kristin Laemmert Date: Fri, 25 Sep 2020 11:18:14 -0400 Subject: [PATCH] terraform: NodePlannableResourceInstanceOrphan refactor --- terraform/node_resource_plan_orphan.go | 111 +++++++++++--------- terraform/node_resource_plan_orphan_test.go | 64 +++++++++++ 2 files changed, 126 insertions(+), 49 deletions(-) create mode 100644 terraform/node_resource_plan_orphan_test.go diff --git a/terraform/node_resource_plan_orphan.go b/terraform/node_resource_plan_orphan.go index 20ad53c35e..bbff235a5c 100644 --- a/terraform/node_resource_plan_orphan.go +++ b/terraform/node_resource_plan_orphan.go @@ -2,7 +2,6 @@ package terraform import ( "github.com/hashicorp/terraform/plans" - "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" ) @@ -20,65 +19,79 @@ var ( _ GraphNodeResourceInstance = (*NodePlannableResourceInstanceOrphan)(nil) _ GraphNodeAttachResourceConfig = (*NodePlannableResourceInstanceOrphan)(nil) _ GraphNodeAttachResourceState = (*NodePlannableResourceInstanceOrphan)(nil) - _ GraphNodeEvalable = (*NodePlannableResourceInstanceOrphan)(nil) -) - -var ( - _ GraphNodeEvalable = (*NodePlannableResourceInstanceOrphan)(nil) + _ GraphNodeExecutable = (*NodePlannableResourceInstanceOrphan)(nil) ) func (n *NodePlannableResourceInstanceOrphan) Name() string { return n.ResourceInstanceAddr().String() + " (orphan)" } -// GraphNodeEvalable -func (n *NodePlannableResourceInstanceOrphan) EvalTree() EvalNode { +// GraphNodeExecutable +func (n *NodePlannableResourceInstanceOrphan) Execute(ctx EvalContext, op walkOperation) error { addr := n.ResourceInstanceAddr() // Declare a bunch of variables that are used for state during - // evaluation. Most of this are written to by-address below. + // evaluation. These are written to by-address below. var change *plans.ResourceInstanceChange var state *states.ResourceInstanceObject - var provider providers.Interface - var providerSchema *ProviderSchema - return &EvalSequence{ - Nodes: []EvalNode{ - &EvalGetProvider{ - Addr: n.ResolvedProvider, - Output: &provider, - Schema: &providerSchema, - }, - &EvalReadState{ - Addr: addr.Resource, - Provider: &provider, - ProviderSchema: &providerSchema, - - Output: &state, - }, - &EvalDiffDestroy{ - Addr: addr.Resource, - State: &state, - ProviderAddr: n.ResolvedProvider, - Output: &change, - OutputState: &state, // Will point to a nil state after this complete, signalling destroyed - }, - &EvalCheckPreventDestroy{ - Addr: addr.Resource, - Config: n.Config, - Change: &change, - }, - &EvalWriteDiff{ - Addr: addr.Resource, - ProviderSchema: &providerSchema, - Change: &change, - }, - &EvalWriteState{ - Addr: addr.Resource, - ProviderAddr: n.ResolvedProvider, - ProviderSchema: &providerSchema, - State: &state, - }, - }, + provider, providerSchema, err := GetProvider(ctx, n.ResolvedProvider) + if err != nil { + return err } + + //EvalReadState + readState := &EvalReadState{ + Addr: addr.Resource, + Provider: &provider, + ProviderSchema: &providerSchema, + Output: &state, + } + _, err = readState.Eval(ctx) + if err != nil { + return err + } + + diffDestroy := &EvalDiffDestroy{ + Addr: addr.Resource, + State: &state, + ProviderAddr: n.ResolvedProvider, + Output: &change, + OutputState: &state, // Will point to a nil state after this complete, signalling destroyed + } + _, err = diffDestroy.Eval(ctx) + if err != nil { + return err + } + + checkPreventDestroy := &EvalCheckPreventDestroy{ + Addr: addr.Resource, + Config: n.Config, + Change: &change, + } + _, err = checkPreventDestroy.Eval(ctx) + if err != nil { + return err + } + + writeDiff := &EvalWriteDiff{ + Addr: addr.Resource, + ProviderSchema: &providerSchema, + Change: &change, + } + _, err = writeDiff.Eval(ctx) + if err != nil { + return err + } + writeState := &EvalWriteState{ + Addr: addr.Resource, + ProviderAddr: n.ResolvedProvider, + ProviderSchema: &providerSchema, + State: &state, + } + _, err = writeState.Eval(ctx) + if err != nil { + return err + } + return nil } diff --git a/terraform/node_resource_plan_orphan_test.go b/terraform/node_resource_plan_orphan_test.go new file mode 100644 index 0000000000..45078cd436 --- /dev/null +++ b/terraform/node_resource_plan_orphan_test.go @@ -0,0 +1,64 @@ +package terraform + +import ( + "testing" + + "github.com/hashicorp/terraform/addrs" + "github.com/hashicorp/terraform/configs/configschema" + "github.com/hashicorp/terraform/instances" + "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/states" +) + +func TestNodeResourcePlanOrphanExecute(t *testing.T) { + state := states.NewState() + state.Module(addrs.RootModuleInstance).SetResourceInstanceCurrent( + addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_object", + Name: "foo", + }.Instance(addrs.NoKey), + &states.ResourceInstanceObjectSrc{ + AttrsFlat: map[string]string{ + "test_string": "foo", + }, + Status: states.ObjectReady, + }, + addrs.AbsProviderConfig{ + Provider: addrs.NewDefaultProvider("test"), + Module: addrs.RootModule, + }, + ) + + p := simpleMockProvider() + ctx := &MockEvalContext{ + StateState: state.SyncWrapper(), + InstanceExpanderExpander: instances.NewExpander(), + ProviderProvider: p, + ProviderSchemaSchema: &ProviderSchema{ + ResourceTypes: map[string]*configschema.Block{ + "test_object": simpleTestSchema(), + }, + }, + ChangesChanges: plans.NewChanges().SyncWrapper(), + } + + node := NodePlannableResourceInstanceOrphan{ + NodeAbstractResourceInstance: &NodeAbstractResourceInstance{ + NodeAbstractResource: NodeAbstractResource{ + ResolvedProvider: addrs.AbsProviderConfig{ + Provider: addrs.NewDefaultProvider("test"), + Module: addrs.RootModule, + }, + }, + Addr: mustResourceInstanceAddr("test_object.foo"), + }, + } + err := node.Execute(ctx, walkApply) + if err != nil { + t.Fatalf("unexpected error: %s", err.Error()) + } + if !state.Empty() { + t.Fatalf("expected empty state, got %s", state.String()) + } +}