github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/states/state_deepcopy.go (about) 1 package states 2 3 import ( 4 "github.com/hashicorp/terraform/addrs" 5 "github.com/zclconf/go-cty/cty" 6 ) 7 8 // Taking deep copies of states is an important operation because state is 9 // otherwise a mutable data structure that is challenging to share across 10 // many separate callers. It is important that the DeepCopy implementations 11 // in this file comprehensively copy all parts of the state data structure 12 // that could be mutated via pointers. 13 14 // DeepCopy returns a new state that contains equivalent data to the reciever 15 // but shares no backing memory in common. 16 // 17 // As with all methods on State, this method is not safe to use concurrently 18 // with writing to any portion of the recieving data structure. It is the 19 // caller's responsibility to ensure mutual exclusion for the duration of the 20 // operation, but may then freely modify the receiver and the returned copy 21 // independently once this method returns. 22 func (s *State) DeepCopy() *State { 23 if s == nil { 24 return nil 25 } 26 27 modules := make(map[string]*Module, len(s.Modules)) 28 for k, m := range s.Modules { 29 modules[k] = m.DeepCopy() 30 } 31 return &State{ 32 Modules: modules, 33 } 34 } 35 36 // DeepCopy returns a new module state that contains equivalent data to the 37 // receiver but shares no backing memory in common. 38 // 39 // As with all methods on Module, this method is not safe to use concurrently 40 // with writing to any portion of the recieving data structure. It is the 41 // caller's responsibility to ensure mutual exclusion for the duration of the 42 // operation, but may then freely modify the receiver and the returned copy 43 // independently once this method returns. 44 func (ms *Module) DeepCopy() *Module { 45 if ms == nil { 46 return nil 47 } 48 49 resources := make(map[string]*Resource, len(ms.Resources)) 50 for k, r := range ms.Resources { 51 resources[k] = r.DeepCopy() 52 } 53 outputValues := make(map[string]*OutputValue, len(ms.OutputValues)) 54 for k, v := range ms.OutputValues { 55 outputValues[k] = v.DeepCopy() 56 } 57 localValues := make(map[string]cty.Value, len(ms.LocalValues)) 58 for k, v := range ms.LocalValues { 59 // cty.Value is immutable, so we don't need to copy these. 60 localValues[k] = v 61 } 62 63 return &Module{ 64 Addr: ms.Addr, // technically mutable, but immutable by convention 65 Resources: resources, 66 OutputValues: outputValues, 67 LocalValues: localValues, 68 } 69 } 70 71 // DeepCopy returns a new resource state that contains equivalent data to the 72 // receiver but shares no backing memory in common. 73 // 74 // As with all methods on Resource, this method is not safe to use concurrently 75 // with writing to any portion of the recieving data structure. It is the 76 // caller's responsibility to ensure mutual exclusion for the duration of the 77 // operation, but may then freely modify the receiver and the returned copy 78 // independently once this method returns. 79 func (rs *Resource) DeepCopy() *Resource { 80 if rs == nil { 81 return nil 82 } 83 84 instances := make(map[addrs.InstanceKey]*ResourceInstance, len(rs.Instances)) 85 for k, i := range rs.Instances { 86 instances[k] = i.DeepCopy() 87 } 88 89 return &Resource{ 90 Addr: rs.Addr, 91 EachMode: rs.EachMode, 92 Instances: instances, 93 ProviderConfig: rs.ProviderConfig, // technically mutable, but immutable by convention 94 } 95 } 96 97 // DeepCopy returns a new resource instance state that contains equivalent data 98 // to the receiver but shares no backing memory in common. 99 // 100 // As with all methods on ResourceInstance, this method is not safe to use 101 // concurrently with writing to any portion of the recieving data structure. It 102 // is the caller's responsibility to ensure mutual exclusion for the duration 103 // of the operation, but may then freely modify the receiver and the returned 104 // copy independently once this method returns. 105 func (is *ResourceInstance) DeepCopy() *ResourceInstance { 106 if is == nil { 107 return nil 108 } 109 110 deposed := make(map[DeposedKey]*ResourceInstanceObjectSrc, len(is.Deposed)) 111 for k, obj := range is.Deposed { 112 deposed[k] = obj.DeepCopy() 113 } 114 115 return &ResourceInstance{ 116 Current: is.Current.DeepCopy(), 117 Deposed: deposed, 118 } 119 } 120 121 // DeepCopy returns a new resource instance object that contains equivalent data 122 // to the receiver but shares no backing memory in common. 123 // 124 // As with all methods on ResourceInstanceObjectSrc, this method is not safe to 125 // use concurrently with writing to any portion of the recieving data structure. 126 // It is the caller's responsibility to ensure mutual exclusion for the duration 127 // of the operation, but may then freely modify the receiver and the returned 128 // copy independently once this method returns. 129 func (obj *ResourceInstanceObjectSrc) DeepCopy() *ResourceInstanceObjectSrc { 130 if obj == nil { 131 return nil 132 } 133 134 var attrsFlat map[string]string 135 if obj.AttrsFlat != nil { 136 attrsFlat = make(map[string]string, len(obj.AttrsFlat)) 137 for k, v := range obj.AttrsFlat { 138 attrsFlat[k] = v 139 } 140 } 141 142 var attrsJSON []byte 143 if obj.AttrsJSON != nil { 144 attrsJSON = make([]byte, len(obj.AttrsJSON)) 145 copy(attrsJSON, obj.AttrsJSON) 146 } 147 148 var private []byte 149 if obj.Private != nil { 150 private = make([]byte, len(obj.Private)) 151 copy(private, obj.Private) 152 } 153 154 // Some addrs.Referencable implementations are technically mutable, but 155 // we treat them as immutable by convention and so we don't deep-copy here. 156 var dependencies []addrs.AbsResource 157 if obj.Dependencies != nil { 158 dependencies = make([]addrs.AbsResource, len(obj.Dependencies)) 159 copy(dependencies, obj.Dependencies) 160 } 161 162 var dependsOn []addrs.Referenceable 163 if obj.DependsOn != nil { 164 dependsOn = make([]addrs.Referenceable, len(obj.DependsOn)) 165 copy(dependsOn, obj.DependsOn) 166 } 167 168 return &ResourceInstanceObjectSrc{ 169 Status: obj.Status, 170 SchemaVersion: obj.SchemaVersion, 171 Private: private, 172 AttrsFlat: attrsFlat, 173 AttrsJSON: attrsJSON, 174 Dependencies: dependencies, 175 DependsOn: dependsOn, 176 } 177 } 178 179 // DeepCopy returns a new resource instance object that contains equivalent data 180 // to the receiver but shares no backing memory in common. 181 // 182 // As with all methods on ResourceInstanceObject, this method is not safe to use 183 // concurrently with writing to any portion of the recieving data structure. It 184 // is the caller's responsibility to ensure mutual exclusion for the duration 185 // of the operation, but may then freely modify the receiver and the returned 186 // copy independently once this method returns. 187 func (obj *ResourceInstanceObject) DeepCopy() *ResourceInstanceObject { 188 if obj == nil { 189 return nil 190 } 191 192 var private []byte 193 if obj.Private != nil { 194 private = make([]byte, len(obj.Private)) 195 copy(private, obj.Private) 196 } 197 198 // Some addrs.Referenceable implementations are technically mutable, but 199 // we treat them as immutable by convention and so we don't deep-copy here. 200 var dependencies []addrs.AbsResource 201 if obj.Dependencies != nil { 202 dependencies = make([]addrs.AbsResource, len(obj.Dependencies)) 203 copy(dependencies, obj.Dependencies) 204 } 205 206 return &ResourceInstanceObject{ 207 Value: obj.Value, 208 Status: obj.Status, 209 Private: private, 210 Dependencies: dependencies, 211 } 212 } 213 214 // DeepCopy returns a new output value state that contains equivalent data 215 // to the receiver but shares no backing memory in common. 216 // 217 // As with all methods on OutputValue, this method is not safe to use 218 // concurrently with writing to any portion of the recieving data structure. It 219 // is the caller's responsibility to ensure mutual exclusion for the duration 220 // of the operation, but may then freely modify the receiver and the returned 221 // copy independently once this method returns. 222 func (os *OutputValue) DeepCopy() *OutputValue { 223 if os == nil { 224 return nil 225 } 226 227 return &OutputValue{ 228 Value: os.Value, 229 Sensitive: os.Sensitive, 230 } 231 }