]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/terraform/terraform/node_resource_destroy.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / node_resource_destroy.go
1 package terraform
2
3 import (
4 "fmt"
5 "log"
6
7 "github.com/hashicorp/terraform/plans"
8 "github.com/hashicorp/terraform/providers"
9
10 "github.com/hashicorp/terraform/addrs"
11 "github.com/hashicorp/terraform/configs"
12 "github.com/hashicorp/terraform/states"
13 )
14
15 // NodeDestroyResourceInstance represents a resource instance that is to be
16 // destroyed.
17 type NodeDestroyResourceInstance struct {
18 *NodeAbstractResourceInstance
19
20 // If DeposedKey is set to anything other than states.NotDeposed then
21 // this node destroys a deposed object of the associated instance
22 // rather than its current object.
23 DeposedKey states.DeposedKey
24
25 CreateBeforeDestroyOverride *bool
26 }
27
28 var (
29 _ GraphNodeResource = (*NodeDestroyResourceInstance)(nil)
30 _ GraphNodeResourceInstance = (*NodeDestroyResourceInstance)(nil)
31 _ GraphNodeDestroyer = (*NodeDestroyResourceInstance)(nil)
32 _ GraphNodeDestroyerCBD = (*NodeDestroyResourceInstance)(nil)
33 _ GraphNodeReferenceable = (*NodeDestroyResourceInstance)(nil)
34 _ GraphNodeReferencer = (*NodeDestroyResourceInstance)(nil)
35 _ GraphNodeEvalable = (*NodeDestroyResourceInstance)(nil)
36 _ GraphNodeProviderConsumer = (*NodeDestroyResourceInstance)(nil)
37 _ GraphNodeProvisionerConsumer = (*NodeDestroyResourceInstance)(nil)
38 )
39
40 func (n *NodeDestroyResourceInstance) Name() string {
41 if n.DeposedKey != states.NotDeposed {
42 return fmt.Sprintf("%s (destroy deposed %s)", n.ResourceInstanceAddr(), n.DeposedKey)
43 }
44 return n.ResourceInstanceAddr().String() + " (destroy)"
45 }
46
47 // GraphNodeDestroyer
48 func (n *NodeDestroyResourceInstance) DestroyAddr() *addrs.AbsResourceInstance {
49 addr := n.ResourceInstanceAddr()
50 return &addr
51 }
52
53 // GraphNodeDestroyerCBD
54 func (n *NodeDestroyResourceInstance) CreateBeforeDestroy() bool {
55 if n.CreateBeforeDestroyOverride != nil {
56 return *n.CreateBeforeDestroyOverride
57 }
58
59 // If we have no config, we just assume no
60 if n.Config == nil || n.Config.Managed == nil {
61 return false
62 }
63
64 return n.Config.Managed.CreateBeforeDestroy
65 }
66
67 // GraphNodeDestroyerCBD
68 func (n *NodeDestroyResourceInstance) ModifyCreateBeforeDestroy(v bool) error {
69 n.CreateBeforeDestroyOverride = &v
70 return nil
71 }
72
73 // GraphNodeReferenceable, overriding NodeAbstractResource
74 func (n *NodeDestroyResourceInstance) ReferenceableAddrs() []addrs.Referenceable {
75 normalAddrs := n.NodeAbstractResourceInstance.ReferenceableAddrs()
76 destroyAddrs := make([]addrs.Referenceable, len(normalAddrs))
77
78 phaseType := addrs.ResourceInstancePhaseDestroy
79 if n.CreateBeforeDestroy() {
80 phaseType = addrs.ResourceInstancePhaseDestroyCBD
81 }
82
83 for i, normalAddr := range normalAddrs {
84 switch ta := normalAddr.(type) {
85 case addrs.Resource:
86 destroyAddrs[i] = ta.Phase(phaseType)
87 case addrs.ResourceInstance:
88 destroyAddrs[i] = ta.Phase(phaseType)
89 default:
90 destroyAddrs[i] = normalAddr
91 }
92 }
93
94 return destroyAddrs
95 }
96
97 // GraphNodeReferencer, overriding NodeAbstractResource
98 func (n *NodeDestroyResourceInstance) References() []*addrs.Reference {
99 // If we have a config, then we need to include destroy-time dependencies
100 if c := n.Config; c != nil && c.Managed != nil {
101 var result []*addrs.Reference
102
103 // We include conn info and config for destroy time provisioners
104 // as dependencies that we have.
105 for _, p := range c.Managed.Provisioners {
106 schema := n.ProvisionerSchemas[p.Type]
107
108 if p.When == configs.ProvisionerWhenDestroy {
109 if p.Connection != nil {
110 result = append(result, ReferencesFromConfig(p.Connection.Config, connectionBlockSupersetSchema)...)
111 }
112 result = append(result, ReferencesFromConfig(p.Config, schema)...)
113 }
114 }
115
116 return result
117 }
118
119 return nil
120 }
121
122 // GraphNodeEvalable
123 func (n *NodeDestroyResourceInstance) EvalTree() EvalNode {
124 addr := n.ResourceInstanceAddr()
125
126 // Get our state
127 rs := n.ResourceState
128 var is *states.ResourceInstance
129 if rs != nil {
130 is = rs.Instance(n.InstanceKey)
131 }
132 if is == nil {
133 log.Printf("[WARN] NodeDestroyResourceInstance for %s with no state", addr)
134 }
135
136 var changeApply *plans.ResourceInstanceChange
137 var provider providers.Interface
138 var providerSchema *ProviderSchema
139 var state *states.ResourceInstanceObject
140 var err error
141 return &EvalOpFilter{
142 Ops: []walkOperation{walkApply, walkDestroy},
143 Node: &EvalSequence{
144 Nodes: []EvalNode{
145 &EvalGetProvider{
146 Addr: n.ResolvedProvider,
147 Output: &provider,
148 Schema: &providerSchema,
149 },
150
151 // Get the saved diff for apply
152 &EvalReadDiff{
153 Addr: addr.Resource,
154 ProviderSchema: &providerSchema,
155 Change: &changeApply,
156 },
157
158 &EvalReduceDiff{
159 Addr: addr.Resource,
160 InChange: &changeApply,
161 Destroy: true,
162 OutChange: &changeApply,
163 },
164
165 // EvalReduceDiff may have simplified our planned change
166 // into a NoOp if it does not require destroying.
167 &EvalIf{
168 If: func(ctx EvalContext) (bool, error) {
169 if changeApply == nil || changeApply.Action == plans.NoOp {
170 return true, EvalEarlyExitError{}
171 }
172 return true, nil
173 },
174 Then: EvalNoop{},
175 },
176
177 &EvalReadState{
178 Addr: addr.Resource,
179 Output: &state,
180 Provider: &provider,
181 ProviderSchema: &providerSchema,
182 },
183 &EvalRequireState{
184 State: &state,
185 },
186
187 // Call pre-apply hook
188 &EvalApplyPre{
189 Addr: addr.Resource,
190 State: &state,
191 Change: &changeApply,
192 },
193
194 // Run destroy provisioners if not tainted
195 &EvalIf{
196 If: func(ctx EvalContext) (bool, error) {
197 if state != nil && state.Status == states.ObjectTainted {
198 return false, nil
199 }
200
201 return true, nil
202 },
203
204 Then: &EvalApplyProvisioners{
205 Addr: addr.Resource,
206 State: &state,
207 ResourceConfig: n.Config,
208 Error: &err,
209 When: configs.ProvisionerWhenDestroy,
210 },
211 },
212
213 // If we have a provisioning error, then we just call
214 // the post-apply hook now.
215 &EvalIf{
216 If: func(ctx EvalContext) (bool, error) {
217 return err != nil, nil
218 },
219
220 Then: &EvalApplyPost{
221 Addr: addr.Resource,
222 State: &state,
223 Error: &err,
224 },
225 },
226
227 // Make sure we handle data sources properly.
228 &EvalIf{
229 If: func(ctx EvalContext) (bool, error) {
230 return addr.Resource.Resource.Mode == addrs.DataResourceMode, nil
231 },
232
233 Then: &EvalReadDataApply{
234 Addr: addr.Resource,
235 Config: n.Config,
236 Change: &changeApply,
237 Provider: &provider,
238 ProviderAddr: n.ResolvedProvider,
239 ProviderSchema: &providerSchema,
240 Output: &state,
241 },
242 Else: &EvalApply{
243 Addr: addr.Resource,
244 Config: nil, // No configuration because we are destroying
245 State: &state,
246 Change: &changeApply,
247 Provider: &provider,
248 ProviderAddr: n.ResolvedProvider,
249 ProviderSchema: &providerSchema,
250 Output: &state,
251 Error: &err,
252 },
253 },
254 &EvalWriteState{
255 Addr: addr.Resource,
256 ProviderAddr: n.ResolvedProvider,
257 ProviderSchema: &providerSchema,
258 State: &state,
259 },
260 &EvalApplyPost{
261 Addr: addr.Resource,
262 State: &state,
263 Error: &err,
264 },
265 &EvalUpdateStateHook{},
266 },
267 },
268 }
269 }
270
271 // NodeDestroyResourceInstance represents a resource that is to be destroyed.
272 //
273 // Destroying a resource is a state-only operation: it is the individual
274 // instances being destroyed that affects remote objects. During graph
275 // construction, NodeDestroyResource should always depend on any other node
276 // related to the given resource, since it's just a final cleanup to avoid
277 // leaving skeleton resource objects in state after their instances have
278 // all been destroyed.
279 type NodeDestroyResource struct {
280 *NodeAbstractResource
281 }
282
283 var (
284 _ GraphNodeResource = (*NodeDestroyResource)(nil)
285 _ GraphNodeReferenceable = (*NodeDestroyResource)(nil)
286 _ GraphNodeReferencer = (*NodeDestroyResource)(nil)
287 _ GraphNodeEvalable = (*NodeDestroyResource)(nil)
288 )
289
290 func (n *NodeDestroyResource) Name() string {
291 return n.ResourceAddr().String() + " (clean up state)"
292 }
293
294 // GraphNodeReferenceable, overriding NodeAbstractResource
295 func (n *NodeDestroyResource) ReferenceableAddrs() []addrs.Referenceable {
296 // NodeDestroyResource doesn't participate in references: the graph
297 // builder that created it should ensure directly that it already depends
298 // on every other node related to its resource, without relying on
299 // references.
300 return nil
301 }
302
303 // GraphNodeReferencer, overriding NodeAbstractResource
304 func (n *NodeDestroyResource) References() []*addrs.Reference {
305 // NodeDestroyResource doesn't participate in references: the graph
306 // builder that created it should ensure directly that it already depends
307 // on every other node related to its resource, without relying on
308 // references.
309 return nil
310 }
311
312 // GraphNodeEvalable
313 func (n *NodeDestroyResource) EvalTree() EvalNode {
314 // This EvalNode will produce an error if the resource isn't already
315 // empty by the time it is called, since it should just be pruning the
316 // leftover husk of a resource in state after all of the child instances
317 // and their objects were destroyed.
318 return &EvalForgetResourceState{
319 Addr: n.ResourceAddr().Resource,
320 }
321 }