]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame_incremental - vendor/github.com/hashicorp/terraform/plans/changes.go
Merge branch 'fix_read_test' of github.com:alexandreFre/terraform-provider-statuscake
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / plans / changes.go
... / ...
CommitLineData
1package plans
2
3import (
4 "github.com/hashicorp/terraform/addrs"
5 "github.com/hashicorp/terraform/states"
6 "github.com/zclconf/go-cty/cty"
7)
8
9// Changes describes various actions that Terraform will attempt to take if
10// the corresponding plan is applied.
11//
12// A Changes object can be rendered into a visual diff (by the caller, using
13// code in another package) for display to the user.
14type Changes struct {
15 // Resources tracks planned changes to resource instance objects.
16 Resources []*ResourceInstanceChangeSrc
17
18 // Outputs tracks planned changes output values.
19 //
20 // Note that although an in-memory plan contains planned changes for
21 // outputs throughout the configuration, a plan serialized
22 // to disk retains only the root outputs because they are
23 // externally-visible, while other outputs are implementation details and
24 // can be easily re-calculated during the apply phase. Therefore only root
25 // module outputs will survive a round-trip through a plan file.
26 Outputs []*OutputChangeSrc
27}
28
29// NewChanges returns a valid Changes object that describes no changes.
30func NewChanges() *Changes {
31 return &Changes{}
32}
33
34func (c *Changes) Empty() bool {
35 for _, res := range c.Resources {
36 if res.Action != NoOp {
37 return false
38 }
39 }
40 return true
41}
42
43// ResourceInstance returns the planned change for the current object of the
44// resource instance of the given address, if any. Returns nil if no change is
45// planned.
46func (c *Changes) ResourceInstance(addr addrs.AbsResourceInstance) *ResourceInstanceChangeSrc {
47 addrStr := addr.String()
48 for _, rc := range c.Resources {
49 if rc.Addr.String() == addrStr && rc.DeposedKey == states.NotDeposed {
50 return rc
51 }
52 }
53
54 return nil
55}
56
57// ResourceInstanceDeposed returns the plan change of a deposed object of
58// the resource instance of the given address, if any. Returns nil if no change
59// is planned.
60func (c *Changes) ResourceInstanceDeposed(addr addrs.AbsResourceInstance, key states.DeposedKey) *ResourceInstanceChangeSrc {
61 addrStr := addr.String()
62 for _, rc := range c.Resources {
63 if rc.Addr.String() == addrStr && rc.DeposedKey == key {
64 return rc
65 }
66 }
67
68 return nil
69}
70
71// OutputValue returns the planned change for the output value with the
72// given address, if any. Returns nil if no change is planned.
73func (c *Changes) OutputValue(addr addrs.AbsOutputValue) *OutputChangeSrc {
74 addrStr := addr.String()
75 for _, oc := range c.Outputs {
76 if oc.Addr.String() == addrStr {
77 return oc
78 }
79 }
80
81 return nil
82}
83
84// SyncWrapper returns a wrapper object around the receiver that can be used
85// to make certain changes to the receiver in a concurrency-safe way, as long
86// as all callers share the same wrapper object.
87func (c *Changes) SyncWrapper() *ChangesSync {
88 return &ChangesSync{
89 changes: c,
90 }
91}
92
93// ResourceInstanceChange describes a change to a particular resource instance
94// object.
95type ResourceInstanceChange struct {
96 // Addr is the absolute address of the resource instance that the change
97 // will apply to.
98 Addr addrs.AbsResourceInstance
99
100 // DeposedKey is the identifier for a deposed object associated with the
101 // given instance, or states.NotDeposed if this change applies to the
102 // current object.
103 //
104 // A Replace change for a resource with create_before_destroy set will
105 // create a new DeposedKey temporarily during replacement. In that case,
106 // DeposedKey in the plan is always states.NotDeposed, representing that
107 // the current object is being replaced with the deposed.
108 DeposedKey states.DeposedKey
109
110 // Provider is the address of the provider configuration that was used
111 // to plan this change, and thus the configuration that must also be
112 // used to apply it.
113 ProviderAddr addrs.AbsProviderConfig
114
115 // Change is an embedded description of the change.
116 Change
117
118 // RequiredReplace is a set of paths that caused the change action to be
119 // Replace rather than Update. Always nil if the change action is not
120 // Replace.
121 //
122 // This is retained only for UI-plan-rendering purposes and so it does not
123 // currently survive a round-trip through a saved plan file.
124 RequiredReplace cty.PathSet
125
126 // Private allows a provider to stash any extra data that is opaque to
127 // Terraform that relates to this change. Terraform will save this
128 // byte-for-byte and return it to the provider in the apply call.
129 Private []byte
130}
131
132// Encode produces a variant of the reciever that has its change values
133// serialized so it can be written to a plan file. Pass the implied type of the
134// corresponding resource type schema for correct operation.
135func (rc *ResourceInstanceChange) Encode(ty cty.Type) (*ResourceInstanceChangeSrc, error) {
136 cs, err := rc.Change.Encode(ty)
137 if err != nil {
138 return nil, err
139 }
140 return &ResourceInstanceChangeSrc{
141 Addr: rc.Addr,
142 DeposedKey: rc.DeposedKey,
143 ProviderAddr: rc.ProviderAddr,
144 ChangeSrc: *cs,
145 RequiredReplace: rc.RequiredReplace,
146 Private: rc.Private,
147 }, err
148}
149
150// Simplify will, where possible, produce a change with a simpler action than
151// the receiever given a flag indicating whether the caller is dealing with
152// a normal apply or a destroy. This flag deals with the fact that Terraform
153// Core uses a specialized graph node type for destroying; only that
154// specialized node should set "destroying" to true.
155//
156// The following table shows the simplification behavior:
157//
158// Action Destroying? New Action
159// --------+-------------+-----------
160// Create true NoOp
161// Delete false NoOp
162// Replace true Delete
163// Replace false Create
164//
165// For any combination not in the above table, the Simplify just returns the
166// receiver as-is.
167func (rc *ResourceInstanceChange) Simplify(destroying bool) *ResourceInstanceChange {
168 if destroying {
169 switch rc.Action {
170 case Delete:
171 // We'll fall out and just return rc verbatim, then.
172 case CreateThenDelete, DeleteThenCreate:
173 return &ResourceInstanceChange{
174 Addr: rc.Addr,
175 DeposedKey: rc.DeposedKey,
176 Private: rc.Private,
177 ProviderAddr: rc.ProviderAddr,
178 Change: Change{
179 Action: Delete,
180 Before: rc.Before,
181 After: cty.NullVal(rc.Before.Type()),
182 },
183 }
184 default:
185 return &ResourceInstanceChange{
186 Addr: rc.Addr,
187 DeposedKey: rc.DeposedKey,
188 Private: rc.Private,
189 ProviderAddr: rc.ProviderAddr,
190 Change: Change{
191 Action: NoOp,
192 Before: rc.Before,
193 After: rc.Before,
194 },
195 }
196 }
197 } else {
198 switch rc.Action {
199 case Delete:
200 return &ResourceInstanceChange{
201 Addr: rc.Addr,
202 DeposedKey: rc.DeposedKey,
203 Private: rc.Private,
204 ProviderAddr: rc.ProviderAddr,
205 Change: Change{
206 Action: NoOp,
207 Before: rc.Before,
208 After: rc.Before,
209 },
210 }
211 case CreateThenDelete, DeleteThenCreate:
212 return &ResourceInstanceChange{
213 Addr: rc.Addr,
214 DeposedKey: rc.DeposedKey,
215 Private: rc.Private,
216 ProviderAddr: rc.ProviderAddr,
217 Change: Change{
218 Action: Create,
219 Before: cty.NullVal(rc.After.Type()),
220 After: rc.After,
221 },
222 }
223 }
224 }
225
226 // If we fall out here then our change is already simple enough.
227 return rc
228}
229
230// OutputChange describes a change to an output value.
231type OutputChange struct {
232 // Addr is the absolute address of the output value that the change
233 // will apply to.
234 Addr addrs.AbsOutputValue
235
236 // Change is an embedded description of the change.
237 //
238 // For output value changes, the type constraint for the DynamicValue
239 // instances is always cty.DynamicPseudoType.
240 Change
241
242 // Sensitive, if true, indicates that either the old or new value in the
243 // change is sensitive and so a rendered version of the plan in the UI
244 // should elide the actual values while still indicating the action of the
245 // change.
246 Sensitive bool
247}
248
249// Encode produces a variant of the reciever that has its change values
250// serialized so it can be written to a plan file.
251func (oc *OutputChange) Encode() (*OutputChangeSrc, error) {
252 cs, err := oc.Change.Encode(cty.DynamicPseudoType)
253 if err != nil {
254 return nil, err
255 }
256 return &OutputChangeSrc{
257 Addr: oc.Addr,
258 ChangeSrc: *cs,
259 Sensitive: oc.Sensitive,
260 }, err
261}
262
263// Change describes a single change with a given action.
264type Change struct {
265 // Action defines what kind of change is being made.
266 Action Action
267
268 // Interpretation of Before and After depend on Action:
269 //
270 // NoOp Before and After are the same, unchanged value
271 // Create Before is nil, and After is the expected value after create.
272 // Read Before is any prior value (nil if no prior), and After is the
273 // value that was or will be read.
274 // Update Before is the value prior to update, and After is the expected
275 // value after update.
276 // Replace As with Update.
277 // Delete Before is the value prior to delete, and After is always nil.
278 //
279 // Unknown values may appear anywhere within the Before and After values,
280 // either as the values themselves or as nested elements within known
281 // collections/structures.
282 Before, After cty.Value
283}
284
285// Encode produces a variant of the reciever that has its change values
286// serialized so it can be written to a plan file. Pass the type constraint
287// that the values are expected to conform to; to properly decode the values
288// later an identical type constraint must be provided at that time.
289//
290// Where a Change is embedded in some other struct, it's generally better
291// to call the corresponding Encode method of that struct rather than working
292// directly with its embedded Change.
293func (c *Change) Encode(ty cty.Type) (*ChangeSrc, error) {
294 beforeDV, err := NewDynamicValue(c.Before, ty)
295 if err != nil {
296 return nil, err
297 }
298 afterDV, err := NewDynamicValue(c.After, ty)
299 if err != nil {
300 return nil, err
301 }
302
303 return &ChangeSrc{
304 Action: c.Action,
305 Before: beforeDV,
306 After: afterDV,
307 }, nil
308}