github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/terraform/node_resource_plan_destroy.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform/internal/addrs" 7 "github.com/hashicorp/terraform/internal/plans" 8 "github.com/hashicorp/terraform/internal/states" 9 "github.com/hashicorp/terraform/internal/tfdiags" 10 "github.com/zclconf/go-cty/cty" 11 ) 12 13 // NodePlanDestroyableResourceInstance represents a resource that is ready 14 // to be planned for destruction. 15 type NodePlanDestroyableResourceInstance struct { 16 *NodeAbstractResourceInstance 17 18 // skipRefresh indicates that we should skip refreshing 19 skipRefresh bool 20 } 21 22 var ( 23 _ GraphNodeModuleInstance = (*NodePlanDestroyableResourceInstance)(nil) 24 _ GraphNodeReferenceable = (*NodePlanDestroyableResourceInstance)(nil) 25 _ GraphNodeReferencer = (*NodePlanDestroyableResourceInstance)(nil) 26 _ GraphNodeDestroyer = (*NodePlanDestroyableResourceInstance)(nil) 27 _ GraphNodeConfigResource = (*NodePlanDestroyableResourceInstance)(nil) 28 _ GraphNodeResourceInstance = (*NodePlanDestroyableResourceInstance)(nil) 29 _ GraphNodeAttachResourceConfig = (*NodePlanDestroyableResourceInstance)(nil) 30 _ GraphNodeAttachResourceState = (*NodePlanDestroyableResourceInstance)(nil) 31 _ GraphNodeExecutable = (*NodePlanDestroyableResourceInstance)(nil) 32 _ GraphNodeProviderConsumer = (*NodePlanDestroyableResourceInstance)(nil) 33 ) 34 35 // GraphNodeDestroyer 36 func (n *NodePlanDestroyableResourceInstance) DestroyAddr() *addrs.AbsResourceInstance { 37 addr := n.ResourceInstanceAddr() 38 return &addr 39 } 40 41 // GraphNodeEvalable 42 func (n *NodePlanDestroyableResourceInstance) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) { 43 addr := n.ResourceInstanceAddr() 44 45 switch addr.Resource.Resource.Mode { 46 case addrs.ManagedResourceMode: 47 return n.managedResourceExecute(ctx, op) 48 case addrs.DataResourceMode: 49 return n.dataResourceExecute(ctx, op) 50 default: 51 panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode)) 52 } 53 } 54 55 func (n *NodePlanDestroyableResourceInstance) managedResourceExecute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) { 56 addr := n.ResourceInstanceAddr() 57 58 // Declare a bunch of variables that are used for state during 59 // evaluation. These are written to by address in the EvalNodes we 60 // declare below. 61 var change *plans.ResourceInstanceChange 62 var state *states.ResourceInstanceObject 63 64 state, err := n.readResourceInstanceState(ctx, addr) 65 diags = diags.Append(err) 66 if diags.HasErrors() { 67 return diags 68 } 69 70 // If we are in the "skip refresh" mode then we will have skipped over our 71 // usual opportunity to update the previous run state and refresh state 72 // with the result of any provider schema upgrades, so we'll compensate 73 // by doing that here. 74 // 75 // NOTE: this is coupled with logic in Context.destroyPlan which skips 76 // running a normal plan walk when refresh is enabled. These two 77 // conditionals must agree (be exactly opposite) in order to get the 78 // correct behavior in both cases. 79 if n.skipRefresh { 80 diags = diags.Append(n.writeResourceInstanceState(ctx, state, prevRunState)) 81 if diags.HasErrors() { 82 return diags 83 } 84 diags = diags.Append(n.writeResourceInstanceState(ctx, state, refreshState)) 85 if diags.HasErrors() { 86 return diags 87 } 88 } 89 90 change, destroyPlanDiags := n.planDestroy(ctx, state, "") 91 diags = diags.Append(destroyPlanDiags) 92 if diags.HasErrors() { 93 return diags 94 } 95 96 diags = diags.Append(n.checkPreventDestroy(change)) 97 if diags.HasErrors() { 98 return diags 99 } 100 101 diags = diags.Append(n.writeChange(ctx, change, "")) 102 return diags 103 } 104 105 func (n *NodePlanDestroyableResourceInstance) dataResourceExecute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) { 106 107 // We may not be able to read a prior data source from the state if the 108 // schema was upgraded and we are destroying before ever refreshing that 109 // data source. Regardless, a data source "destroy" is simply writing a 110 // null state, which we can do with a null prior state too. 111 change := &plans.ResourceInstanceChange{ 112 Addr: n.ResourceInstanceAddr(), 113 PrevRunAddr: n.prevRunAddr(ctx), 114 Change: plans.Change{ 115 Action: plans.Delete, 116 Before: cty.NullVal(cty.DynamicPseudoType), 117 After: cty.NullVal(cty.DynamicPseudoType), 118 }, 119 ProviderAddr: n.ResolvedProvider, 120 } 121 return diags.Append(n.writeChange(ctx, change, "")) 122 }