diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/flatmap')
3 files changed, 300 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/flatmap/expand.go b/vendor/github.com/hashicorp/terraform/flatmap/expand.go new file mode 100644 index 0000000..e0b81b6 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/flatmap/expand.go | |||
@@ -0,0 +1,147 @@ | |||
1 | package flatmap | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "sort" | ||
6 | "strconv" | ||
7 | "strings" | ||
8 | |||
9 | "github.com/hashicorp/hil" | ||
10 | ) | ||
11 | |||
12 | // Expand takes a map and a key (prefix) and expands that value into | ||
13 | // a more complex structure. This is the reverse of the Flatten operation. | ||
14 | func Expand(m map[string]string, key string) interface{} { | ||
15 | // If the key is exactly a key in the map, just return it | ||
16 | if v, ok := m[key]; ok { | ||
17 | if v == "true" { | ||
18 | return true | ||
19 | } else if v == "false" { | ||
20 | return false | ||
21 | } | ||
22 | |||
23 | return v | ||
24 | } | ||
25 | |||
26 | // Check if the key is an array, and if so, expand the array | ||
27 | if v, ok := m[key+".#"]; ok { | ||
28 | // If the count of the key is unknown, then just put the unknown | ||
29 | // value in the value itself. This will be detected by Terraform | ||
30 | // core later. | ||
31 | if v == hil.UnknownValue { | ||
32 | return v | ||
33 | } | ||
34 | |||
35 | return expandArray(m, key) | ||
36 | } | ||
37 | |||
38 | // Check if this is a prefix in the map | ||
39 | prefix := key + "." | ||
40 | for k := range m { | ||
41 | if strings.HasPrefix(k, prefix) { | ||
42 | return expandMap(m, prefix) | ||
43 | } | ||
44 | } | ||
45 | |||
46 | return nil | ||
47 | } | ||
48 | |||
49 | func expandArray(m map[string]string, prefix string) []interface{} { | ||
50 | num, err := strconv.ParseInt(m[prefix+".#"], 0, 0) | ||
51 | if err != nil { | ||
52 | panic(err) | ||
53 | } | ||
54 | |||
55 | // If the number of elements in this array is 0, then return an | ||
56 | // empty slice as there is nothing to expand. Trying to expand it | ||
57 | // anyway could lead to crashes as any child maps, arrays or sets | ||
58 | // that no longer exist are still shown as empty with a count of 0. | ||
59 | if num == 0 { | ||
60 | return []interface{}{} | ||
61 | } | ||
62 | |||
63 | // The Schema "Set" type stores its values in an array format, but | ||
64 | // using numeric hash values instead of ordinal keys. Take the set | ||
65 | // of keys regardless of value, and expand them in numeric order. | ||
66 | // See GH-11042 for more details. | ||
67 | keySet := map[int]bool{} | ||
68 | computed := map[string]bool{} | ||
69 | for k := range m { | ||
70 | if !strings.HasPrefix(k, prefix+".") { | ||
71 | continue | ||
72 | } | ||
73 | |||
74 | key := k[len(prefix)+1:] | ||
75 | idx := strings.Index(key, ".") | ||
76 | if idx != -1 { | ||
77 | key = key[:idx] | ||
78 | } | ||
79 | |||
80 | // skip the count value | ||
81 | if key == "#" { | ||
82 | continue | ||
83 | } | ||
84 | |||
85 | // strip the computed flag if there is one | ||
86 | if strings.HasPrefix(key, "~") { | ||
87 | key = key[1:] | ||
88 | computed[key] = true | ||
89 | } | ||
90 | |||
91 | k, err := strconv.Atoi(key) | ||
92 | if err != nil { | ||
93 | panic(err) | ||
94 | } | ||
95 | keySet[int(k)] = true | ||
96 | } | ||
97 | |||
98 | keysList := make([]int, 0, num) | ||
99 | for key := range keySet { | ||
100 | keysList = append(keysList, key) | ||
101 | } | ||
102 | sort.Ints(keysList) | ||
103 | |||
104 | result := make([]interface{}, num) | ||
105 | for i, key := range keysList { | ||
106 | keyString := strconv.Itoa(key) | ||
107 | if computed[keyString] { | ||
108 | keyString = "~" + keyString | ||
109 | } | ||
110 | result[i] = Expand(m, fmt.Sprintf("%s.%s", prefix, keyString)) | ||
111 | } | ||
112 | |||
113 | return result | ||
114 | } | ||
115 | |||
116 | func expandMap(m map[string]string, prefix string) map[string]interface{} { | ||
117 | // Submaps may not have a '%' key, so we can't count on this value being | ||
118 | // here. If we don't have a count, just proceed as if we have have a map. | ||
119 | if count, ok := m[prefix+"%"]; ok && count == "0" { | ||
120 | return map[string]interface{}{} | ||
121 | } | ||
122 | |||
123 | result := make(map[string]interface{}) | ||
124 | for k := range m { | ||
125 | if !strings.HasPrefix(k, prefix) { | ||
126 | continue | ||
127 | } | ||
128 | |||
129 | key := k[len(prefix):] | ||
130 | idx := strings.Index(key, ".") | ||
131 | if idx != -1 { | ||
132 | key = key[:idx] | ||
133 | } | ||
134 | if _, ok := result[key]; ok { | ||
135 | continue | ||
136 | } | ||
137 | |||
138 | // skip the map count value | ||
139 | if key == "%" { | ||
140 | continue | ||
141 | } | ||
142 | |||
143 | result[key] = Expand(m, k[:len(prefix)+len(key)]) | ||
144 | } | ||
145 | |||
146 | return result | ||
147 | } | ||
diff --git a/vendor/github.com/hashicorp/terraform/flatmap/flatten.go b/vendor/github.com/hashicorp/terraform/flatmap/flatten.go new file mode 100644 index 0000000..9ff6e42 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/flatmap/flatten.go | |||
@@ -0,0 +1,71 @@ | |||
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 | } | ||
diff --git a/vendor/github.com/hashicorp/terraform/flatmap/map.go b/vendor/github.com/hashicorp/terraform/flatmap/map.go new file mode 100644 index 0000000..46b72c4 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/flatmap/map.go | |||
@@ -0,0 +1,82 @@ | |||
1 | package flatmap | ||
2 | |||
3 | import ( | ||
4 | "strings" | ||
5 | ) | ||
6 | |||
7 | // Map is a wrapper around map[string]string that provides some helpers | ||
8 | // above it that assume the map is in the format that flatmap expects | ||
9 | // (the result of Flatten). | ||
10 | // | ||
11 | // All modifying functions such as Delete are done in-place unless | ||
12 | // otherwise noted. | ||
13 | type Map map[string]string | ||
14 | |||
15 | // Contains returns true if the map contains the given key. | ||
16 | func (m Map) Contains(key string) bool { | ||
17 | for _, k := range m.Keys() { | ||
18 | if k == key { | ||
19 | return true | ||
20 | } | ||
21 | } | ||
22 | |||
23 | return false | ||
24 | } | ||
25 | |||
26 | // Delete deletes a key out of the map with the given prefix. | ||
27 | func (m Map) Delete(prefix string) { | ||
28 | for k, _ := range m { | ||
29 | match := k == prefix | ||
30 | if !match { | ||
31 | if !strings.HasPrefix(k, prefix) { | ||
32 | continue | ||
33 | } | ||
34 | |||
35 | if k[len(prefix):len(prefix)+1] != "." { | ||
36 | continue | ||
37 | } | ||
38 | } | ||
39 | |||
40 | delete(m, k) | ||
41 | } | ||
42 | } | ||
43 | |||
44 | // Keys returns all of the top-level keys in this map | ||
45 | func (m Map) Keys() []string { | ||
46 | ks := make(map[string]struct{}) | ||
47 | for k, _ := range m { | ||
48 | idx := strings.Index(k, ".") | ||
49 | if idx == -1 { | ||
50 | idx = len(k) | ||
51 | } | ||
52 | |||
53 | ks[k[:idx]] = struct{}{} | ||
54 | } | ||
55 | |||
56 | result := make([]string, 0, len(ks)) | ||
57 | for k, _ := range ks { | ||
58 | result = append(result, k) | ||
59 | } | ||
60 | |||
61 | return result | ||
62 | } | ||
63 | |||
64 | // Merge merges the contents of the other Map into this one. | ||
65 | // | ||
66 | // This merge is smarter than a simple map iteration because it | ||
67 | // will fully replace arrays and other complex structures that | ||
68 | // are present in this map with the other map's. For example, if | ||
69 | // this map has a 3 element "foo" list, and m2 has a 2 element "foo" | ||
70 | // list, then the result will be that m has a 2 element "foo" | ||
71 | // list. | ||
72 | func (m Map) Merge(m2 Map) { | ||
73 | for _, prefix := range m2.Keys() { | ||
74 | m.Delete(prefix) | ||
75 | |||
76 | for k, v := range m2 { | ||
77 | if strings.HasPrefix(k, prefix) { | ||
78 | m[k] = v | ||
79 | } | ||
80 | } | ||
81 | } | ||
82 | } | ||