mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-23 07:33:32 -06:00
fd775f0fe3
Signed-off-by: ollevche <ollevche@gmail.com> Signed-off-by: Christian Mesh <christianmesh1@gmail.com> Signed-off-by: Ronny Orot <ronny.orot@gmail.com> Signed-off-by: Martin Atkins <mart@degeneration.co.uk> Co-authored-by: ollevche <ollevche@gmail.com> Co-authored-by: Ronny Orot <ronny.orot@gmail.com> Co-authored-by: Martin Atkins <mart@degeneration.co.uk>
241 lines
7.9 KiB
Go
241 lines
7.9 KiB
Go
// Copyright (c) The OpenTofu Authors
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package states
|
|
|
|
import (
|
|
"github.com/opentofu/opentofu/internal/addrs"
|
|
"github.com/zclconf/go-cty/cty"
|
|
)
|
|
|
|
// Taking deep copies of states is an important operation because state is
|
|
// otherwise a mutable data structure that is challenging to share across
|
|
// many separate callers. It is important that the DeepCopy implementations
|
|
// in this file comprehensively copy all parts of the state data structure
|
|
// that could be mutated via pointers.
|
|
|
|
// DeepCopy returns a new state that contains equivalent data to the receiver
|
|
// but shares no backing memory in common.
|
|
//
|
|
// As with all methods on State, this method is not safe to use concurrently
|
|
// with writing to any portion of the receiving data structure. It is the
|
|
// caller's responsibility to ensure mutual exclusion for the duration of the
|
|
// operation, but may then freely modify the receiver and the returned copy
|
|
// independently once this method returns.
|
|
func (s *State) DeepCopy() *State {
|
|
if s == nil {
|
|
return nil
|
|
}
|
|
|
|
modules := make(map[string]*Module, len(s.Modules))
|
|
for k, m := range s.Modules {
|
|
modules[k] = m.DeepCopy()
|
|
}
|
|
return &State{
|
|
Modules: modules,
|
|
CheckResults: s.CheckResults.DeepCopy(),
|
|
}
|
|
}
|
|
|
|
// DeepCopy returns a new module state that contains equivalent data to the
|
|
// receiver but shares no backing memory in common.
|
|
//
|
|
// As with all methods on Module, this method is not safe to use concurrently
|
|
// with writing to any portion of the receiving data structure. It is the
|
|
// caller's responsibility to ensure mutual exclusion for the duration of the
|
|
// operation, but may then freely modify the receiver and the returned copy
|
|
// independently once this method returns.
|
|
func (ms *Module) DeepCopy() *Module {
|
|
if ms == nil {
|
|
return nil
|
|
}
|
|
|
|
resources := make(map[string]*Resource, len(ms.Resources))
|
|
for k, r := range ms.Resources {
|
|
resources[k] = r.DeepCopy()
|
|
}
|
|
outputValues := make(map[string]*OutputValue, len(ms.OutputValues))
|
|
for k, v := range ms.OutputValues {
|
|
outputValues[k] = v.DeepCopy()
|
|
}
|
|
localValues := make(map[string]cty.Value, len(ms.LocalValues))
|
|
for k, v := range ms.LocalValues {
|
|
// cty.Value is immutable, so we don't need to copy these.
|
|
localValues[k] = v
|
|
}
|
|
|
|
return &Module{
|
|
Addr: ms.Addr, // technically mutable, but immutable by convention
|
|
Resources: resources,
|
|
OutputValues: outputValues,
|
|
LocalValues: localValues,
|
|
}
|
|
}
|
|
|
|
// DeepCopy returns a new resource state that contains equivalent data to the
|
|
// receiver but shares no backing memory in common.
|
|
//
|
|
// As with all methods on Resource, this method is not safe to use concurrently
|
|
// with writing to any portion of the receiving data structure. It is the
|
|
// caller's responsibility to ensure mutual exclusion for the duration of the
|
|
// operation, but may then freely modify the receiver and the returned copy
|
|
// independently once this method returns.
|
|
func (rs *Resource) DeepCopy() *Resource {
|
|
if rs == nil {
|
|
return nil
|
|
}
|
|
|
|
instances := make(map[addrs.InstanceKey]*ResourceInstance, len(rs.Instances))
|
|
for k, i := range rs.Instances {
|
|
instances[k] = i.DeepCopy()
|
|
}
|
|
|
|
return &Resource{
|
|
Addr: rs.Addr,
|
|
Instances: instances,
|
|
ProviderConfig: rs.ProviderConfig, // technically mutable, but immutable by convention
|
|
}
|
|
}
|
|
|
|
// DeepCopy returns a new resource instance state that contains equivalent data
|
|
// to the receiver but shares no backing memory in common.
|
|
//
|
|
// As with all methods on ResourceInstance, this method is not safe to use
|
|
// concurrently with writing to any portion of the receiving data structure. It
|
|
// is the caller's responsibility to ensure mutual exclusion for the duration
|
|
// of the operation, but may then freely modify the receiver and the returned
|
|
// copy independently once this method returns.
|
|
func (i *ResourceInstance) DeepCopy() *ResourceInstance {
|
|
if i == nil {
|
|
return nil
|
|
}
|
|
|
|
deposed := make(map[DeposedKey]*ResourceInstanceObjectSrc, len(i.Deposed))
|
|
for k, obj := range i.Deposed {
|
|
deposed[k] = obj.DeepCopy()
|
|
}
|
|
|
|
return &ResourceInstance{
|
|
Current: i.Current.DeepCopy(),
|
|
Deposed: deposed,
|
|
ProviderKey: i.ProviderKey,
|
|
}
|
|
}
|
|
|
|
// DeepCopy returns a new resource instance object that contains equivalent data
|
|
// to the receiver but shares no backing memory in common.
|
|
//
|
|
// As with all methods on ResourceInstanceObjectSrc, this method is not safe to
|
|
// use concurrently with writing to any portion of the receiving data structure.
|
|
// It is the caller's responsibility to ensure mutual exclusion for the duration
|
|
// of the operation, but may then freely modify the receiver and the returned
|
|
// copy independently once this method returns.
|
|
func (os *ResourceInstanceObjectSrc) DeepCopy() *ResourceInstanceObjectSrc {
|
|
if os == nil {
|
|
return nil
|
|
}
|
|
|
|
var attrsFlat map[string]string
|
|
if os.AttrsFlat != nil {
|
|
attrsFlat = make(map[string]string, len(os.AttrsFlat))
|
|
for k, v := range os.AttrsFlat {
|
|
attrsFlat[k] = v
|
|
}
|
|
}
|
|
|
|
var attrsJSON []byte
|
|
if os.AttrsJSON != nil {
|
|
attrsJSON = make([]byte, len(os.AttrsJSON))
|
|
copy(attrsJSON, os.AttrsJSON)
|
|
}
|
|
|
|
var attrPaths []cty.PathValueMarks
|
|
if os.AttrSensitivePaths != nil {
|
|
attrPaths = make([]cty.PathValueMarks, len(os.AttrSensitivePaths))
|
|
copy(attrPaths, os.AttrSensitivePaths)
|
|
}
|
|
|
|
var private []byte
|
|
if os.Private != nil {
|
|
private = make([]byte, len(os.Private))
|
|
copy(private, os.Private)
|
|
}
|
|
|
|
// Some addrs.Referenceable implementations are technically mutable, but
|
|
// we treat them as immutable by convention and so we don't deep-copy here.
|
|
var dependencies []addrs.ConfigResource
|
|
if os.Dependencies != nil {
|
|
dependencies = make([]addrs.ConfigResource, len(os.Dependencies))
|
|
copy(dependencies, os.Dependencies)
|
|
}
|
|
|
|
return &ResourceInstanceObjectSrc{
|
|
Status: os.Status,
|
|
SchemaVersion: os.SchemaVersion,
|
|
Private: private,
|
|
AttrsFlat: attrsFlat,
|
|
AttrsJSON: attrsJSON,
|
|
AttrSensitivePaths: attrPaths,
|
|
Dependencies: dependencies,
|
|
CreateBeforeDestroy: os.CreateBeforeDestroy,
|
|
}
|
|
}
|
|
|
|
// DeepCopy returns a new resource instance object that contains equivalent data
|
|
// to the receiver but shares no backing memory in common.
|
|
//
|
|
// As with all methods on ResourceInstanceObject, this method is not safe to use
|
|
// concurrently with writing to any portion of the receiving data structure. It
|
|
// is the caller's responsibility to ensure mutual exclusion for the duration
|
|
// of the operation, but may then freely modify the receiver and the returned
|
|
// copy independently once this method returns.
|
|
func (o *ResourceInstanceObject) DeepCopy() *ResourceInstanceObject {
|
|
if o == nil {
|
|
return nil
|
|
}
|
|
|
|
var private []byte
|
|
if o.Private != nil {
|
|
private = make([]byte, len(o.Private))
|
|
copy(private, o.Private)
|
|
}
|
|
|
|
// Some addrs.Referenceable implementations are technically mutable, but
|
|
// we treat them as immutable by convention and so we don't deep-copy here.
|
|
var dependencies []addrs.ConfigResource
|
|
if o.Dependencies != nil {
|
|
dependencies = make([]addrs.ConfigResource, len(o.Dependencies))
|
|
copy(dependencies, o.Dependencies)
|
|
}
|
|
|
|
return &ResourceInstanceObject{
|
|
Value: o.Value,
|
|
Status: o.Status,
|
|
Private: private,
|
|
Dependencies: dependencies,
|
|
CreateBeforeDestroy: o.CreateBeforeDestroy,
|
|
}
|
|
}
|
|
|
|
// DeepCopy returns a new output value state that contains equivalent data
|
|
// to the receiver but shares no backing memory in common.
|
|
//
|
|
// As with all methods on OutputValue, this method is not safe to use
|
|
// concurrently with writing to any portion of the receiving data structure. It
|
|
// is the caller's responsibility to ensure mutual exclusion for the duration
|
|
// of the operation, but may then freely modify the receiver and the returned
|
|
// copy independently once this method returns.
|
|
func (os *OutputValue) DeepCopy() *OutputValue {
|
|
if os == nil {
|
|
return nil
|
|
}
|
|
|
|
return &OutputValue{
|
|
Addr: os.Addr,
|
|
Value: os.Value,
|
|
Sensitive: os.Sensitive,
|
|
}
|
|
}
|