]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
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 | } |