forked from hashicorp/terraform
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexpand.go
132 lines (111 loc) · 2.67 KB
/
expand.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package flatmap
import (
"fmt"
"sort"
"strconv"
"strings"
"github.com/hashicorp/hil"
)
// Expand takes a map and a key (prefix) and expands that value into
// a more complex structure. This is the reverse of the Flatten operation.
func Expand(m map[string]string, key string) interface{} {
// If the key is exactly a key in the map, just return it
if v, ok := m[key]; ok {
if v == "true" {
return true
} else if v == "false" {
return false
}
return v
}
// Check if the key is an array, and if so, expand the array
if v, ok := m[key+".#"]; ok {
// If the count of the key is unknown, then just put the unknown
// value in the value itself. This will be detected by Terraform
// core later.
if v == hil.UnknownValue {
return v
}
return expandArray(m, key)
}
// Check if this is a prefix in the map
prefix := key + "."
for k, _ := range m {
if strings.HasPrefix(k, prefix) {
return expandMap(m, prefix)
}
}
return nil
}
func expandArray(m map[string]string, prefix string) []interface{} {
num, err := strconv.ParseInt(m[prefix+".#"], 0, 0)
if err != nil {
panic(err)
}
// The Schema "Set" type stores its values in an array format, but using
// numeric hash values instead of ordinal keys. Take the set of keys
// regardless of value, and expand them in numeric order.
// See GH-11042 for more details.
keySet := map[int]bool{}
computed := map[string]bool{}
for k := range m {
if !strings.HasPrefix(k, prefix+".") {
continue
}
key := k[len(prefix)+1:]
idx := strings.Index(key, ".")
if idx != -1 {
key = key[:idx]
}
// skip the count value
if key == "#" {
continue
}
// strip the computed flag if there is one
if strings.HasPrefix(key, "~") {
key = key[1:]
computed[key] = true
}
k, err := strconv.Atoi(key)
if err != nil {
panic(err)
}
keySet[int(k)] = true
}
keysList := make([]int, 0, num)
for key := range keySet {
keysList = append(keysList, key)
}
sort.Ints(keysList)
result := make([]interface{}, num)
for i, key := range keysList {
keyString := strconv.Itoa(key)
if computed[keyString] {
keyString = "~" + keyString
}
result[i] = Expand(m, fmt.Sprintf("%s.%s", prefix, keyString))
}
return result
}
func expandMap(m map[string]string, prefix string) map[string]interface{} {
result := make(map[string]interface{})
for k, _ := range m {
if !strings.HasPrefix(k, prefix) {
continue
}
key := k[len(prefix):]
idx := strings.Index(key, ".")
if idx != -1 {
key = key[:idx]
}
if _, ok := result[key]; ok {
continue
}
// skip the map count value
if key == "%" {
continue
}
result[key] = Expand(m, k[:len(prefix)+len(key)])
}
return result
}