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 }