]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/terraform/terraform/node_resource_destroy_deposed.go
Merge branch 'fix_read_test' of github.com:alexandreFre/terraform-provider-statuscake
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / node_resource_destroy_deposed.go
1 package terraform
2
3 import (
4 "fmt"
5
6 "github.com/hashicorp/terraform/addrs"
7 "github.com/hashicorp/terraform/dag"
8 "github.com/hashicorp/terraform/plans"
9 "github.com/hashicorp/terraform/providers"
10 "github.com/hashicorp/terraform/states"
11 )
12
13 // ConcreteResourceInstanceDeposedNodeFunc is a callback type used to convert
14 // an abstract resource instance to a concrete one of some type that has
15 // an associated deposed object key.
16 type ConcreteResourceInstanceDeposedNodeFunc func(*NodeAbstractResourceInstance, states.DeposedKey) dag.Vertex
17
18 type GraphNodeDeposedResourceInstanceObject interface {
19 DeposedInstanceObjectKey() states.DeposedKey
20 }
21
22 // NodePlanDeposedResourceInstanceObject represents deposed resource
23 // instance objects during plan. These are distinct from the primary object
24 // for each resource instance since the only valid operation to do with them
25 // is to destroy them.
26 //
27 // This node type is also used during the refresh walk to ensure that the
28 // record of a deposed object is up-to-date before we plan to destroy it.
29 type NodePlanDeposedResourceInstanceObject struct {
30 *NodeAbstractResourceInstance
31 DeposedKey states.DeposedKey
32 }
33
34 var (
35 _ GraphNodeDeposedResourceInstanceObject = (*NodePlanDeposedResourceInstanceObject)(nil)
36 _ GraphNodeResource = (*NodePlanDeposedResourceInstanceObject)(nil)
37 _ GraphNodeResourceInstance = (*NodePlanDeposedResourceInstanceObject)(nil)
38 _ GraphNodeReferenceable = (*NodePlanDeposedResourceInstanceObject)(nil)
39 _ GraphNodeReferencer = (*NodePlanDeposedResourceInstanceObject)(nil)
40 _ GraphNodeEvalable = (*NodePlanDeposedResourceInstanceObject)(nil)
41 _ GraphNodeProviderConsumer = (*NodePlanDeposedResourceInstanceObject)(nil)
42 _ GraphNodeProvisionerConsumer = (*NodePlanDeposedResourceInstanceObject)(nil)
43 )
44
45 func (n *NodePlanDeposedResourceInstanceObject) Name() string {
46 return fmt.Sprintf("%s (deposed %s)", n.ResourceInstanceAddr().String(), n.DeposedKey)
47 }
48
49 func (n *NodePlanDeposedResourceInstanceObject) DeposedInstanceObjectKey() states.DeposedKey {
50 return n.DeposedKey
51 }
52
53 // GraphNodeReferenceable implementation, overriding the one from NodeAbstractResourceInstance
54 func (n *NodePlanDeposedResourceInstanceObject) ReferenceableAddrs() []addrs.Referenceable {
55 // Deposed objects don't participate in references.
56 return nil
57 }
58
59 // GraphNodeReferencer implementation, overriding the one from NodeAbstractResourceInstance
60 func (n *NodePlanDeposedResourceInstanceObject) References() []*addrs.Reference {
61 // We don't evaluate configuration for deposed objects, so they effectively
62 // make no references.
63 return nil
64 }
65
66 // GraphNodeEvalable impl.
67 func (n *NodePlanDeposedResourceInstanceObject) EvalTree() EvalNode {
68 addr := n.ResourceInstanceAddr()
69
70 var provider providers.Interface
71 var providerSchema *ProviderSchema
72 var state *states.ResourceInstanceObject
73
74 seq := &EvalSequence{Nodes: make([]EvalNode, 0, 5)}
75
76 // During the refresh walk we will ensure that our record of the deposed
77 // object is up-to-date. If it was already deleted outside of Terraform
78 // then this will remove it from state and thus avoid us planning a
79 // destroy for it during the subsequent plan walk.
80 seq.Nodes = append(seq.Nodes, &EvalOpFilter{
81 Ops: []walkOperation{walkRefresh},
82 Node: &EvalSequence{
83 Nodes: []EvalNode{
84 &EvalGetProvider{
85 Addr: n.ResolvedProvider,
86 Output: &provider,
87 Schema: &providerSchema,
88 },
89 &EvalReadStateDeposed{
90 Addr: addr.Resource,
91 Provider: &provider,
92 ProviderSchema: &providerSchema,
93 Key: n.DeposedKey,
94 Output: &state,
95 },
96 &EvalRefresh{
97 Addr: addr.Resource,
98 ProviderAddr: n.ResolvedProvider,
99 Provider: &provider,
100 ProviderSchema: &providerSchema,
101 State: &state,
102 Output: &state,
103 },
104 &EvalWriteStateDeposed{
105 Addr: addr.Resource,
106 Key: n.DeposedKey,
107 ProviderAddr: n.ResolvedProvider,
108 ProviderSchema: &providerSchema,
109 State: &state,
110 },
111 },
112 },
113 })
114
115 // During the plan walk we always produce a planned destroy change, because
116 // destroying is the only supported action for deposed objects.
117 var change *plans.ResourceInstanceChange
118 seq.Nodes = append(seq.Nodes, &EvalOpFilter{
119 Ops: []walkOperation{walkPlan, walkPlanDestroy},
120 Node: &EvalSequence{
121 Nodes: []EvalNode{
122 &EvalGetProvider{
123 Addr: n.ResolvedProvider,
124 Output: &provider,
125 Schema: &providerSchema,
126 },
127 &EvalReadStateDeposed{
128 Addr: addr.Resource,
129 Output: &state,
130 Key: n.DeposedKey,
131 Provider: &provider,
132 ProviderSchema: &providerSchema,
133 },
134 &EvalDiffDestroy{
135 Addr: addr.Resource,
136 ProviderAddr: n.ResolvedProvider,
137 DeposedKey: n.DeposedKey,
138 State: &state,
139 Output: &change,
140 },
141 &EvalWriteDiff{
142 Addr: addr.Resource,
143 DeposedKey: n.DeposedKey,
144 ProviderSchema: &providerSchema,
145 Change: &change,
146 },
147 // Since deposed objects cannot be referenced by expressions
148 // elsewhere, we don't need to also record the planned new
149 // state in this case.
150 },
151 },
152 })
153
154 return seq
155 }
156
157 // NodeDestroyDeposedResourceInstanceObject represents deposed resource
158 // instance objects during apply. Nodes of this type are inserted by
159 // DiffTransformer when the planned changeset contains "delete" changes for
160 // deposed instance objects, and its only supported operation is to destroy
161 // and then forget the associated object.
162 type NodeDestroyDeposedResourceInstanceObject struct {
163 *NodeAbstractResourceInstance
164 DeposedKey states.DeposedKey
165 }
166
167 var (
168 _ GraphNodeDeposedResourceInstanceObject = (*NodeDestroyDeposedResourceInstanceObject)(nil)
169 _ GraphNodeResource = (*NodeDestroyDeposedResourceInstanceObject)(nil)
170 _ GraphNodeResourceInstance = (*NodeDestroyDeposedResourceInstanceObject)(nil)
171 _ GraphNodeDestroyer = (*NodeDestroyDeposedResourceInstanceObject)(nil)
172 _ GraphNodeDestroyerCBD = (*NodeDestroyDeposedResourceInstanceObject)(nil)
173 _ GraphNodeReferenceable = (*NodeDestroyDeposedResourceInstanceObject)(nil)
174 _ GraphNodeReferencer = (*NodeDestroyDeposedResourceInstanceObject)(nil)
175 _ GraphNodeEvalable = (*NodeDestroyDeposedResourceInstanceObject)(nil)
176 _ GraphNodeProviderConsumer = (*NodeDestroyDeposedResourceInstanceObject)(nil)
177 _ GraphNodeProvisionerConsumer = (*NodeDestroyDeposedResourceInstanceObject)(nil)
178 )
179
180 func (n *NodeDestroyDeposedResourceInstanceObject) Name() string {
181 return fmt.Sprintf("%s (destroy deposed %s)", n.Addr.String(), n.DeposedKey)
182 }
183
184 func (n *NodeDestroyDeposedResourceInstanceObject) DeposedInstanceObjectKey() states.DeposedKey {
185 return n.DeposedKey
186 }
187
188 // GraphNodeReferenceable implementation, overriding the one from NodeAbstractResourceInstance
189 func (n *NodeDestroyDeposedResourceInstanceObject) ReferenceableAddrs() []addrs.Referenceable {
190 // Deposed objects don't participate in references.
191 return nil
192 }
193
194 // GraphNodeReferencer implementation, overriding the one from NodeAbstractResourceInstance
195 func (n *NodeDestroyDeposedResourceInstanceObject) References() []*addrs.Reference {
196 // We don't evaluate configuration for deposed objects, so they effectively
197 // make no references.
198 return nil
199 }
200
201 // GraphNodeDestroyer
202 func (n *NodeDestroyDeposedResourceInstanceObject) DestroyAddr() *addrs.AbsResourceInstance {
203 addr := n.ResourceInstanceAddr()
204 return &addr
205 }
206
207 // GraphNodeDestroyerCBD
208 func (n *NodeDestroyDeposedResourceInstanceObject) CreateBeforeDestroy() bool {
209 // A deposed instance is always CreateBeforeDestroy by definition, since
210 // we use deposed only to handle create-before-destroy.
211 return true
212 }
213
214 // GraphNodeDestroyerCBD
215 func (n *NodeDestroyDeposedResourceInstanceObject) ModifyCreateBeforeDestroy(v bool) error {
216 if !v {
217 // Should never happen: deposed instances are _always_ create_before_destroy.
218 return fmt.Errorf("can't deactivate create_before_destroy for a deposed instance")
219 }
220 return nil
221 }
222
223 // GraphNodeEvalable impl.
224 func (n *NodeDestroyDeposedResourceInstanceObject) EvalTree() EvalNode {
225 addr := n.ResourceInstanceAddr()
226
227 var provider providers.Interface
228 var providerSchema *ProviderSchema
229 var state *states.ResourceInstanceObject
230 var change *plans.ResourceInstanceChange
231 var err error
232
233 return &EvalSequence{
234 Nodes: []EvalNode{
235 &EvalGetProvider{
236 Addr: n.ResolvedProvider,
237 Output: &provider,
238 Schema: &providerSchema,
239 },
240 &EvalReadStateDeposed{
241 Addr: addr.Resource,
242 Output: &state,
243 Key: n.DeposedKey,
244 Provider: &provider,
245 ProviderSchema: &providerSchema,
246 },
247 &EvalDiffDestroy{
248 Addr: addr.Resource,
249 ProviderAddr: n.ResolvedProvider,
250 State: &state,
251 Output: &change,
252 },
253 // Call pre-apply hook
254 &EvalApplyPre{
255 Addr: addr.Resource,
256 State: &state,
257 Change: &change,
258 },
259 &EvalApply{
260 Addr: addr.Resource,
261 Config: nil, // No configuration because we are destroying
262 State: &state,
263 Change: &change,
264 Provider: &provider,
265 ProviderAddr: n.ResolvedProvider,
266 ProviderSchema: &providerSchema,
267 Output: &state,
268 Error: &err,
269 },
270 // Always write the resource back to the state deposed... if it
271 // was successfully destroyed it will be pruned. If it was not, it will
272 // be caught on the next run.
273 &EvalWriteStateDeposed{
274 Addr: addr.Resource,
275 Key: n.DeposedKey,
276 ProviderAddr: n.ResolvedProvider,
277 ProviderSchema: &providerSchema,
278 State: &state,
279 },
280 &EvalApplyPost{
281 Addr: addr.Resource,
282 State: &state,
283 Error: &err,
284 },
285 &EvalReturnError{
286 Error: &err,
287 },
288 &EvalUpdateStateHook{},
289 },
290 }
291 }
292
293 // GraphNodeDeposer is an optional interface implemented by graph nodes that
294 // might create a single new deposed object for a specific associated resource
295 // instance, allowing a caller to optionally pre-allocate a DeposedKey for
296 // it.
297 type GraphNodeDeposer interface {
298 // SetPreallocatedDeposedKey will be called during graph construction
299 // if a particular node must use a pre-allocated deposed key if/when it
300 // "deposes" the current object of its associated resource instance.
301 SetPreallocatedDeposedKey(key states.DeposedKey)
302 }
303
304 // graphNodeDeposer is an embeddable implementation of GraphNodeDeposer.
305 // Embed it in a node type to get automatic support for it, and then access
306 // the field PreallocatedDeposedKey to access any pre-allocated key.
307 type graphNodeDeposer struct {
308 PreallocatedDeposedKey states.DeposedKey
309 }
310
311 func (n *graphNodeDeposer) SetPreallocatedDeposedKey(key states.DeposedKey) {
312 n.PreallocatedDeposedKey = key
313 }