aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/flatmap
diff options
context:
space:
mode:
authorJake Champlin <jake.champlin.27@gmail.com>2017-06-06 12:40:07 -0400
committerJake Champlin <jake.champlin.27@gmail.com>2017-06-06 12:40:07 -0400
commitbae9f6d2fd5eb5bc80929bd393932b23f14d7c93 (patch)
treeca9ab12a7d78b1fc27a8f734729081357ce6d252 /vendor/github.com/hashicorp/terraform/flatmap
parent254c495b6bebab3fb72a243c4bce858d79e6ee99 (diff)
downloadterraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.tar.gz
terraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.tar.zst
terraform-provider-statuscake-bae9f6d2fd5eb5bc80929bd393932b23f14d7c93.zip
Initial transfer of provider code
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/flatmap')
-rw-r--r--vendor/github.com/hashicorp/terraform/flatmap/expand.go147
-rw-r--r--vendor/github.com/hashicorp/terraform/flatmap/flatten.go71
-rw-r--r--vendor/github.com/hashicorp/terraform/flatmap/map.go82
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 @@
1package flatmap
2
3import (
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.
14func 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
49func 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
116func 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 @@
1package flatmap
2
3import (
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.
15func 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
25func 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
50func 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
64func 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 @@
1package flatmap
2
3import (
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.
13type Map map[string]string
14
15// Contains returns true if the map contains the given key.
16func (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.
27func (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
45func (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.
72func (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}