forked from hashicorp/terraform
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexpand.go
121 lines (101 loc) · 2.42 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
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{}
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
}
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 {
result[i] = Expand(m, fmt.Sprintf("%s.%d", prefix, key))
}
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
}