github.com/opentofu/opentofu@v1.7.1/internal/tofu/transform_attach_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/dag" 12 "github.com/opentofu/opentofu/internal/states" 13 ) 14 15 // GraphNodeAttachResourceState is an interface that can be implemented 16 // to request that a ResourceState is attached to the node. 17 // 18 // Due to a historical naming inconsistency, the type ResourceState actually 19 // represents the state for a particular _instance_, while InstanceState 20 // represents the values for that instance during a particular phase 21 // (e.g. primary vs. deposed). Consequently, GraphNodeAttachResourceState 22 // is supported only for nodes that represent resource instances, even though 23 // the name might suggest it is for containing resources. 24 type GraphNodeAttachResourceState interface { 25 GraphNodeResourceInstance 26 27 // Sets the state 28 AttachResourceState(*states.Resource) 29 } 30 31 // AttachStateTransformer goes through the graph and attaches 32 // state to nodes that implement the interfaces above. 33 type AttachStateTransformer struct { 34 State *states.State // State is the root state 35 } 36 37 func (t *AttachStateTransformer) Transform(g *Graph) error { 38 // If no state, then nothing to do 39 if t.State == nil { 40 log.Printf("[DEBUG] Not attaching any node states: overall state is nil") 41 return nil 42 } 43 44 for _, v := range g.Vertices() { 45 // Nodes implement this interface to request state attachment. 46 an, ok := v.(GraphNodeAttachResourceState) 47 if !ok { 48 continue 49 } 50 addr := an.ResourceInstanceAddr() 51 52 rs := t.State.Resource(addr.ContainingResource()) 53 if rs == nil { 54 log.Printf("[DEBUG] Resource state not found for node %q, instance %s", dag.VertexName(v), addr) 55 continue 56 } 57 58 is := rs.Instance(addr.Resource.Key) 59 if is == nil { 60 // We don't actually need this here, since we'll attach the whole 61 // resource state, but we still check because it'd be weird 62 // for the specific instance we're attaching to not to exist. 63 log.Printf("[DEBUG] Resource instance state not found for node %q, instance %s", dag.VertexName(v), addr) 64 continue 65 } 66 67 // make sure to attach a copy of the state, so instances can modify the 68 // same ResourceState. 69 an.AttachResourceState(rs.DeepCopy()) 70 } 71 72 return nil 73 }