github.com/ggriffiths/terraform@v0.9.0-beta1.0.20170222213024-79c4935604cb/flatmap/expand.go (about) 1 package flatmap 2 3 import ( 4 "fmt" 5 "sort" 6 "strconv" 7 "strings" 8 ) 9 10 // Expand takes a map and a key (prefix) and expands that value into 11 // a more complex structure. This is the reverse of the Flatten operation. 12 func Expand(m map[string]string, key string) interface{} { 13 // If the key is exactly a key in the map, just return it 14 if v, ok := m[key]; ok { 15 if v == "true" { 16 return true 17 } else if v == "false" { 18 return false 19 } 20 21 return v 22 } 23 24 // Check if the key is an array, and if so, expand the array 25 if _, ok := m[key+".#"]; ok { 26 return expandArray(m, key) 27 } 28 29 // Check if this is a prefix in the map 30 prefix := key + "." 31 for k, _ := range m { 32 if strings.HasPrefix(k, prefix) { 33 return expandMap(m, prefix) 34 } 35 } 36 37 return nil 38 } 39 40 func expandArray(m map[string]string, prefix string) []interface{} { 41 num, err := strconv.ParseInt(m[prefix+".#"], 0, 0) 42 if err != nil { 43 panic(err) 44 } 45 46 // The Schema "Set" type stores its values in an array format, but using 47 // numeric hash values instead of ordinal keys. Take the set of keys 48 // regardless of value, and expand them in numeric order. 49 // See GH-11042 for more details. 50 keySet := map[int]bool{} 51 for k := range m { 52 if !strings.HasPrefix(k, prefix+".") { 53 continue 54 } 55 56 key := k[len(prefix)+1:] 57 idx := strings.Index(key, ".") 58 if idx != -1 { 59 key = key[:idx] 60 } 61 62 // skip the count value 63 if key == "#" { 64 continue 65 } 66 67 k, err := strconv.Atoi(key) 68 if err != nil { 69 panic(err) 70 } 71 keySet[int(k)] = true 72 } 73 74 keysList := make([]int, 0, num) 75 for key := range keySet { 76 keysList = append(keysList, key) 77 } 78 sort.Ints(keysList) 79 80 result := make([]interface{}, num) 81 for i, key := range keysList { 82 result[i] = Expand(m, fmt.Sprintf("%s.%d", prefix, key)) 83 } 84 85 return result 86 } 87 88 func expandMap(m map[string]string, prefix string) map[string]interface{} { 89 result := make(map[string]interface{}) 90 for k, _ := range m { 91 if !strings.HasPrefix(k, prefix) { 92 continue 93 } 94 95 key := k[len(prefix):] 96 idx := strings.Index(key, ".") 97 if idx != -1 { 98 key = key[:idx] 99 } 100 if _, ok := result[key]; ok { 101 continue 102 } 103 104 // skip the map count value 105 if key == "%" { 106 continue 107 } 108 result[key] = Expand(m, k[:len(prefix)+len(key)]) 109 } 110 111 return result 112 }