github.com/iaas-resource-provision/iaas-rpc@v1.0.7-0.20211021023331-ed21f798c408/internal/plans/changes_src.go (about)

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