github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/flatmap/flatten.go (about) 1 package flatmap 2 3 import ( 4 "fmt" 5 "reflect" 6 ) 7 8 // Flatten takes a structure and turns into a flat map[string]string. 9 // 10 // Within the "thing" parameter, only primitive values are allowed. Structs are 11 // not supported. Therefore, it can only be slices, maps, primitives, and 12 // any combination of those together. 13 // 14 // See the tests for examples of what inputs are turned into. 15 func Flatten(thing map[string]interface{}) Map { 16 result := make(map[string]string) 17 18 for k, raw := range thing { 19 flatten(result, k, reflect.ValueOf(raw)) 20 } 21 22 return Map(result) 23 } 24 25 func flatten(result map[string]string, prefix string, v reflect.Value) { 26 if v.Kind() == reflect.Interface { 27 v = v.Elem() 28 } 29 30 switch v.Kind() { 31 case reflect.Bool: 32 if v.Bool() { 33 result[prefix] = "true" 34 } else { 35 result[prefix] = "false" 36 } 37 case reflect.Int: 38 result[prefix] = fmt.Sprintf("%d", v.Int()) 39 case reflect.Map: 40 flattenMap(result, prefix, v) 41 case reflect.Slice: 42 flattenSlice(result, prefix, v) 43 case reflect.String: 44 result[prefix] = v.String() 45 default: 46 panic(fmt.Sprintf("Unknown: %s", v)) 47 } 48 } 49 50 func flattenMap(result map[string]string, prefix string, v reflect.Value) { 51 for _, k := range v.MapKeys() { 52 if k.Kind() == reflect.Interface { 53 k = k.Elem() 54 } 55 56 if k.Kind() != reflect.String { 57 panic(fmt.Sprintf("%s: map key is not string: %s", prefix, k)) 58 } 59 60 flatten(result, fmt.Sprintf("%s.%s", prefix, k.String()), v.MapIndex(k)) 61 } 62 } 63 64 func flattenSlice(result map[string]string, prefix string, v reflect.Value) { 65 prefix = prefix + "." 66 67 result[prefix+"#"] = fmt.Sprintf("%d", v.Len()) 68 for i := 0; i < v.Len(); i++ { 69 flatten(result, fmt.Sprintf("%s%d", prefix, i), v.Index(i)) 70 } 71 }