diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/resource.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/terraform/resource.go | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/terraform/resource.go b/vendor/github.com/hashicorp/terraform/terraform/resource.go new file mode 100644 index 0000000..0acf0be --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/terraform/resource.go | |||
@@ -0,0 +1,360 @@ | |||
1 | package terraform | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "reflect" | ||
6 | "sort" | ||
7 | "strconv" | ||
8 | "strings" | ||
9 | |||
10 | "github.com/hashicorp/terraform/config" | ||
11 | "github.com/mitchellh/copystructure" | ||
12 | "github.com/mitchellh/reflectwalk" | ||
13 | ) | ||
14 | |||
15 | // ResourceProvisionerConfig is used to pair a provisioner | ||
16 | // with its provided configuration. This allows us to use singleton | ||
17 | // instances of each ResourceProvisioner and to keep the relevant | ||
18 | // configuration instead of instantiating a new Provisioner for each | ||
19 | // resource. | ||
20 | type ResourceProvisionerConfig struct { | ||
21 | Type string | ||
22 | Provisioner ResourceProvisioner | ||
23 | Config *ResourceConfig | ||
24 | RawConfig *config.RawConfig | ||
25 | ConnInfo *config.RawConfig | ||
26 | } | ||
27 | |||
28 | // Resource encapsulates a resource, its configuration, its provider, | ||
29 | // its current state, and potentially a desired diff from the state it | ||
30 | // wants to reach. | ||
31 | type Resource struct { | ||
32 | // These are all used by the new EvalNode stuff. | ||
33 | Name string | ||
34 | Type string | ||
35 | CountIndex int | ||
36 | |||
37 | // These aren't really used anymore anywhere, but we keep them around | ||
38 | // since we haven't done a proper cleanup yet. | ||
39 | Id string | ||
40 | Info *InstanceInfo | ||
41 | Config *ResourceConfig | ||
42 | Dependencies []string | ||
43 | Diff *InstanceDiff | ||
44 | Provider ResourceProvider | ||
45 | State *InstanceState | ||
46 | Provisioners []*ResourceProvisionerConfig | ||
47 | Flags ResourceFlag | ||
48 | } | ||
49 | |||
50 | // ResourceKind specifies what kind of instance we're working with, whether | ||
51 | // its a primary instance, a tainted instance, or an orphan. | ||
52 | type ResourceFlag byte | ||
53 | |||
54 | // InstanceInfo is used to hold information about the instance and/or | ||
55 | // resource being modified. | ||
56 | type InstanceInfo struct { | ||
57 | // Id is a unique name to represent this instance. This is not related | ||
58 | // to InstanceState.ID in any way. | ||
59 | Id string | ||
60 | |||
61 | // ModulePath is the complete path of the module containing this | ||
62 | // instance. | ||
63 | ModulePath []string | ||
64 | |||
65 | // Type is the resource type of this instance | ||
66 | Type string | ||
67 | |||
68 | // uniqueExtra is an internal field that can be populated to supply | ||
69 | // extra metadata that is used to identify a unique instance in | ||
70 | // the graph walk. This will be appended to HumanID when uniqueId | ||
71 | // is called. | ||
72 | uniqueExtra string | ||
73 | } | ||
74 | |||
75 | // HumanId is a unique Id that is human-friendly and useful for UI elements. | ||
76 | func (i *InstanceInfo) HumanId() string { | ||
77 | if i == nil { | ||
78 | return "<nil>" | ||
79 | } | ||
80 | |||
81 | if len(i.ModulePath) <= 1 { | ||
82 | return i.Id | ||
83 | } | ||
84 | |||
85 | return fmt.Sprintf( | ||
86 | "module.%s.%s", | ||
87 | strings.Join(i.ModulePath[1:], "."), | ||
88 | i.Id) | ||
89 | } | ||
90 | |||
91 | func (i *InstanceInfo) uniqueId() string { | ||
92 | prefix := i.HumanId() | ||
93 | if v := i.uniqueExtra; v != "" { | ||
94 | prefix += " " + v | ||
95 | } | ||
96 | |||
97 | return prefix | ||
98 | } | ||
99 | |||
100 | // ResourceConfig holds the configuration given for a resource. This is | ||
101 | // done instead of a raw `map[string]interface{}` type so that rich | ||
102 | // methods can be added to it to make dealing with it easier. | ||
103 | type ResourceConfig struct { | ||
104 | ComputedKeys []string | ||
105 | Raw map[string]interface{} | ||
106 | Config map[string]interface{} | ||
107 | |||
108 | raw *config.RawConfig | ||
109 | } | ||
110 | |||
111 | // NewResourceConfig creates a new ResourceConfig from a config.RawConfig. | ||
112 | func NewResourceConfig(c *config.RawConfig) *ResourceConfig { | ||
113 | result := &ResourceConfig{raw: c} | ||
114 | result.interpolateForce() | ||
115 | return result | ||
116 | } | ||
117 | |||
118 | // DeepCopy performs a deep copy of the configuration. This makes it safe | ||
119 | // to modify any of the structures that are part of the resource config without | ||
120 | // affecting the original configuration. | ||
121 | func (c *ResourceConfig) DeepCopy() *ResourceConfig { | ||
122 | // DeepCopying a nil should return a nil to avoid panics | ||
123 | if c == nil { | ||
124 | return nil | ||
125 | } | ||
126 | |||
127 | // Copy, this will copy all the exported attributes | ||
128 | copy, err := copystructure.Config{Lock: true}.Copy(c) | ||
129 | if err != nil { | ||
130 | panic(err) | ||
131 | } | ||
132 | |||
133 | // Force the type | ||
134 | result := copy.(*ResourceConfig) | ||
135 | |||
136 | // For the raw configuration, we can just use its own copy method | ||
137 | result.raw = c.raw.Copy() | ||
138 | |||
139 | return result | ||
140 | } | ||
141 | |||
142 | // Equal checks the equality of two resource configs. | ||
143 | func (c *ResourceConfig) Equal(c2 *ResourceConfig) bool { | ||
144 | // If either are nil, then they're only equal if they're both nil | ||
145 | if c == nil || c2 == nil { | ||
146 | return c == c2 | ||
147 | } | ||
148 | |||
149 | // Sort the computed keys so they're deterministic | ||
150 | sort.Strings(c.ComputedKeys) | ||
151 | sort.Strings(c2.ComputedKeys) | ||
152 | |||
153 | // Two resource configs if their exported properties are equal. | ||
154 | // We don't compare "raw" because it is never used again after | ||
155 | // initialization and for all intents and purposes they are equal | ||
156 | // if the exported properties are equal. | ||
157 | check := [][2]interface{}{ | ||
158 | {c.ComputedKeys, c2.ComputedKeys}, | ||
159 | {c.Raw, c2.Raw}, | ||
160 | {c.Config, c2.Config}, | ||
161 | } | ||
162 | for _, pair := range check { | ||
163 | if !reflect.DeepEqual(pair[0], pair[1]) { | ||
164 | return false | ||
165 | } | ||
166 | } | ||
167 | |||
168 | return true | ||
169 | } | ||
170 | |||
171 | // CheckSet checks that the given list of configuration keys is | ||
172 | // properly set. If not, errors are returned for each unset key. | ||
173 | // | ||
174 | // This is useful to be called in the Validate method of a ResourceProvider. | ||
175 | func (c *ResourceConfig) CheckSet(keys []string) []error { | ||
176 | var errs []error | ||
177 | |||
178 | for _, k := range keys { | ||
179 | if !c.IsSet(k) { | ||
180 | errs = append(errs, fmt.Errorf("%s must be set", k)) | ||
181 | } | ||
182 | } | ||
183 | |||
184 | return errs | ||
185 | } | ||
186 | |||
187 | // Get looks up a configuration value by key and returns the value. | ||
188 | // | ||
189 | // The second return value is true if the get was successful. Get will | ||
190 | // return the raw value if the key is computed, so you should pair this | ||
191 | // with IsComputed. | ||
192 | func (c *ResourceConfig) Get(k string) (interface{}, bool) { | ||
193 | // We aim to get a value from the configuration. If it is computed, | ||
194 | // then we return the pure raw value. | ||
195 | source := c.Config | ||
196 | if c.IsComputed(k) { | ||
197 | source = c.Raw | ||
198 | } | ||
199 | |||
200 | return c.get(k, source) | ||
201 | } | ||
202 | |||
203 | // GetRaw looks up a configuration value by key and returns the value, | ||
204 | // from the raw, uninterpolated config. | ||
205 | // | ||
206 | // The second return value is true if the get was successful. Get will | ||
207 | // not succeed if the value is being computed. | ||
208 | func (c *ResourceConfig) GetRaw(k string) (interface{}, bool) { | ||
209 | return c.get(k, c.Raw) | ||
210 | } | ||
211 | |||
212 | // IsComputed returns whether the given key is computed or not. | ||
213 | func (c *ResourceConfig) IsComputed(k string) bool { | ||
214 | // The next thing we do is check the config if we get a computed | ||
215 | // value out of it. | ||
216 | v, ok := c.get(k, c.Config) | ||
217 | if !ok { | ||
218 | return false | ||
219 | } | ||
220 | |||
221 | // If value is nil, then it isn't computed | ||
222 | if v == nil { | ||
223 | return false | ||
224 | } | ||
225 | |||
226 | // Test if the value contains an unknown value | ||
227 | var w unknownCheckWalker | ||
228 | if err := reflectwalk.Walk(v, &w); err != nil { | ||
229 | panic(err) | ||
230 | } | ||
231 | |||
232 | return w.Unknown | ||
233 | } | ||
234 | |||
235 | // IsSet checks if the key in the configuration is set. A key is set if | ||
236 | // it has a value or the value is being computed (is unknown currently). | ||
237 | // | ||
238 | // This function should be used rather than checking the keys of the | ||
239 | // raw configuration itself, since a key may be omitted from the raw | ||
240 | // configuration if it is being computed. | ||
241 | func (c *ResourceConfig) IsSet(k string) bool { | ||
242 | if c == nil { | ||
243 | return false | ||
244 | } | ||
245 | |||
246 | if c.IsComputed(k) { | ||
247 | return true | ||
248 | } | ||
249 | |||
250 | if _, ok := c.Get(k); ok { | ||
251 | return true | ||
252 | } | ||
253 | |||
254 | return false | ||
255 | } | ||
256 | |||
257 | func (c *ResourceConfig) get( | ||
258 | k string, raw map[string]interface{}) (interface{}, bool) { | ||
259 | parts := strings.Split(k, ".") | ||
260 | if len(parts) == 1 && parts[0] == "" { | ||
261 | parts = nil | ||
262 | } | ||
263 | |||
264 | var current interface{} = raw | ||
265 | var previous interface{} = nil | ||
266 | for i, part := range parts { | ||
267 | if current == nil { | ||
268 | return nil, false | ||
269 | } | ||
270 | |||
271 | cv := reflect.ValueOf(current) | ||
272 | switch cv.Kind() { | ||
273 | case reflect.Map: | ||
274 | previous = current | ||
275 | v := cv.MapIndex(reflect.ValueOf(part)) | ||
276 | if !v.IsValid() { | ||
277 | if i > 0 && i != (len(parts)-1) { | ||
278 | tryKey := strings.Join(parts[i:], ".") | ||
279 | v := cv.MapIndex(reflect.ValueOf(tryKey)) | ||
280 | if !v.IsValid() { | ||
281 | return nil, false | ||
282 | } | ||
283 | |||
284 | return v.Interface(), true | ||
285 | } | ||
286 | |||
287 | return nil, false | ||
288 | } | ||
289 | |||
290 | current = v.Interface() | ||
291 | case reflect.Slice: | ||
292 | previous = current | ||
293 | |||
294 | if part == "#" { | ||
295 | // If any value in a list is computed, this whole thing | ||
296 | // is computed and we can't read any part of it. | ||
297 | for i := 0; i < cv.Len(); i++ { | ||
298 | if v := cv.Index(i).Interface(); v == unknownValue() { | ||
299 | return v, true | ||
300 | } | ||
301 | } | ||
302 | |||
303 | current = cv.Len() | ||
304 | } else { | ||
305 | i, err := strconv.ParseInt(part, 0, 0) | ||
306 | if err != nil { | ||
307 | return nil, false | ||
308 | } | ||
309 | if i >= int64(cv.Len()) { | ||
310 | return nil, false | ||
311 | } | ||
312 | current = cv.Index(int(i)).Interface() | ||
313 | } | ||
314 | case reflect.String: | ||
315 | // This happens when map keys contain "." and have a common | ||
316 | // prefix so were split as path components above. | ||
317 | actualKey := strings.Join(parts[i-1:], ".") | ||
318 | if prevMap, ok := previous.(map[string]interface{}); ok { | ||
319 | v, ok := prevMap[actualKey] | ||
320 | return v, ok | ||
321 | } | ||
322 | |||
323 | return nil, false | ||
324 | default: | ||
325 | panic(fmt.Sprintf("Unknown kind: %s", cv.Kind())) | ||
326 | } | ||
327 | } | ||
328 | |||
329 | return current, true | ||
330 | } | ||
331 | |||
332 | // interpolateForce is a temporary thing. We want to get rid of interpolate | ||
333 | // above and likewise this, but it can only be done after the f-ast-graph | ||
334 | // refactor is complete. | ||
335 | func (c *ResourceConfig) interpolateForce() { | ||
336 | if c.raw == nil { | ||
337 | var err error | ||
338 | c.raw, err = config.NewRawConfig(make(map[string]interface{})) | ||
339 | if err != nil { | ||
340 | panic(err) | ||
341 | } | ||
342 | } | ||
343 | |||
344 | c.ComputedKeys = c.raw.UnknownKeys() | ||
345 | c.Raw = c.raw.RawMap() | ||
346 | c.Config = c.raw.Config() | ||
347 | } | ||
348 | |||
349 | // unknownCheckWalker | ||
350 | type unknownCheckWalker struct { | ||
351 | Unknown bool | ||
352 | } | ||
353 | |||
354 | func (w *unknownCheckWalker) Primitive(v reflect.Value) error { | ||
355 | if v.Interface() == unknownValue() { | ||
356 | w.Unknown = true | ||
357 | } | ||
358 | |||
359 | return nil | ||
360 | } | ||