github.com/skyscape-cloud-services/terraform@v0.9.2-0.20170609144644-7ece028a1747/terraform/eval_count_boundary.go (about) 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 }