diff options
author | Jake Champlin <jake.champlin.27@gmail.com> | 2017-06-06 12:40:07 -0400 |
---|---|---|
committer | Jake Champlin <jake.champlin.27@gmail.com> | 2017-06-06 12:40:07 -0400 |
commit | bae9f6d2fd5eb5bc80929bd393932b23f14d7c93 (patch) | |
tree | ca9ab12a7d78b1fc27a8f734729081357ce6d252 /vendor/github.com/hashicorp/terraform/terraform/eval_state.go | |
parent | 254c495b6bebab3fb72a243c4bce858d79e6ee99 (diff) | |
download | terraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.tar.gz terraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.tar.zst terraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.zip |
Initial transfer of provider code
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/eval_state.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/terraform/eval_state.go | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/terraform/eval_state.go b/vendor/github.com/hashicorp/terraform/terraform/eval_state.go new file mode 100644 index 0000000..126a0e6 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/terraform/eval_state.go | |||
@@ -0,0 +1,324 @@ | |||
1 | package terraform | ||
2 | |||
3 | import "fmt" | ||
4 | |||
5 | // EvalReadState is an EvalNode implementation that reads the | ||
6 | // primary InstanceState for a specific resource out of the state. | ||
7 | type EvalReadState struct { | ||
8 | Name string | ||
9 | Output **InstanceState | ||
10 | } | ||
11 | |||
12 | func (n *EvalReadState) Eval(ctx EvalContext) (interface{}, error) { | ||
13 | return readInstanceFromState(ctx, n.Name, n.Output, func(rs *ResourceState) (*InstanceState, error) { | ||
14 | return rs.Primary, nil | ||
15 | }) | ||
16 | } | ||
17 | |||
18 | // EvalReadStateDeposed is an EvalNode implementation that reads the | ||
19 | // deposed InstanceState for a specific resource out of the state | ||
20 | type EvalReadStateDeposed struct { | ||
21 | Name string | ||
22 | Output **InstanceState | ||
23 | // Index indicates which instance in the Deposed list to target, or -1 for | ||
24 | // the last item. | ||
25 | Index int | ||
26 | } | ||
27 | |||
28 | func (n *EvalReadStateDeposed) Eval(ctx EvalContext) (interface{}, error) { | ||
29 | return readInstanceFromState(ctx, n.Name, n.Output, func(rs *ResourceState) (*InstanceState, error) { | ||
30 | // Get the index. If it is negative, then we get the last one | ||
31 | idx := n.Index | ||
32 | if idx < 0 { | ||
33 | idx = len(rs.Deposed) - 1 | ||
34 | } | ||
35 | if idx >= 0 && idx < len(rs.Deposed) { | ||
36 | return rs.Deposed[idx], nil | ||
37 | } else { | ||
38 | return nil, fmt.Errorf("bad deposed index: %d, for resource: %#v", idx, rs) | ||
39 | } | ||
40 | }) | ||
41 | } | ||
42 | |||
43 | // Does the bulk of the work for the various flavors of ReadState eval nodes. | ||
44 | // Each node just provides a reader function to get from the ResourceState to the | ||
45 | // InstanceState, and this takes care of all the plumbing. | ||
46 | func readInstanceFromState( | ||
47 | ctx EvalContext, | ||
48 | resourceName string, | ||
49 | output **InstanceState, | ||
50 | readerFn func(*ResourceState) (*InstanceState, error), | ||
51 | ) (*InstanceState, error) { | ||
52 | state, lock := ctx.State() | ||
53 | |||
54 | // Get a read lock so we can access this instance | ||
55 | lock.RLock() | ||
56 | defer lock.RUnlock() | ||
57 | |||
58 | // Look for the module state. If we don't have one, then it doesn't matter. | ||
59 | mod := state.ModuleByPath(ctx.Path()) | ||
60 | if mod == nil { | ||
61 | return nil, nil | ||
62 | } | ||
63 | |||
64 | // Look for the resource state. If we don't have one, then it is okay. | ||
65 | rs := mod.Resources[resourceName] | ||
66 | if rs == nil { | ||
67 | return nil, nil | ||
68 | } | ||
69 | |||
70 | // Use the delegate function to get the instance state from the resource state | ||
71 | is, err := readerFn(rs) | ||
72 | if err != nil { | ||
73 | return nil, err | ||
74 | } | ||
75 | |||
76 | // Write the result to the output pointer | ||
77 | if output != nil { | ||
78 | *output = is | ||
79 | } | ||
80 | |||
81 | return is, nil | ||
82 | } | ||
83 | |||
84 | // EvalRequireState is an EvalNode implementation that early exits | ||
85 | // if the state doesn't have an ID. | ||
86 | type EvalRequireState struct { | ||
87 | State **InstanceState | ||
88 | } | ||
89 | |||
90 | func (n *EvalRequireState) Eval(ctx EvalContext) (interface{}, error) { | ||
91 | if n.State == nil { | ||
92 | return nil, EvalEarlyExitError{} | ||
93 | } | ||
94 | |||
95 | state := *n.State | ||
96 | if state == nil || state.ID == "" { | ||
97 | return nil, EvalEarlyExitError{} | ||
98 | } | ||
99 | |||
100 | return nil, nil | ||
101 | } | ||
102 | |||
103 | // EvalUpdateStateHook is an EvalNode implementation that calls the | ||
104 | // PostStateUpdate hook with the current state. | ||
105 | type EvalUpdateStateHook struct{} | ||
106 | |||
107 | func (n *EvalUpdateStateHook) Eval(ctx EvalContext) (interface{}, error) { | ||
108 | state, lock := ctx.State() | ||
109 | |||
110 | // Get a full lock. Even calling something like WriteState can modify | ||
111 | // (prune) the state, so we need the full lock. | ||
112 | lock.Lock() | ||
113 | defer lock.Unlock() | ||
114 | |||
115 | // Call the hook | ||
116 | err := ctx.Hook(func(h Hook) (HookAction, error) { | ||
117 | return h.PostStateUpdate(state) | ||
118 | }) | ||
119 | if err != nil { | ||
120 | return nil, err | ||
121 | } | ||
122 | |||
123 | return nil, nil | ||
124 | } | ||
125 | |||
126 | // EvalWriteState is an EvalNode implementation that writes the | ||
127 | // primary InstanceState for a specific resource into the state. | ||
128 | type EvalWriteState struct { | ||
129 | Name string | ||
130 | ResourceType string | ||
131 | Provider string | ||
132 | Dependencies []string | ||
133 | State **InstanceState | ||
134 | } | ||
135 | |||
136 | func (n *EvalWriteState) Eval(ctx EvalContext) (interface{}, error) { | ||
137 | return writeInstanceToState(ctx, n.Name, n.ResourceType, n.Provider, n.Dependencies, | ||
138 | func(rs *ResourceState) error { | ||
139 | rs.Primary = *n.State | ||
140 | return nil | ||
141 | }, | ||
142 | ) | ||
143 | } | ||
144 | |||
145 | // EvalWriteStateDeposed is an EvalNode implementation that writes | ||
146 | // an InstanceState out to the Deposed list of a resource in the state. | ||
147 | type EvalWriteStateDeposed struct { | ||
148 | Name string | ||
149 | ResourceType string | ||
150 | Provider string | ||
151 | Dependencies []string | ||
152 | State **InstanceState | ||
153 | // Index indicates which instance in the Deposed list to target, or -1 to append. | ||
154 | Index int | ||
155 | } | ||
156 | |||
157 | func (n *EvalWriteStateDeposed) Eval(ctx EvalContext) (interface{}, error) { | ||
158 | return writeInstanceToState(ctx, n.Name, n.ResourceType, n.Provider, n.Dependencies, | ||
159 | func(rs *ResourceState) error { | ||
160 | if n.Index == -1 { | ||
161 | rs.Deposed = append(rs.Deposed, *n.State) | ||
162 | } else { | ||
163 | rs.Deposed[n.Index] = *n.State | ||
164 | } | ||
165 | return nil | ||
166 | }, | ||
167 | ) | ||
168 | } | ||
169 | |||
170 | // Pulls together the common tasks of the EvalWriteState nodes. All the args | ||
171 | // are passed directly down from the EvalNode along with a `writer` function | ||
172 | // which is yielded the *ResourceState and is responsible for writing an | ||
173 | // InstanceState to the proper field in the ResourceState. | ||
174 | func writeInstanceToState( | ||
175 | ctx EvalContext, | ||
176 | resourceName string, | ||
177 | resourceType string, | ||
178 | provider string, | ||
179 | dependencies []string, | ||
180 | writerFn func(*ResourceState) error, | ||
181 | ) (*InstanceState, error) { | ||
182 | state, lock := ctx.State() | ||
183 | if state == nil { | ||
184 | return nil, fmt.Errorf("cannot write state to nil state") | ||
185 | } | ||
186 | |||
187 | // Get a write lock so we can access this instance | ||
188 | lock.Lock() | ||
189 | defer lock.Unlock() | ||
190 | |||
191 | // Look for the module state. If we don't have one, create it. | ||
192 | mod := state.ModuleByPath(ctx.Path()) | ||
193 | if mod == nil { | ||
194 | mod = state.AddModule(ctx.Path()) | ||
195 | } | ||
196 | |||
197 | // Look for the resource state. | ||
198 | rs := mod.Resources[resourceName] | ||
199 | if rs == nil { | ||
200 | rs = &ResourceState{} | ||
201 | rs.init() | ||
202 | mod.Resources[resourceName] = rs | ||
203 | } | ||
204 | rs.Type = resourceType | ||
205 | rs.Dependencies = dependencies | ||
206 | rs.Provider = provider | ||
207 | |||
208 | if err := writerFn(rs); err != nil { | ||
209 | return nil, err | ||
210 | } | ||
211 | |||
212 | return nil, nil | ||
213 | } | ||
214 | |||
215 | // EvalClearPrimaryState is an EvalNode implementation that clears the primary | ||
216 | // instance from a resource state. | ||
217 | type EvalClearPrimaryState struct { | ||
218 | Name string | ||
219 | } | ||
220 | |||
221 | func (n *EvalClearPrimaryState) Eval(ctx EvalContext) (interface{}, error) { | ||
222 | state, lock := ctx.State() | ||
223 | |||
224 | // Get a read lock so we can access this instance | ||
225 | lock.RLock() | ||
226 | defer lock.RUnlock() | ||
227 | |||
228 | // Look for the module state. If we don't have one, then it doesn't matter. | ||
229 | mod := state.ModuleByPath(ctx.Path()) | ||
230 | if mod == nil { | ||
231 | return nil, nil | ||
232 | } | ||
233 | |||
234 | // Look for the resource state. If we don't have one, then it is okay. | ||
235 | rs := mod.Resources[n.Name] | ||
236 | if rs == nil { | ||
237 | return nil, nil | ||
238 | } | ||
239 | |||
240 | // Clear primary from the resource state | ||
241 | rs.Primary = nil | ||
242 | |||
243 | return nil, nil | ||
244 | } | ||
245 | |||
246 | // EvalDeposeState is an EvalNode implementation that takes the primary | ||
247 | // out of a state and makes it Deposed. This is done at the beginning of | ||
248 | // create-before-destroy calls so that the create can create while preserving | ||
249 | // the old state of the to-be-destroyed resource. | ||
250 | type EvalDeposeState struct { | ||
251 | Name string | ||
252 | } | ||
253 | |||
254 | // TODO: test | ||
255 | func (n *EvalDeposeState) Eval(ctx EvalContext) (interface{}, error) { | ||
256 | state, lock := ctx.State() | ||
257 | |||
258 | // Get a read lock so we can access this instance | ||
259 | lock.RLock() | ||
260 | defer lock.RUnlock() | ||
261 | |||
262 | // Look for the module state. If we don't have one, then it doesn't matter. | ||
263 | mod := state.ModuleByPath(ctx.Path()) | ||
264 | if mod == nil { | ||
265 | return nil, nil | ||
266 | } | ||
267 | |||
268 | // Look for the resource state. If we don't have one, then it is okay. | ||
269 | rs := mod.Resources[n.Name] | ||
270 | if rs == nil { | ||
271 | return nil, nil | ||
272 | } | ||
273 | |||
274 | // If we don't have a primary, we have nothing to depose | ||
275 | if rs.Primary == nil { | ||
276 | return nil, nil | ||
277 | } | ||
278 | |||
279 | // Depose | ||
280 | rs.Deposed = append(rs.Deposed, rs.Primary) | ||
281 | rs.Primary = nil | ||
282 | |||
283 | return nil, nil | ||
284 | } | ||
285 | |||
286 | // EvalUndeposeState is an EvalNode implementation that reads the | ||
287 | // InstanceState for a specific resource out of the state. | ||
288 | type EvalUndeposeState struct { | ||
289 | Name string | ||
290 | State **InstanceState | ||
291 | } | ||
292 | |||
293 | // TODO: test | ||
294 | func (n *EvalUndeposeState) Eval(ctx EvalContext) (interface{}, error) { | ||
295 | state, lock := ctx.State() | ||
296 | |||
297 | // Get a read lock so we can access this instance | ||
298 | lock.RLock() | ||
299 | defer lock.RUnlock() | ||
300 | |||
301 | // Look for the module state. If we don't have one, then it doesn't matter. | ||
302 | mod := state.ModuleByPath(ctx.Path()) | ||
303 | if mod == nil { | ||
304 | return nil, nil | ||
305 | } | ||
306 | |||
307 | // Look for the resource state. If we don't have one, then it is okay. | ||
308 | rs := mod.Resources[n.Name] | ||
309 | if rs == nil { | ||
310 | return nil, nil | ||
311 | } | ||
312 | |||
313 | // If we don't have any desposed resource, then we don't have anything to do | ||
314 | if len(rs.Deposed) == 0 { | ||
315 | return nil, nil | ||
316 | } | ||
317 | |||
318 | // Undepose | ||
319 | idx := len(rs.Deposed) - 1 | ||
320 | rs.Primary = rs.Deposed[idx] | ||
321 | rs.Deposed[idx] = *n.State | ||
322 | |||
323 | return nil, nil | ||
324 | } | ||