github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/plans/changes_src.go (about)

     1  package plans
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/hashicorp/terraform-plugin-sdk/internal/addrs"
     7  	"github.com/hashicorp/terraform-plugin-sdk/internal/states"
     8  	"github.com/zclconf/go-cty/cty"
     9  )
    10  
    11  // ResourceInstanceChangeSrc is a not-yet-decoded ResourceInstanceChange.
    12  // Pass the associated resource type's schema type to method Decode to
    13  // obtain a ResourceInstancChange.
    14  type ResourceInstanceChangeSrc struct {
    15  	// Addr is the absolute address of the resource instance that the change
    16  	// will apply to.
    17  	Addr addrs.AbsResourceInstance
    18  
    19  	// DeposedKey is the identifier for a deposed object associated with the
    20  	// given instance, or states.NotDeposed if this change applies to the
    21  	// current object.
    22  	//
    23  	// A Replace change for a resource with create_before_destroy set will
    24  	// create a new DeposedKey temporarily during replacement. In that case,
    25  	// DeposedKey in the plan is always states.NotDeposed, representing that
    26  	// the current object is being replaced with the deposed.
    27  	DeposedKey states.DeposedKey
    28  
    29  	// Provider is the address of the provider configuration that was used
    30  	// to plan this change, and thus the configuration that must also be
    31  	// used to apply it.
    32  	ProviderAddr addrs.AbsProviderConfig
    33  
    34  	// ChangeSrc is an embedded description of the not-yet-decoded change.
    35  	ChangeSrc
    36  
    37  	// RequiredReplace is a set of paths that caused the change action to be
    38  	// Replace rather than Update. Always nil if the change action is not
    39  	// Replace.
    40  	//
    41  	// This is retained only for UI-plan-rendering purposes and so it does not
    42  	// currently survive a round-trip through a saved plan file.
    43  	RequiredReplace cty.PathSet
    44  
    45  	// Private allows a provider to stash any extra data that is opaque to
    46  	// Terraform that relates to this change. Terraform will save this
    47  	// byte-for-byte and return it to the provider in the apply call.
    48  	Private []byte
    49  }
    50  
    51  // Decode unmarshals the raw representation of the instance object being
    52  // changed. Pass the implied type of the corresponding resource type schema
    53  // for correct operation.
    54  func (rcs *ResourceInstanceChangeSrc) Decode(ty cty.Type) (*ResourceInstanceChange, error) {
    55  	change, err := rcs.ChangeSrc.Decode(ty)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	return &ResourceInstanceChange{
    60  		Addr:            rcs.Addr,
    61  		DeposedKey:      rcs.DeposedKey,
    62  		ProviderAddr:    rcs.ProviderAddr,
    63  		Change:          *change,
    64  		RequiredReplace: rcs.RequiredReplace,
    65  		Private:         rcs.Private,
    66  	}, nil
    67  }
    68  
    69  // DeepCopy creates a copy of the receiver where any pointers to nested mutable
    70  // values are also copied, thus ensuring that future mutations of the receiver
    71  // will not affect the copy.
    72  //
    73  // Some types used within a resource change are immutable by convention even
    74  // though the Go language allows them to be mutated, such as the types from
    75  // the addrs package. These are _not_ copied by this method, under the
    76  // assumption that callers will behave themselves.
    77  func (rcs *ResourceInstanceChangeSrc) DeepCopy() *ResourceInstanceChangeSrc {
    78  	if rcs == nil {
    79  		return nil
    80  	}
    81  	ret := *rcs
    82  
    83  	ret.RequiredReplace = cty.NewPathSet(ret.RequiredReplace.List()...)
    84  
    85  	if len(ret.Private) != 0 {
    86  		private := make([]byte, len(ret.Private))
    87  		copy(private, ret.Private)
    88  		ret.Private = private
    89  	}
    90  
    91  	ret.ChangeSrc.Before = ret.ChangeSrc.Before.Copy()
    92  	ret.ChangeSrc.After = ret.ChangeSrc.After.Copy()
    93  
    94  	return &ret
    95  }
    96  
    97  // OutputChangeSrc describes a change to an output value.
    98  type OutputChangeSrc struct {
    99  	// Addr is the absolute address of the output value that the change
   100  	// will apply to.
   101  	Addr addrs.AbsOutputValue
   102  
   103  	// ChangeSrc is an embedded description of the not-yet-decoded change.
   104  	//
   105  	// For output value changes, the type constraint for the DynamicValue
   106  	// instances is always cty.DynamicPseudoType.
   107  	ChangeSrc
   108  
   109  	// Sensitive, if true, indicates that either the old or new value in the
   110  	// change is sensitive and so a rendered version of the plan in the UI
   111  	// should elide the actual values while still indicating the action of the
   112  	// change.
   113  	Sensitive bool
   114  }
   115  
   116  // Decode unmarshals the raw representation of the output value being
   117  // changed.
   118  func (ocs *OutputChangeSrc) Decode() (*OutputChange, error) {
   119  	change, err := ocs.ChangeSrc.Decode(cty.DynamicPseudoType)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	return &OutputChange{
   124  		Addr:      ocs.Addr,
   125  		Change:    *change,
   126  		Sensitive: ocs.Sensitive,
   127  	}, nil
   128  }
   129  
   130  // DeepCopy creates a copy of the receiver where any pointers to nested mutable
   131  // values are also copied, thus ensuring that future mutations of the receiver
   132  // will not affect the copy.
   133  //
   134  // Some types used within a resource change are immutable by convention even
   135  // though the Go language allows them to be mutated, such as the types from
   136  // the addrs package. These are _not_ copied by this method, under the
   137  // assumption that callers will behave themselves.
   138  func (ocs *OutputChangeSrc) DeepCopy() *OutputChangeSrc {
   139  	if ocs == nil {
   140  		return nil
   141  	}
   142  	ret := *ocs
   143  
   144  	ret.ChangeSrc.Before = ret.ChangeSrc.Before.Copy()
   145  	ret.ChangeSrc.After = ret.ChangeSrc.After.Copy()
   146  
   147  	return &ret
   148  }
   149  
   150  // ChangeSrc is a not-yet-decoded Change.
   151  type ChangeSrc struct {
   152  	// Action defines what kind of change is being made.
   153  	Action Action
   154  
   155  	// Before and After correspond to the fields of the same name in Change,
   156  	// but have not yet been decoded from the serialized value used for
   157  	// storage.
   158  	Before, After DynamicValue
   159  }
   160  
   161  // Decode unmarshals the raw representations of the before and after values
   162  // to produce a Change object. Pass the type constraint that the result must
   163  // conform to.
   164  //
   165  // Where a ChangeSrc is embedded in some other struct, it's generally better
   166  // to call the corresponding Decode method of that struct rather than working
   167  // directly with its embedded Change.
   168  func (cs *ChangeSrc) Decode(ty cty.Type) (*Change, error) {
   169  	var err error
   170  	before := cty.NullVal(ty)
   171  	after := cty.NullVal(ty)
   172  
   173  	if len(cs.Before) > 0 {
   174  		before, err = cs.Before.Decode(ty)
   175  		if err != nil {
   176  			return nil, fmt.Errorf("error decoding 'before' value: %s", err)
   177  		}
   178  	}
   179  	if len(cs.After) > 0 {
   180  		after, err = cs.After.Decode(ty)
   181  		if err != nil {
   182  			return nil, fmt.Errorf("error decoding 'after' value: %s", err)
   183  		}
   184  	}
   185  	return &Change{
   186  		Action: cs.Action,
   187  		Before: before,
   188  		After:  after,
   189  	}, nil
   190  }