diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/eval_count_boundary.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/terraform/eval_count_boundary.go | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/terraform/eval_count_boundary.go b/vendor/github.com/hashicorp/terraform/terraform/eval_count_boundary.go new file mode 100644 index 0000000..91e2b90 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/terraform/eval_count_boundary.go | |||
@@ -0,0 +1,78 @@ | |||
1 | package terraform | ||
2 | |||
3 | import ( | ||
4 | "log" | ||
5 | ) | ||
6 | |||
7 | // EvalCountFixZeroOneBoundaryGlobal is an EvalNode that fixes up the state | ||
8 | // when there is a resource count with zero/one boundary, i.e. fixing | ||
9 | // a resource named "aws_instance.foo" to "aws_instance.foo.0" and vice-versa. | ||
10 | // | ||
11 | // This works on the global state. | ||
12 | type EvalCountFixZeroOneBoundaryGlobal struct{} | ||
13 | |||
14 | // TODO: test | ||
15 | func (n *EvalCountFixZeroOneBoundaryGlobal) Eval(ctx EvalContext) (interface{}, error) { | ||
16 | // Get the state and lock it since we'll potentially modify it | ||
17 | state, lock := ctx.State() | ||
18 | lock.Lock() | ||
19 | defer lock.Unlock() | ||
20 | |||
21 | // Prune the state since we require a clean state to work | ||
22 | state.prune() | ||
23 | |||
24 | // Go through each modules since the boundaries are restricted to a | ||
25 | // module scope. | ||
26 | for _, m := range state.Modules { | ||
27 | if err := n.fixModule(m); err != nil { | ||
28 | return nil, err | ||
29 | } | ||
30 | } | ||
31 | |||
32 | return nil, nil | ||
33 | } | ||
34 | |||
35 | func (n *EvalCountFixZeroOneBoundaryGlobal) fixModule(m *ModuleState) error { | ||
36 | // Counts keeps track of keys and their counts | ||
37 | counts := make(map[string]int) | ||
38 | for k, _ := range m.Resources { | ||
39 | // Parse the key | ||
40 | key, err := ParseResourceStateKey(k) | ||
41 | if err != nil { | ||
42 | return err | ||
43 | } | ||
44 | |||
45 | // Set the index to -1 so that we can keep count | ||
46 | key.Index = -1 | ||
47 | |||
48 | // Increment | ||
49 | counts[key.String()]++ | ||
50 | } | ||
51 | |||
52 | // Go through the counts and do the fixup for each resource | ||
53 | for raw, count := range counts { | ||
54 | // Search and replace this resource | ||
55 | search := raw | ||
56 | replace := raw + ".0" | ||
57 | if count < 2 { | ||
58 | search, replace = replace, search | ||
59 | } | ||
60 | log.Printf("[TRACE] EvalCountFixZeroOneBoundaryGlobal: count %d, search %q, replace %q", count, search, replace) | ||
61 | |||
62 | // Look for the resource state. If we don't have one, then it is okay. | ||
63 | rs, ok := m.Resources[search] | ||
64 | if !ok { | ||
65 | continue | ||
66 | } | ||
67 | |||
68 | // If the replacement key exists, we just keep both | ||
69 | if _, ok := m.Resources[replace]; ok { | ||
70 | continue | ||
71 | } | ||
72 | |||
73 | m.Resources[replace] = rs | ||
74 | delete(m.Resources, search) | ||
75 | } | ||
76 | |||
77 | return nil | ||
78 | } | ||