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  }