github.com/pulumi/terraform@v1.4.0/pkg/plans/changes_src.go (about)

     1  package plans
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/pulumi/terraform/pkg/addrs"
     7  	"github.com/pulumi/terraform/pkg/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 ResourceInstanceChange.
    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  	// PrevRunAddr is the absolute address that this resource instance had at
    20  	// the conclusion of a previous run.
    21  	//
    22  	// This will typically be the same as Addr, but can be different if the
    23  	// previous resource instance was subject to a "moved" block that we
    24  	// handled in the process of creating this plan.
    25  	//
    26  	// For the initial creation of a resource instance there isn't really any
    27  	// meaningful "previous run address", but PrevRunAddr will still be set
    28  	// equal to Addr in that case in order to simplify logic elsewhere which
    29  	// aims to detect and react to the movement of instances between addresses.
    30  	PrevRunAddr addrs.AbsResourceInstance
    31  
    32  	// DeposedKey is the identifier for a deposed object associated with the
    33  	// given instance, or states.NotDeposed if this change applies to the
    34  	// current object.
    35  	//
    36  	// A Replace change for a resource with create_before_destroy set will
    37  	// create a new DeposedKey temporarily during replacement. In that case,
    38  	// DeposedKey in the plan is always states.NotDeposed, representing that
    39  	// the current object is being replaced with the deposed.
    40  	DeposedKey states.DeposedKey
    41  
    42  	// Provider is the address of the provider configuration that was used
    43  	// to plan this change, and thus the configuration that must also be
    44  	// used to apply it.
    45  	ProviderAddr addrs.AbsProviderConfig
    46  
    47  	// ChangeSrc is an embedded description of the not-yet-decoded change.
    48  	ChangeSrc
    49  
    50  	// ActionReason is an optional extra indication of why we chose the
    51  	// action recorded in Change.Action for this particular resource instance.
    52  	//
    53  	// This is an approximate mechanism only for the purpose of explaining the
    54  	// plan to end-users in the UI and is not to be used for any
    55  	// decision-making during the apply step; if apply behavior needs to vary
    56  	// depending on the "action reason" then the information for that decision
    57  	// must be recorded more precisely elsewhere for that purpose.
    58  	//
    59  	// See the field of the same name in ResourceInstanceChange for more
    60  	// details.
    61  	ActionReason ResourceInstanceChangeActionReason
    62  
    63  	// RequiredReplace is a set of paths that caused the change action to be
    64  	// Replace rather than Update. Always nil if the change action is not
    65  	// Replace.
    66  	RequiredReplace cty.PathSet
    67  
    68  	// Private allows a provider to stash any extra data that is opaque to
    69  	// Terraform that relates to this change. Terraform will save this
    70  	// byte-for-byte and return it to the provider in the apply call.
    71  	Private []byte
    72  }
    73  
    74  // Decode unmarshals the raw representation of the instance object being
    75  // changed. Pass the implied type of the corresponding resource type schema
    76  // for correct operation.
    77  func (rcs *ResourceInstanceChangeSrc) Decode(ty cty.Type) (*ResourceInstanceChange, error) {
    78  	change, err := rcs.ChangeSrc.Decode(ty)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	prevRunAddr := rcs.PrevRunAddr
    83  	if prevRunAddr.Resource.Resource.Type == "" {
    84  		// Suggests an old caller that hasn't been properly updated to
    85  		// populate this yet.
    86  		prevRunAddr = rcs.Addr
    87  	}
    88  	return &ResourceInstanceChange{
    89  		Addr:            rcs.Addr,
    90  		PrevRunAddr:     prevRunAddr,
    91  		DeposedKey:      rcs.DeposedKey,
    92  		ProviderAddr:    rcs.ProviderAddr,
    93  		Change:          *change,
    94  		ActionReason:    rcs.ActionReason,
    95  		RequiredReplace: rcs.RequiredReplace,
    96  		Private:         rcs.Private,
    97  	}, nil
    98  }
    99  
   100  // DeepCopy creates a copy of the receiver where any pointers to nested mutable
   101  // values are also copied, thus ensuring that future mutations of the receiver
   102  // will not affect the copy.
   103  //
   104  // Some types used within a resource change are immutable by convention even
   105  // though the Go language allows them to be mutated, such as the types from
   106  // the addrs package. These are _not_ copied by this method, under the
   107  // assumption that callers will behave themselves.
   108  func (rcs *ResourceInstanceChangeSrc) DeepCopy() *ResourceInstanceChangeSrc {
   109  	if rcs == nil {
   110  		return nil
   111  	}
   112  	ret := *rcs
   113  
   114  	ret.RequiredReplace = cty.NewPathSet(ret.RequiredReplace.List()...)
   115  
   116  	if len(ret.Private) != 0 {
   117  		private := make([]byte, len(ret.Private))
   118  		copy(private, ret.Private)
   119  		ret.Private = private
   120  	}
   121  
   122  	ret.ChangeSrc.Before = ret.ChangeSrc.Before.Copy()
   123  	ret.ChangeSrc.After = ret.ChangeSrc.After.Copy()
   124  
   125  	return &ret
   126  }
   127  
   128  func (rcs *ResourceInstanceChangeSrc) Moved() bool {
   129  	return !rcs.Addr.Equal(rcs.PrevRunAddr)
   130  }
   131  
   132  // OutputChangeSrc describes a change to an output value.
   133  type OutputChangeSrc struct {
   134  	// Addr is the absolute address of the output value that the change
   135  	// will apply to.
   136  	Addr addrs.AbsOutputValue
   137  
   138  	// ChangeSrc is an embedded description of the not-yet-decoded change.
   139  	//
   140  	// For output value changes, the type constraint for the DynamicValue
   141  	// instances is always cty.DynamicPseudoType.
   142  	ChangeSrc
   143  
   144  	// Sensitive, if true, indicates that either the old or new value in the
   145  	// change is sensitive and so a rendered version of the plan in the UI
   146  	// should elide the actual values while still indicating the action of the
   147  	// change.
   148  	Sensitive bool
   149  }
   150  
   151  // Decode unmarshals the raw representation of the output value being
   152  // changed.
   153  func (ocs *OutputChangeSrc) Decode() (*OutputChange, error) {
   154  	change, err := ocs.ChangeSrc.Decode(cty.DynamicPseudoType)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	return &OutputChange{
   159  		Addr:      ocs.Addr,
   160  		Change:    *change,
   161  		Sensitive: ocs.Sensitive,
   162  	}, nil
   163  }
   164  
   165  // DeepCopy creates a copy of the receiver where any pointers to nested mutable
   166  // values are also copied, thus ensuring that future mutations of the receiver
   167  // will not affect the copy.
   168  //
   169  // Some types used within a resource change are immutable by convention even
   170  // though the Go language allows them to be mutated, such as the types from
   171  // the addrs package. These are _not_ copied by this method, under the
   172  // assumption that callers will behave themselves.
   173  func (ocs *OutputChangeSrc) DeepCopy() *OutputChangeSrc {
   174  	if ocs == nil {
   175  		return nil
   176  	}
   177  	ret := *ocs
   178  
   179  	ret.ChangeSrc.Before = ret.ChangeSrc.Before.Copy()
   180  	ret.ChangeSrc.After = ret.ChangeSrc.After.Copy()
   181  
   182  	return &ret
   183  }
   184  
   185  // ChangeSrc is a not-yet-decoded Change.
   186  type ChangeSrc struct {
   187  	// Action defines what kind of change is being made.
   188  	Action Action
   189  
   190  	// Before and After correspond to the fields of the same name in Change,
   191  	// but have not yet been decoded from the serialized value used for
   192  	// storage.
   193  	Before, After DynamicValue
   194  
   195  	// BeforeValMarks and AfterValMarks are stored path+mark combinations
   196  	// that might be discovered when encoding a change. Marks are removed
   197  	// to enable encoding (marked values cannot be marshalled), and so storing
   198  	// the path+mark combinations allow us to re-mark the value later
   199  	// when, for example, displaying the diff to the UI.
   200  	BeforeValMarks, AfterValMarks []cty.PathValueMarks
   201  }
   202  
   203  // Decode unmarshals the raw representations of the before and after values
   204  // to produce a Change object. Pass the type constraint that the result must
   205  // conform to.
   206  //
   207  // Where a ChangeSrc is embedded in some other struct, it's generally better
   208  // to call the corresponding Decode method of that struct rather than working
   209  // directly with its embedded Change.
   210  func (cs *ChangeSrc) Decode(ty cty.Type) (*Change, error) {
   211  	var err error
   212  	before := cty.NullVal(ty)
   213  	after := cty.NullVal(ty)
   214  
   215  	if len(cs.Before) > 0 {
   216  		before, err = cs.Before.Decode(ty)
   217  		if err != nil {
   218  			return nil, fmt.Errorf("error decoding 'before' value: %s", err)
   219  		}
   220  	}
   221  	if len(cs.After) > 0 {
   222  		after, err = cs.After.Decode(ty)
   223  		if err != nil {
   224  			return nil, fmt.Errorf("error decoding 'after' value: %s", err)
   225  		}
   226  	}
   227  
   228  	return &Change{
   229  		Action: cs.Action,
   230  		Before: before.MarkWithPaths(cs.BeforeValMarks),
   231  		After:  after.MarkWithPaths(cs.AfterValMarks),
   232  	}, nil
   233  }