kubeform.dev/terraform-backend-sdk@v0.0.0-20220310143633-45f07fe731c5/states/state_deepcopy.go (about)

     1  package states
     2  
     3  import (
     4  	"kubeform.dev/terraform-backend-sdk/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  		Instances:      instances,
    92  		ProviderConfig: rs.ProviderConfig, // technically mutable, but immutable by convention
    93  	}
    94  }
    95  
    96  // DeepCopy returns a new resource instance state that contains equivalent data
    97  // to the receiver but shares no backing memory in common.
    98  //
    99  // As with all methods on ResourceInstance, this method is not safe to use
   100  // concurrently with writing to any portion of the recieving data structure. It
   101  // is the caller's responsibility to ensure mutual exclusion for the duration
   102  // of the operation, but may then freely modify the receiver and the returned
   103  // copy independently once this method returns.
   104  func (i *ResourceInstance) DeepCopy() *ResourceInstance {
   105  	if i == nil {
   106  		return nil
   107  	}
   108  
   109  	deposed := make(map[DeposedKey]*ResourceInstanceObjectSrc, len(i.Deposed))
   110  	for k, obj := range i.Deposed {
   111  		deposed[k] = obj.DeepCopy()
   112  	}
   113  
   114  	return &ResourceInstance{
   115  		Current: i.Current.DeepCopy(),
   116  		Deposed: deposed,
   117  	}
   118  }
   119  
   120  // DeepCopy returns a new resource instance object that contains equivalent data
   121  // to the receiver but shares no backing memory in common.
   122  //
   123  // As with all methods on ResourceInstanceObjectSrc, this method is not safe to
   124  // use concurrently with writing to any portion of the recieving data structure.
   125  // It is the caller's responsibility to ensure mutual exclusion for the duration
   126  // of the operation, but may then freely modify the receiver and the returned
   127  // copy independently once this method returns.
   128  func (os *ResourceInstanceObjectSrc) DeepCopy() *ResourceInstanceObjectSrc {
   129  	if os == nil {
   130  		return nil
   131  	}
   132  
   133  	var attrsFlat map[string]string
   134  	if os.AttrsFlat != nil {
   135  		attrsFlat = make(map[string]string, len(os.AttrsFlat))
   136  		for k, v := range os.AttrsFlat {
   137  			attrsFlat[k] = v
   138  		}
   139  	}
   140  
   141  	var attrsJSON []byte
   142  	if os.AttrsJSON != nil {
   143  		attrsJSON = make([]byte, len(os.AttrsJSON))
   144  		copy(attrsJSON, os.AttrsJSON)
   145  	}
   146  
   147  	var attrPaths []cty.PathValueMarks
   148  	if os.AttrSensitivePaths != nil {
   149  		attrPaths = make([]cty.PathValueMarks, len(os.AttrSensitivePaths))
   150  		copy(attrPaths, os.AttrSensitivePaths)
   151  	}
   152  
   153  	var private []byte
   154  	if os.Private != nil {
   155  		private = make([]byte, len(os.Private))
   156  		copy(private, os.Private)
   157  	}
   158  
   159  	// Some addrs.Referencable implementations are technically mutable, but
   160  	// we treat them as immutable by convention and so we don't deep-copy here.
   161  	var dependencies []addrs.ConfigResource
   162  	if os.Dependencies != nil {
   163  		dependencies = make([]addrs.ConfigResource, len(os.Dependencies))
   164  		copy(dependencies, os.Dependencies)
   165  	}
   166  
   167  	return &ResourceInstanceObjectSrc{
   168  		Status:              os.Status,
   169  		SchemaVersion:       os.SchemaVersion,
   170  		Private:             private,
   171  		AttrsFlat:           attrsFlat,
   172  		AttrsJSON:           attrsJSON,
   173  		AttrSensitivePaths:  attrPaths,
   174  		Dependencies:        dependencies,
   175  		CreateBeforeDestroy: os.CreateBeforeDestroy,
   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 (o *ResourceInstanceObject) DeepCopy() *ResourceInstanceObject {
   188  	if o == nil {
   189  		return nil
   190  	}
   191  
   192  	var private []byte
   193  	if o.Private != nil {
   194  		private = make([]byte, len(o.Private))
   195  		copy(private, o.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.ConfigResource
   201  	if o.Dependencies != nil {
   202  		dependencies = make([]addrs.ConfigResource, len(o.Dependencies))
   203  		copy(dependencies, o.Dependencies)
   204  	}
   205  
   206  	return &ResourceInstanceObject{
   207  		Value:               o.Value,
   208  		Status:              o.Status,
   209  		Private:             private,
   210  		Dependencies:        dependencies,
   211  		CreateBeforeDestroy: o.CreateBeforeDestroy,
   212  	}
   213  }
   214  
   215  // DeepCopy returns a new output value state that contains equivalent data
   216  // to the receiver but shares no backing memory in common.
   217  //
   218  // As with all methods on OutputValue, this method is not safe to use
   219  // concurrently with writing to any portion of the recieving data structure. It
   220  // is the caller's responsibility to ensure mutual exclusion for the duration
   221  // of the operation, but may then freely modify the receiver and the returned
   222  // copy independently once this method returns.
   223  func (os *OutputValue) DeepCopy() *OutputValue {
   224  	if os == nil {
   225  		return nil
   226  	}
   227  
   228  	return &OutputValue{
   229  		Addr:      os.Addr,
   230  		Value:     os.Value,
   231  		Sensitive: os.Sensitive,
   232  	}
   233  }