diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/plans/changes.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/plans/changes.go | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/plans/changes.go b/vendor/github.com/hashicorp/terraform/plans/changes.go new file mode 100644 index 0000000..d7e0dcd --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/plans/changes.go | |||
@@ -0,0 +1,308 @@ | |||
1 | package plans | ||
2 | |||
3 | import ( | ||
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. | ||
14 | type 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. | ||
30 | func NewChanges() *Changes { | ||
31 | return &Changes{} | ||
32 | } | ||
33 | |||
34 | func (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. | ||
46 | func (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. | ||
60 | func (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. | ||
73 | func (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. | ||
87 | func (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. | ||
95 | type 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. | ||
135 | func (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. | ||
167 | func (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. | ||
231 | type 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. | ||
251 | func (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. | ||
264 | type 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. | ||
293 | func (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 | } | ||