github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/terraform/flatten.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  )
     7  
     8  // remoteStateFlatten 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  // The difference between this version and the version in package flatmap is that
    15  // we add the count key for maps in this version, and return a normal
    16  // map[string]string instead of a flatmap.Map
    17  func remoteStateFlatten(thing map[string]interface{}) map[string]string {
    18  	result := make(map[string]string)
    19  
    20  	for k, raw := range thing {
    21  		flatten(result, k, reflect.ValueOf(raw))
    22  	}
    23  
    24  	return result
    25  }
    26  
    27  func flatten(result map[string]string, prefix string, v reflect.Value) {
    28  	if v.Kind() == reflect.Interface {
    29  		v = v.Elem()
    30  	}
    31  
    32  	switch v.Kind() {
    33  	case reflect.Bool:
    34  		if v.Bool() {
    35  			result[prefix] = "true"
    36  		} else {
    37  			result[prefix] = "false"
    38  		}
    39  	case reflect.Int:
    40  		result[prefix] = fmt.Sprintf("%d", v.Int())
    41  	case reflect.Map:
    42  		flattenMap(result, prefix, v)
    43  	case reflect.Slice:
    44  		flattenSlice(result, prefix, v)
    45  	case reflect.String:
    46  		result[prefix] = v.String()
    47  	default:
    48  		panic(fmt.Sprintf("Unknown: %s", v))
    49  	}
    50  }
    51  
    52  func flattenMap(result map[string]string, prefix string, v reflect.Value) {
    53  	mapKeys := v.MapKeys()
    54  
    55  	result[fmt.Sprintf("%s.%%", prefix)] = fmt.Sprintf("%d", len(mapKeys))
    56  	for _, k := range mapKeys {
    57  		if k.Kind() == reflect.Interface {
    58  			k = k.Elem()
    59  		}
    60  
    61  		if k.Kind() != reflect.String {
    62  			panic(fmt.Sprintf("%s: map key is not string: %s", prefix, k))
    63  		}
    64  
    65  		flatten(result, fmt.Sprintf("%s.%s", prefix, k.String()), v.MapIndex(k))
    66  	}
    67  }
    68  
    69  func flattenSlice(result map[string]string, prefix string, v reflect.Value) {
    70  	prefix = prefix + "."
    71  
    72  	result[prefix+"#"] = fmt.Sprintf("%d", v.Len())
    73  	for i := 0; i < v.Len(); i++ {
    74  		flatten(result, fmt.Sprintf("%s%d", prefix, i), v.Index(i))
    75  	}
    76  }