diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/node_resource_destroy.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/terraform/node_resource_destroy.go | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/terraform/node_resource_destroy.go b/vendor/github.com/hashicorp/terraform/terraform/node_resource_destroy.go new file mode 100644 index 0000000..c2efd2c --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/terraform/node_resource_destroy.go | |||
@@ -0,0 +1,288 @@ | |||
1 | package terraform | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/hashicorp/terraform/config" | ||
7 | ) | ||
8 | |||
9 | // NodeDestroyResource represents a resource that is to be destroyed. | ||
10 | type NodeDestroyResource struct { | ||
11 | *NodeAbstractResource | ||
12 | } | ||
13 | |||
14 | func (n *NodeDestroyResource) Name() string { | ||
15 | return n.NodeAbstractResource.Name() + " (destroy)" | ||
16 | } | ||
17 | |||
18 | // GraphNodeDestroyer | ||
19 | func (n *NodeDestroyResource) DestroyAddr() *ResourceAddress { | ||
20 | return n.Addr | ||
21 | } | ||
22 | |||
23 | // GraphNodeDestroyerCBD | ||
24 | func (n *NodeDestroyResource) CreateBeforeDestroy() bool { | ||
25 | // If we have no config, we just assume no | ||
26 | if n.Config == nil { | ||
27 | return false | ||
28 | } | ||
29 | |||
30 | return n.Config.Lifecycle.CreateBeforeDestroy | ||
31 | } | ||
32 | |||
33 | // GraphNodeDestroyerCBD | ||
34 | func (n *NodeDestroyResource) ModifyCreateBeforeDestroy(v bool) error { | ||
35 | // If we have no config, do nothing since it won't affect the | ||
36 | // create step anyways. | ||
37 | if n.Config == nil { | ||
38 | return nil | ||
39 | } | ||
40 | |||
41 | // Set CBD to true | ||
42 | n.Config.Lifecycle.CreateBeforeDestroy = true | ||
43 | |||
44 | return nil | ||
45 | } | ||
46 | |||
47 | // GraphNodeReferenceable, overriding NodeAbstractResource | ||
48 | func (n *NodeDestroyResource) ReferenceableName() []string { | ||
49 | // We modify our referenceable name to have the suffix of ".destroy" | ||
50 | // since depending on the creation side doesn't necessarilly mean | ||
51 | // depending on destruction. | ||
52 | suffix := ".destroy" | ||
53 | |||
54 | // If we're CBD, we also append "-cbd". This is because CBD will setup | ||
55 | // its own edges (in CBDEdgeTransformer). Depending on the "destroy" | ||
56 | // side generally doesn't mean depending on CBD as well. See GH-11349 | ||
57 | if n.CreateBeforeDestroy() { | ||
58 | suffix += "-cbd" | ||
59 | } | ||
60 | |||
61 | result := n.NodeAbstractResource.ReferenceableName() | ||
62 | for i, v := range result { | ||
63 | result[i] = v + suffix | ||
64 | } | ||
65 | |||
66 | return result | ||
67 | } | ||
68 | |||
69 | // GraphNodeReferencer, overriding NodeAbstractResource | ||
70 | func (n *NodeDestroyResource) References() []string { | ||
71 | // If we have a config, then we need to include destroy-time dependencies | ||
72 | if c := n.Config; c != nil { | ||
73 | var result []string | ||
74 | for _, p := range c.Provisioners { | ||
75 | // We include conn info and config for destroy time provisioners | ||
76 | // as dependencies that we have. | ||
77 | if p.When == config.ProvisionerWhenDestroy { | ||
78 | result = append(result, ReferencesFromConfig(p.ConnInfo)...) | ||
79 | result = append(result, ReferencesFromConfig(p.RawConfig)...) | ||
80 | } | ||
81 | } | ||
82 | |||
83 | return result | ||
84 | } | ||
85 | |||
86 | return nil | ||
87 | } | ||
88 | |||
89 | // GraphNodeDynamicExpandable | ||
90 | func (n *NodeDestroyResource) DynamicExpand(ctx EvalContext) (*Graph, error) { | ||
91 | // If we have no config we do nothing | ||
92 | if n.Addr == nil { | ||
93 | return nil, nil | ||
94 | } | ||
95 | |||
96 | state, lock := ctx.State() | ||
97 | lock.RLock() | ||
98 | defer lock.RUnlock() | ||
99 | |||
100 | // Start creating the steps | ||
101 | steps := make([]GraphTransformer, 0, 5) | ||
102 | |||
103 | // We want deposed resources in the state to be destroyed | ||
104 | steps = append(steps, &DeposedTransformer{ | ||
105 | State: state, | ||
106 | View: n.Addr.stateId(), | ||
107 | }) | ||
108 | |||
109 | // Target | ||
110 | steps = append(steps, &TargetsTransformer{ | ||
111 | ParsedTargets: n.Targets, | ||
112 | }) | ||
113 | |||
114 | // Always end with the root being added | ||
115 | steps = append(steps, &RootTransformer{}) | ||
116 | |||
117 | // Build the graph | ||
118 | b := &BasicGraphBuilder{ | ||
119 | Steps: steps, | ||
120 | Name: "NodeResourceDestroy", | ||
121 | } | ||
122 | return b.Build(ctx.Path()) | ||
123 | } | ||
124 | |||
125 | // GraphNodeEvalable | ||
126 | func (n *NodeDestroyResource) EvalTree() EvalNode { | ||
127 | // stateId is the ID to put into the state | ||
128 | stateId := n.Addr.stateId() | ||
129 | |||
130 | // Build the instance info. More of this will be populated during eval | ||
131 | info := &InstanceInfo{ | ||
132 | Id: stateId, | ||
133 | Type: n.Addr.Type, | ||
134 | uniqueExtra: "destroy", | ||
135 | } | ||
136 | |||
137 | // Build the resource for eval | ||
138 | addr := n.Addr | ||
139 | resource := &Resource{ | ||
140 | Name: addr.Name, | ||
141 | Type: addr.Type, | ||
142 | CountIndex: addr.Index, | ||
143 | } | ||
144 | if resource.CountIndex < 0 { | ||
145 | resource.CountIndex = 0 | ||
146 | } | ||
147 | |||
148 | // Get our state | ||
149 | rs := n.ResourceState | ||
150 | if rs == nil { | ||
151 | rs = &ResourceState{} | ||
152 | } | ||
153 | |||
154 | var diffApply *InstanceDiff | ||
155 | var provider ResourceProvider | ||
156 | var state *InstanceState | ||
157 | var err error | ||
158 | return &EvalOpFilter{ | ||
159 | Ops: []walkOperation{walkApply, walkDestroy}, | ||
160 | Node: &EvalSequence{ | ||
161 | Nodes: []EvalNode{ | ||
162 | // Get the saved diff for apply | ||
163 | &EvalReadDiff{ | ||
164 | Name: stateId, | ||
165 | Diff: &diffApply, | ||
166 | }, | ||
167 | |||
168 | // Filter the diff so we only get the destroy | ||
169 | &EvalFilterDiff{ | ||
170 | Diff: &diffApply, | ||
171 | Output: &diffApply, | ||
172 | Destroy: true, | ||
173 | }, | ||
174 | |||
175 | // If we're not destroying, then compare diffs | ||
176 | &EvalIf{ | ||
177 | If: func(ctx EvalContext) (bool, error) { | ||
178 | if diffApply != nil && diffApply.GetDestroy() { | ||
179 | return true, nil | ||
180 | } | ||
181 | |||
182 | return true, EvalEarlyExitError{} | ||
183 | }, | ||
184 | Then: EvalNoop{}, | ||
185 | }, | ||
186 | |||
187 | // Load the instance info so we have the module path set | ||
188 | &EvalInstanceInfo{Info: info}, | ||
189 | |||
190 | &EvalGetProvider{ | ||
191 | Name: n.ProvidedBy()[0], | ||
192 | Output: &provider, | ||
193 | }, | ||
194 | &EvalReadState{ | ||
195 | Name: stateId, | ||
196 | Output: &state, | ||
197 | }, | ||
198 | &EvalRequireState{ | ||
199 | State: &state, | ||
200 | }, | ||
201 | |||
202 | // Call pre-apply hook | ||
203 | &EvalApplyPre{ | ||
204 | Info: info, | ||
205 | State: &state, | ||
206 | Diff: &diffApply, | ||
207 | }, | ||
208 | |||
209 | // Run destroy provisioners if not tainted | ||
210 | &EvalIf{ | ||
211 | If: func(ctx EvalContext) (bool, error) { | ||
212 | if state != nil && state.Tainted { | ||
213 | return false, nil | ||
214 | } | ||
215 | |||
216 | return true, nil | ||
217 | }, | ||
218 | |||
219 | Then: &EvalApplyProvisioners{ | ||
220 | Info: info, | ||
221 | State: &state, | ||
222 | Resource: n.Config, | ||
223 | InterpResource: resource, | ||
224 | Error: &err, | ||
225 | When: config.ProvisionerWhenDestroy, | ||
226 | }, | ||
227 | }, | ||
228 | |||
229 | // If we have a provisioning error, then we just call | ||
230 | // the post-apply hook now. | ||
231 | &EvalIf{ | ||
232 | If: func(ctx EvalContext) (bool, error) { | ||
233 | return err != nil, nil | ||
234 | }, | ||
235 | |||
236 | Then: &EvalApplyPost{ | ||
237 | Info: info, | ||
238 | State: &state, | ||
239 | Error: &err, | ||
240 | }, | ||
241 | }, | ||
242 | |||
243 | // Make sure we handle data sources properly. | ||
244 | &EvalIf{ | ||
245 | If: func(ctx EvalContext) (bool, error) { | ||
246 | if n.Addr == nil { | ||
247 | return false, fmt.Errorf("nil address") | ||
248 | } | ||
249 | |||
250 | if n.Addr.Mode == config.DataResourceMode { | ||
251 | return true, nil | ||
252 | } | ||
253 | |||
254 | return false, nil | ||
255 | }, | ||
256 | |||
257 | Then: &EvalReadDataApply{ | ||
258 | Info: info, | ||
259 | Diff: &diffApply, | ||
260 | Provider: &provider, | ||
261 | Output: &state, | ||
262 | }, | ||
263 | Else: &EvalApply{ | ||
264 | Info: info, | ||
265 | State: &state, | ||
266 | Diff: &diffApply, | ||
267 | Provider: &provider, | ||
268 | Output: &state, | ||
269 | Error: &err, | ||
270 | }, | ||
271 | }, | ||
272 | &EvalWriteState{ | ||
273 | Name: stateId, | ||
274 | ResourceType: n.Addr.Type, | ||
275 | Provider: rs.Provider, | ||
276 | Dependencies: rs.Dependencies, | ||
277 | State: &state, | ||
278 | }, | ||
279 | &EvalApplyPost{ | ||
280 | Info: info, | ||
281 | State: &state, | ||
282 | Error: &err, | ||
283 | }, | ||
284 | &EvalUpdateStateHook{}, | ||
285 | }, | ||
286 | }, | ||
287 | } | ||
288 | } | ||