]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - 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
CommitLineData
bae9f6d2
JC
1package terraform
2
3import (
4 "fmt"
107c1cdb 5 "log"
bae9f6d2 6
107c1cdb
ND
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"
bae9f6d2
JC
13)
14
107c1cdb
ND
15// NodeDestroyResourceInstance represents a resource instance that is to be
16// destroyed.
17type 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
bae9f6d2
JC
26}
27
107c1cdb
ND
28var (
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
40func (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)"
bae9f6d2
JC
45}
46
47// GraphNodeDestroyer
107c1cdb
ND
48func (n *NodeDestroyResourceInstance) DestroyAddr() *addrs.AbsResourceInstance {
49 addr := n.ResourceInstanceAddr()
50 return &addr
bae9f6d2
JC
51}
52
53// GraphNodeDestroyerCBD
107c1cdb
ND
54func (n *NodeDestroyResourceInstance) CreateBeforeDestroy() bool {
55 if n.CreateBeforeDestroyOverride != nil {
56 return *n.CreateBeforeDestroyOverride
57 }
58
bae9f6d2 59 // If we have no config, we just assume no
107c1cdb 60 if n.Config == nil || n.Config.Managed == nil {
bae9f6d2
JC
61 return false
62 }
63
107c1cdb 64 return n.Config.Managed.CreateBeforeDestroy
bae9f6d2
JC
65}
66
67// GraphNodeDestroyerCBD
107c1cdb
ND
68func (n *NodeDestroyResourceInstance) ModifyCreateBeforeDestroy(v bool) error {
69 n.CreateBeforeDestroyOverride = &v
bae9f6d2
JC
70 return nil
71}
72
73// GraphNodeReferenceable, overriding NodeAbstractResource
107c1cdb
ND
74func (n *NodeDestroyResourceInstance) ReferenceableAddrs() []addrs.Referenceable {
75 normalAddrs := n.NodeAbstractResourceInstance.ReferenceableAddrs()
76 destroyAddrs := make([]addrs.Referenceable, len(normalAddrs))
77
78 phaseType := addrs.ResourceInstancePhaseDestroy
bae9f6d2 79 if n.CreateBeforeDestroy() {
107c1cdb 80 phaseType = addrs.ResourceInstancePhaseDestroyCBD
bae9f6d2
JC
81 }
82
107c1cdb
ND
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 }
bae9f6d2
JC
92 }
93
107c1cdb 94 return destroyAddrs
bae9f6d2
JC
95}
96
97// GraphNodeReferencer, overriding NodeAbstractResource
107c1cdb 98func (n *NodeDestroyResourceInstance) References() []*addrs.Reference {
bae9f6d2 99 // If we have a config, then we need to include destroy-time dependencies
107c1cdb
ND
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)...)
bae9f6d2
JC
113 }
114 }
115
116 return result
117 }
118
119 return nil
120}
121
bae9f6d2 122// GraphNodeEvalable
107c1cdb
ND
123func (n *NodeDestroyResourceInstance) EvalTree() EvalNode {
124 addr := n.ResourceInstanceAddr()
bae9f6d2
JC
125
126 // Get our state
127 rs := n.ResourceState
107c1cdb
ND
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)
bae9f6d2
JC
134 }
135
107c1cdb
ND
136 var changeApply *plans.ResourceInstanceChange
137 var provider providers.Interface
138 var providerSchema *ProviderSchema
139 var state *states.ResourceInstanceObject
bae9f6d2
JC
140 var err error
141 return &EvalOpFilter{
142 Ops: []walkOperation{walkApply, walkDestroy},
143 Node: &EvalSequence{
144 Nodes: []EvalNode{
107c1cdb
ND
145 &EvalGetProvider{
146 Addr: n.ResolvedProvider,
147 Output: &provider,
148 Schema: &providerSchema,
149 },
150
bae9f6d2
JC
151 // Get the saved diff for apply
152 &EvalReadDiff{
107c1cdb
ND
153 Addr: addr.Resource,
154 ProviderSchema: &providerSchema,
155 Change: &changeApply,
bae9f6d2
JC
156 },
157
107c1cdb
ND
158 &EvalReduceDiff{
159 Addr: addr.Resource,
160 InChange: &changeApply,
161 Destroy: true,
162 OutChange: &changeApply,
bae9f6d2
JC
163 },
164
107c1cdb
ND
165 // EvalReduceDiff may have simplified our planned change
166 // into a NoOp if it does not require destroying.
bae9f6d2
JC
167 &EvalIf{
168 If: func(ctx EvalContext) (bool, error) {
107c1cdb
ND
169 if changeApply == nil || changeApply.Action == plans.NoOp {
170 return true, EvalEarlyExitError{}
bae9f6d2 171 }
107c1cdb 172 return true, nil
bae9f6d2
JC
173 },
174 Then: EvalNoop{},
175 },
176
bae9f6d2 177 &EvalReadState{
107c1cdb
ND
178 Addr: addr.Resource,
179 Output: &state,
180 Provider: &provider,
181 ProviderSchema: &providerSchema,
bae9f6d2
JC
182 },
183 &EvalRequireState{
184 State: &state,
185 },
186
187 // Call pre-apply hook
188 &EvalApplyPre{
107c1cdb
ND
189 Addr: addr.Resource,
190 State: &state,
191 Change: &changeApply,
bae9f6d2
JC
192 },
193
194 // Run destroy provisioners if not tainted
195 &EvalIf{
196 If: func(ctx EvalContext) (bool, error) {
107c1cdb 197 if state != nil && state.Status == states.ObjectTainted {
bae9f6d2
JC
198 return false, nil
199 }
200
201 return true, nil
202 },
203
204 Then: &EvalApplyProvisioners{
107c1cdb 205 Addr: addr.Resource,
bae9f6d2 206 State: &state,
107c1cdb 207 ResourceConfig: n.Config,
bae9f6d2 208 Error: &err,
107c1cdb 209 When: configs.ProvisionerWhenDestroy,
bae9f6d2
JC
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{
107c1cdb 221 Addr: addr.Resource,
bae9f6d2
JC
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) {
107c1cdb 230 return addr.Resource.Resource.Mode == addrs.DataResourceMode, nil
bae9f6d2
JC
231 },
232
233 Then: &EvalReadDataApply{
107c1cdb
ND
234 Addr: addr.Resource,
235 Config: n.Config,
236 Change: &changeApply,
237 Provider: &provider,
238 ProviderAddr: n.ResolvedProvider,
239 ProviderSchema: &providerSchema,
240 Output: &state,
bae9f6d2
JC
241 },
242 Else: &EvalApply{
107c1cdb
ND
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,
bae9f6d2
JC
252 },
253 },
254 &EvalWriteState{
107c1cdb
ND
255 Addr: addr.Resource,
256 ProviderAddr: n.ResolvedProvider,
257 ProviderSchema: &providerSchema,
258 State: &state,
bae9f6d2
JC
259 },
260 &EvalApplyPost{
107c1cdb 261 Addr: addr.Resource,
bae9f6d2
JC
262 State: &state,
263 Error: &err,
264 },
265 &EvalUpdateStateHook{},
266 },
267 },
268 }
269}
107c1cdb
ND
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.
279type NodeDestroyResource struct {
280 *NodeAbstractResource
281}
282
283var (
284 _ GraphNodeResource = (*NodeDestroyResource)(nil)
285 _ GraphNodeReferenceable = (*NodeDestroyResource)(nil)
286 _ GraphNodeReferencer = (*NodeDestroyResource)(nil)
287 _ GraphNodeEvalable = (*NodeDestroyResource)(nil)
288)
289
290func (n *NodeDestroyResource) Name() string {
291 return n.ResourceAddr().String() + " (clean up state)"
292}
293
294// GraphNodeReferenceable, overriding NodeAbstractResource
295func (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
304func (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
313func (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}