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  }