github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/terraform/node_resource_destroy.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/muratcelep/terraform/not-internal/plans"
     8  	"github.com/muratcelep/terraform/not-internal/tfdiags"
     9  
    10  	"github.com/muratcelep/terraform/not-internal/addrs"
    11  	"github.com/muratcelep/terraform/not-internal/configs"
    12  	"github.com/muratcelep/terraform/not-internal/states"
    13  )
    14  
    15  // NodeDestroyResourceInstance represents a resource instance that is to be
    16  // destroyed.
    17  type NodeDestroyResourceInstance struct {
    18  	*NodeAbstractResourceInstance
    19  
    20  	// If DeposedKey is set to anything other than states.NotDeposed then
    21  	// this node destroys a deposed object of the associated instance
    22  	// rather than its current object.
    23  	DeposedKey states.DeposedKey
    24  }
    25  
    26  var (
    27  	_ GraphNodeModuleInstance      = (*NodeDestroyResourceInstance)(nil)
    28  	_ GraphNodeConfigResource      = (*NodeDestroyResourceInstance)(nil)
    29  	_ GraphNodeResourceInstance    = (*NodeDestroyResourceInstance)(nil)
    30  	_ GraphNodeDestroyer           = (*NodeDestroyResourceInstance)(nil)
    31  	_ GraphNodeDestroyerCBD        = (*NodeDestroyResourceInstance)(nil)
    32  	_ GraphNodeReferenceable       = (*NodeDestroyResourceInstance)(nil)
    33  	_ GraphNodeReferencer          = (*NodeDestroyResourceInstance)(nil)
    34  	_ GraphNodeExecutable          = (*NodeDestroyResourceInstance)(nil)
    35  	_ GraphNodeProviderConsumer    = (*NodeDestroyResourceInstance)(nil)
    36  	_ GraphNodeProvisionerConsumer = (*NodeDestroyResourceInstance)(nil)
    37  )
    38  
    39  func (n *NodeDestroyResourceInstance) Name() string {
    40  	if n.DeposedKey != states.NotDeposed {
    41  		return fmt.Sprintf("%s (destroy deposed %s)", n.ResourceInstanceAddr(), n.DeposedKey)
    42  	}
    43  	return n.ResourceInstanceAddr().String() + " (destroy)"
    44  }
    45  
    46  func (n *NodeDestroyResourceInstance) ProvidedBy() (addr addrs.ProviderConfig, exact bool) {
    47  	if n.Addr.Resource.Resource.Mode == addrs.DataResourceMode {
    48  		// indicate that this node does not require a configured provider
    49  		return nil, true
    50  	}
    51  	return n.NodeAbstractResourceInstance.ProvidedBy()
    52  }
    53  
    54  // GraphNodeDestroyer
    55  func (n *NodeDestroyResourceInstance) DestroyAddr() *addrs.AbsResourceInstance {
    56  	addr := n.ResourceInstanceAddr()
    57  	return &addr
    58  }
    59  
    60  // GraphNodeDestroyerCBD
    61  func (n *NodeDestroyResourceInstance) CreateBeforeDestroy() bool {
    62  	// State takes precedence during destroy.
    63  	// If the resource was removed, there is no config to check.
    64  	// If CBD was forced from descendent, it should be saved in the state
    65  	// already.
    66  	if s := n.instanceState; s != nil {
    67  		if s.Current != nil {
    68  			return s.Current.CreateBeforeDestroy
    69  		}
    70  	}
    71  
    72  	if n.Config != nil && n.Config.Managed != nil {
    73  		return n.Config.Managed.CreateBeforeDestroy
    74  	}
    75  
    76  	return false
    77  }
    78  
    79  // GraphNodeDestroyerCBD
    80  func (n *NodeDestroyResourceInstance) ModifyCreateBeforeDestroy(v bool) error {
    81  	return nil
    82  }
    83  
    84  // GraphNodeReferenceable, overriding NodeAbstractResource
    85  func (n *NodeDestroyResourceInstance) ReferenceableAddrs() []addrs.Referenceable {
    86  	normalAddrs := n.NodeAbstractResourceInstance.ReferenceableAddrs()
    87  	destroyAddrs := make([]addrs.Referenceable, len(normalAddrs))
    88  
    89  	phaseType := addrs.ResourceInstancePhaseDestroy
    90  	if n.CreateBeforeDestroy() {
    91  		phaseType = addrs.ResourceInstancePhaseDestroyCBD
    92  	}
    93  
    94  	for i, normalAddr := range normalAddrs {
    95  		switch ta := normalAddr.(type) {
    96  		case addrs.Resource:
    97  			destroyAddrs[i] = ta.Phase(phaseType)
    98  		case addrs.ResourceInstance:
    99  			destroyAddrs[i] = ta.Phase(phaseType)
   100  		default:
   101  			destroyAddrs[i] = normalAddr
   102  		}
   103  	}
   104  
   105  	return destroyAddrs
   106  }
   107  
   108  // GraphNodeReferencer, overriding NodeAbstractResource
   109  func (n *NodeDestroyResourceInstance) References() []*addrs.Reference {
   110  	// If we have a config, then we need to include destroy-time dependencies
   111  	if c := n.Config; c != nil && c.Managed != nil {
   112  		var result []*addrs.Reference
   113  
   114  		// We include conn info and config for destroy time provisioners
   115  		// as dependencies that we have.
   116  		for _, p := range c.Managed.Provisioners {
   117  			schema := n.ProvisionerSchemas[p.Type]
   118  
   119  			if p.When == configs.ProvisionerWhenDestroy {
   120  				if p.Connection != nil {
   121  					result = append(result, ReferencesFromConfig(p.Connection.Config, connectionBlockSupersetSchema)...)
   122  				}
   123  				result = append(result, ReferencesFromConfig(p.Config, schema)...)
   124  			}
   125  		}
   126  
   127  		return result
   128  	}
   129  
   130  	return nil
   131  }
   132  
   133  // GraphNodeExecutable
   134  func (n *NodeDestroyResourceInstance) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
   135  	addr := n.ResourceInstanceAddr()
   136  
   137  	// Eval info is different depending on what kind of resource this is
   138  	switch addr.Resource.Resource.Mode {
   139  	case addrs.ManagedResourceMode:
   140  		return n.managedResourceExecute(ctx)
   141  	case addrs.DataResourceMode:
   142  		return n.dataResourceExecute(ctx)
   143  	default:
   144  		panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode))
   145  	}
   146  }
   147  
   148  func (n *NodeDestroyResourceInstance) managedResourceExecute(ctx EvalContext) (diags tfdiags.Diagnostics) {
   149  	addr := n.ResourceInstanceAddr()
   150  
   151  	// Get our state
   152  	is := n.instanceState
   153  	if is == nil {
   154  		log.Printf("[WARN] NodeDestroyResourceInstance for %s with no state", addr)
   155  	}
   156  
   157  	// These vars are updated through pointers at various stages below.
   158  	var changeApply *plans.ResourceInstanceChange
   159  	var state *states.ResourceInstanceObject
   160  
   161  	_, providerSchema, err := getProvider(ctx, n.ResolvedProvider)
   162  	diags = diags.Append(err)
   163  	if diags.HasErrors() {
   164  		return diags
   165  	}
   166  
   167  	changeApply, err = n.readDiff(ctx, providerSchema)
   168  	diags = diags.Append(err)
   169  	if changeApply == nil || diags.HasErrors() {
   170  		return diags
   171  	}
   172  
   173  	changeApply = reducePlan(addr.Resource, changeApply, true)
   174  	// reducePlan may have simplified our planned change
   175  	// into a NoOp if it does not require destroying.
   176  	if changeApply == nil || changeApply.Action == plans.NoOp {
   177  		return diags
   178  	}
   179  
   180  	state, readDiags := n.readResourceInstanceState(ctx, addr)
   181  	diags = diags.Append(readDiags)
   182  	if diags.HasErrors() {
   183  		return diags
   184  	}
   185  
   186  	// Exit early if the state object is null after reading the state
   187  	if state == nil || state.Value.IsNull() {
   188  		return diags
   189  	}
   190  
   191  	diags = diags.Append(n.preApplyHook(ctx, changeApply))
   192  	if diags.HasErrors() {
   193  		return diags
   194  	}
   195  
   196  	// Run destroy provisioners if not tainted
   197  	if state.Status != states.ObjectTainted {
   198  		applyProvisionersDiags := n.evalApplyProvisioners(ctx, state, false, configs.ProvisionerWhenDestroy)
   199  		diags = diags.Append(applyProvisionersDiags)
   200  		// keep the diags separate from the main set until we handle the cleanup
   201  
   202  		if diags.HasErrors() {
   203  			// If we have a provisioning error, then we just call
   204  			// the post-apply hook now.
   205  			diags = diags.Append(n.postApplyHook(ctx, state, diags.Err()))
   206  			return diags
   207  		}
   208  	}
   209  
   210  	// Managed resources need to be destroyed, while data sources
   211  	// are only removed from state.
   212  	// we pass a nil configuration to apply because we are destroying
   213  	s, d := n.apply(ctx, state, changeApply, nil, false)
   214  	state, diags = s, diags.Append(d)
   215  	// we don't return immediately here on error, so that the state can be
   216  	// finalized
   217  
   218  	err = n.writeResourceInstanceState(ctx, state, workingState)
   219  	if err != nil {
   220  		return diags.Append(err)
   221  	}
   222  
   223  	// create the err value for postApplyHook
   224  	diags = diags.Append(n.postApplyHook(ctx, state, diags.Err()))
   225  	diags = diags.Append(updateStateHook(ctx))
   226  	return diags
   227  }
   228  
   229  func (n *NodeDestroyResourceInstance) dataResourceExecute(ctx EvalContext) (diags tfdiags.Diagnostics) {
   230  	log.Printf("[TRACE] NodeDestroyResourceInstance: removing state object for %s", n.Addr)
   231  	ctx.State().SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider)
   232  	return diags.Append(updateStateHook(ctx))
   233  }