github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/states/state_deepcopy.go (about) 1 package states 2 3 import ( 4 "github.com/hashicorp/terraform/internal/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 CheckResults: s.CheckResults.DeepCopy(), 34 } 35 } 36 37 // DeepCopy returns a new module state that contains equivalent data to the 38 // receiver but shares no backing memory in common. 39 // 40 // As with all methods on Module, this method is not safe to use concurrently 41 // with writing to any portion of the recieving data structure. It is the 42 // caller's responsibility to ensure mutual exclusion for the duration of the 43 // operation, but may then freely modify the receiver and the returned copy 44 // independently once this method returns. 45 func (ms *Module) DeepCopy() *Module { 46 if ms == nil { 47 return nil 48 } 49 50 resources := make(map[string]*Resource, len(ms.Resources)) 51 for k, r := range ms.Resources { 52 resources[k] = r.DeepCopy() 53 } 54 outputValues := make(map[string]*OutputValue, len(ms.OutputValues)) 55 for k, v := range ms.OutputValues { 56 outputValues[k] = v.DeepCopy() 57 } 58 localValues := make(map[string]cty.Value, len(ms.LocalValues)) 59 for k, v := range ms.LocalValues { 60 // cty.Value is immutable, so we don't need to copy these. 61 localValues[k] = v 62 } 63 64 return &Module{ 65 Addr: ms.Addr, // technically mutable, but immutable by convention 66 Resources: resources, 67 OutputValues: outputValues, 68 LocalValues: localValues, 69 } 70 } 71 72 // DeepCopy returns a new resource state that contains equivalent data to the 73 // receiver but shares no backing memory in common. 74 // 75 // As with all methods on Resource, this method is not safe to use concurrently 76 // with writing to any portion of the recieving data structure. It is the 77 // caller's responsibility to ensure mutual exclusion for the duration of the 78 // operation, but may then freely modify the receiver and the returned copy 79 // independently once this method returns. 80 func (rs *Resource) DeepCopy() *Resource { 81 if rs == nil { 82 return nil 83 } 84 85 instances := make(map[addrs.InstanceKey]*ResourceInstance, len(rs.Instances)) 86 for k, i := range rs.Instances { 87 instances[k] = i.DeepCopy() 88 } 89 90 return &Resource{ 91 Addr: rs.Addr, 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 (i *ResourceInstance) DeepCopy() *ResourceInstance { 106 if i == nil { 107 return nil 108 } 109 110 deposed := make(map[DeposedKey]*ResourceInstanceObjectSrc, len(i.Deposed)) 111 for k, obj := range i.Deposed { 112 deposed[k] = obj.DeepCopy() 113 } 114 115 return &ResourceInstance{ 116 Current: i.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 (os *ResourceInstanceObjectSrc) DeepCopy() *ResourceInstanceObjectSrc { 130 if os == nil { 131 return nil 132 } 133 134 var attrsFlat map[string]string 135 if os.AttrsFlat != nil { 136 attrsFlat = make(map[string]string, len(os.AttrsFlat)) 137 for k, v := range os.AttrsFlat { 138 attrsFlat[k] = v 139 } 140 } 141 142 var attrsJSON []byte 143 if os.AttrsJSON != nil { 144 attrsJSON = make([]byte, len(os.AttrsJSON)) 145 copy(attrsJSON, os.AttrsJSON) 146 } 147 148 var attrPaths []cty.PathValueMarks 149 if os.AttrSensitivePaths != nil { 150 attrPaths = make([]cty.PathValueMarks, len(os.AttrSensitivePaths)) 151 copy(attrPaths, os.AttrSensitivePaths) 152 } 153 154 var private []byte 155 if os.Private != nil { 156 private = make([]byte, len(os.Private)) 157 copy(private, os.Private) 158 } 159 160 // Some addrs.Referencable implementations are technically mutable, but 161 // we treat them as immutable by convention and so we don't deep-copy here. 162 var dependencies []addrs.ConfigResource 163 if os.Dependencies != nil { 164 dependencies = make([]addrs.ConfigResource, len(os.Dependencies)) 165 copy(dependencies, os.Dependencies) 166 } 167 168 return &ResourceInstanceObjectSrc{ 169 Status: os.Status, 170 SchemaVersion: os.SchemaVersion, 171 Private: private, 172 AttrsFlat: attrsFlat, 173 AttrsJSON: attrsJSON, 174 AttrSensitivePaths: attrPaths, 175 Dependencies: dependencies, 176 CreateBeforeDestroy: os.CreateBeforeDestroy, 177 } 178 } 179 180 // DeepCopy returns a new resource instance object that contains equivalent data 181 // to the receiver but shares no backing memory in common. 182 // 183 // As with all methods on ResourceInstanceObject, this method is not safe to use 184 // concurrently with writing to any portion of the recieving data structure. It 185 // is the caller's responsibility to ensure mutual exclusion for the duration 186 // of the operation, but may then freely modify the receiver and the returned 187 // copy independently once this method returns. 188 func (o *ResourceInstanceObject) DeepCopy() *ResourceInstanceObject { 189 if o == nil { 190 return nil 191 } 192 193 var private []byte 194 if o.Private != nil { 195 private = make([]byte, len(o.Private)) 196 copy(private, o.Private) 197 } 198 199 // Some addrs.Referenceable implementations are technically mutable, but 200 // we treat them as immutable by convention and so we don't deep-copy here. 201 var dependencies []addrs.ConfigResource 202 if o.Dependencies != nil { 203 dependencies = make([]addrs.ConfigResource, len(o.Dependencies)) 204 copy(dependencies, o.Dependencies) 205 } 206 207 return &ResourceInstanceObject{ 208 Value: o.Value, 209 Status: o.Status, 210 Private: private, 211 Dependencies: dependencies, 212 CreateBeforeDestroy: o.CreateBeforeDestroy, 213 } 214 } 215 216 // DeepCopy returns a new output value state that contains equivalent data 217 // to the receiver but shares no backing memory in common. 218 // 219 // As with all methods on OutputValue, this method is not safe to use 220 // concurrently with writing to any portion of the recieving data structure. It 221 // is the caller's responsibility to ensure mutual exclusion for the duration 222 // of the operation, but may then freely modify the receiver and the returned 223 // copy independently once this method returns. 224 func (os *OutputValue) DeepCopy() *OutputValue { 225 if os == nil { 226 return nil 227 } 228 229 return &OutputValue{ 230 Addr: os.Addr, 231 Value: os.Value, 232 Sensitive: os.Sensitive, 233 } 234 }