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 }