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  }