github.com/opentofu/opentofu@v1.7.1/internal/tofu/transform_state.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package tofu
     7  
     8  import (
     9  	"log"
    10  
    11  	"github.com/opentofu/opentofu/internal/states"
    12  )
    13  
    14  // StateTransformer is a GraphTransformer that adds the elements of
    15  // the state to the graph.
    16  //
    17  // This transform is used for example by the DestroyPlanGraphBuilder to ensure
    18  // that only resources that are in the state are represented in the graph.
    19  type StateTransformer struct {
    20  	// ConcreteCurrent and ConcreteDeposed are used to specialize the abstract
    21  	// resource instance nodes that this transformer will create.
    22  	//
    23  	// If either of these is nil, the objects of that type will be skipped and
    24  	// not added to the graph at all. It doesn't make sense to use this
    25  	// transformer without setting at least one of these, since that would
    26  	// skip everything and thus be a no-op.
    27  	ConcreteCurrent ConcreteResourceInstanceNodeFunc
    28  	ConcreteDeposed ConcreteResourceInstanceDeposedNodeFunc
    29  
    30  	State *states.State
    31  }
    32  
    33  func (t *StateTransformer) Transform(g *Graph) error {
    34  	if t.State == nil {
    35  		log.Printf("[TRACE] StateTransformer: state is nil, so nothing to do")
    36  		return nil
    37  	}
    38  
    39  	switch {
    40  	case t.ConcreteCurrent != nil && t.ConcreteDeposed != nil:
    41  		log.Printf("[TRACE] StateTransformer: creating nodes for both current and deposed instance objects")
    42  	case t.ConcreteCurrent != nil:
    43  		log.Printf("[TRACE] StateTransformer: creating nodes for current instance objects only")
    44  	case t.ConcreteDeposed != nil:
    45  		log.Printf("[TRACE] StateTransformer: creating nodes for deposed instance objects only")
    46  	default:
    47  		log.Printf("[TRACE] StateTransformer: pointless no-op call, creating no nodes at all")
    48  	}
    49  
    50  	for _, ms := range t.State.Modules {
    51  		for _, rs := range ms.Resources {
    52  			resourceAddr := rs.Addr
    53  
    54  			for key, is := range rs.Instances {
    55  				addr := resourceAddr.Instance(key)
    56  
    57  				if obj := is.Current; obj != nil && t.ConcreteCurrent != nil {
    58  					abstract := NewNodeAbstractResourceInstance(addr)
    59  					node := t.ConcreteCurrent(abstract)
    60  					g.Add(node)
    61  					log.Printf("[TRACE] StateTransformer: added %T for %s current object", node, addr)
    62  				}
    63  
    64  				if t.ConcreteDeposed != nil {
    65  					for dk := range is.Deposed {
    66  						abstract := NewNodeAbstractResourceInstance(addr)
    67  						node := t.ConcreteDeposed(abstract, dk)
    68  						g.Add(node)
    69  						log.Printf("[TRACE] StateTransformer: added %T for %s deposed object %s", node, addr, dk)
    70  					}
    71  				}
    72  			}
    73  		}
    74  	}
    75  
    76  	return nil
    77  }