github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/terraform/transform_orphan_resource.go (about)

     1  package terraform
     2  
     3  import (
     4  	"log"
     5  
     6  	"github.com/hashicorp/terraform/internal/configs"
     7  	"github.com/hashicorp/terraform/internal/dag"
     8  	"github.com/hashicorp/terraform/internal/states"
     9  )
    10  
    11  // OrphanResourceInstanceTransformer is a GraphTransformer that adds orphaned
    12  // resource instances to the graph. An "orphan" is an instance that is present
    13  // in the state but belongs to a resource that is no longer present in the
    14  // configuration.
    15  //
    16  // This is not the transformer that deals with "count orphans" (instances that
    17  // are no longer covered by a resource's "count" or "for_each" setting); that's
    18  // handled instead by OrphanResourceCountTransformer.
    19  type OrphanResourceInstanceTransformer struct {
    20  	Concrete ConcreteResourceInstanceNodeFunc
    21  
    22  	// State is the global state. We require the global state to
    23  	// properly find module orphans at our path.
    24  	State *states.State
    25  
    26  	// Config is the root node in the configuration tree. We'll look up
    27  	// the appropriate note in this tree using the path in each node.
    28  	Config *configs.Config
    29  
    30  	// Do not apply this transformer
    31  	skip bool
    32  }
    33  
    34  func (t *OrphanResourceInstanceTransformer) Transform(g *Graph) error {
    35  	if t.skip {
    36  		return nil
    37  	}
    38  
    39  	if t.State == nil {
    40  		// If the entire state is nil, there can't be any orphans
    41  		return nil
    42  	}
    43  	if t.Config == nil {
    44  		// Should never happen: we can't be doing any Terraform operations
    45  		// without at least an empty configuration.
    46  		panic("OrphanResourceInstanceTransformer used without setting Config")
    47  	}
    48  
    49  	// Go through the modules and for each module transform in order
    50  	// to add the orphan.
    51  	for _, ms := range t.State.Modules {
    52  		if err := t.transform(g, ms); err != nil {
    53  			return err
    54  		}
    55  	}
    56  
    57  	return nil
    58  }
    59  
    60  func (t *OrphanResourceInstanceTransformer) transform(g *Graph, ms *states.Module) error {
    61  	if ms == nil {
    62  		return nil
    63  	}
    64  
    65  	moduleAddr := ms.Addr
    66  
    67  	// Get the configuration for this module. The configuration might be
    68  	// nil if the module was removed from the configuration. This is okay,
    69  	// this just means that every resource is an orphan.
    70  	var m *configs.Module
    71  	if c := t.Config.DescendentForInstance(moduleAddr); c != nil {
    72  		m = c.Module
    73  	}
    74  
    75  	// An "orphan" is a resource that is in the state but not the configuration,
    76  	// so we'll walk the state resources and try to correlate each of them
    77  	// with a configuration block. Each orphan gets a node in the graph whose
    78  	// type is decided by t.Concrete.
    79  	//
    80  	// We don't handle orphans related to changes in the "count" and "for_each"
    81  	// pseudo-arguments here. They are handled by OrphanResourceCountTransformer.
    82  	for _, rs := range ms.Resources {
    83  		if m != nil {
    84  			if r := m.ResourceByAddr(rs.Addr.Resource); r != nil {
    85  				continue
    86  			}
    87  		}
    88  
    89  		for key, inst := range rs.Instances {
    90  			// deposed instances will be taken care of separately
    91  			if inst.Current == nil {
    92  				continue
    93  			}
    94  
    95  			addr := rs.Addr.Instance(key)
    96  			abstract := NewNodeAbstractResourceInstance(addr)
    97  			var node dag.Vertex = abstract
    98  			if f := t.Concrete; f != nil {
    99  				node = f(abstract)
   100  			}
   101  			log.Printf("[TRACE] OrphanResourceInstanceTransformer: adding single-instance orphan node for %s", addr)
   102  			g.Add(node)
   103  		}
   104  	}
   105  
   106  	return nil
   107  }