/
mod_variable_map.go
123 lines (106 loc) · 3.63 KB
/
mod_variable_map.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
package modconfig
import (
"github.com/turbot/pipe-fittings/hclhelpers"
"github.com/turbot/pipe-fittings/utils"
)
// ModVariableMap is a struct containing maps of variable definitions
type ModVariableMap struct {
// which mod have these variables been loaded for?
Mod *Mod
// top level variables, keyed by short name
RootVariables map[string]*Variable
// map of dependency variable maps, keyed by dependency NAME
DependencyVariables map[string]*ModVariableMap
// a list of the pointers to the variables whose values can be changed
// NOTE: this refers to the SAME variable objects as exist in the RootVariables and DependencyVariables maps,
// so when we set the value of public variables, we mutate the underlying variable
PublicVariables map[string]*Variable
}
// NewModVariableMap builds a ModVariableMap using the variables from a mod and its dependencies
func NewModVariableMap(mod *Mod) (*ModVariableMap, error) {
m := &ModVariableMap{
Mod: mod,
RootVariables: make(map[string]*Variable),
DependencyVariables: make(map[string]*ModVariableMap),
}
// add variables into map, modifying the key to be the variable short name
for name, variable := range mod.ResourceMaps.Variables {
if variable.Mod.ShortName != mod.ShortName {
continue
}
k, err := buildVariableMapKey(name)
if err != nil {
return nil, err
}
m.RootVariables[k] = variable
}
// now traverse all dependency mods
for _, depMod := range mod.ResourceMaps.Mods {
// todo for some reason the mod appears in its own resource maps?
if depMod.Name() != mod.Name() {
depMap, err := NewModVariableMap(depMod)
if err != nil {
return nil, err
}
m.DependencyVariables[depMod.DependencyName] = depMap
}
}
// build map of all publicly settable variables
m.PopulatePublicVariables()
return m, nil
}
func (m *ModVariableMap) ToArray() []*Variable {
var res []*Variable
keys := utils.SortedMapKeys(m.RootVariables)
for _, k := range keys {
res = append(res, m.RootVariables[k])
}
for _, depVariables := range m.DependencyVariables {
keys := utils.SortedMapKeys(depVariables.RootVariables)
for _, k := range keys {
res = append(res, depVariables.RootVariables[k])
}
}
return res
}
// build map key for root variables - they are keyed by short name
// to allow the user to set their value using the short name
func buildVariableMapKey(k string) (string, error) {
parsed, err := ParseResourceName(k)
if err != nil {
return "", err
}
return parsed.Name, nil
}
// PopulatePublicVariables builds a map of top level and dependency variables
// (dependency variables are keyed by full (qualified) name
func (m *ModVariableMap) PopulatePublicVariables() {
res := make(map[string]*Variable)
for k, v := range m.RootVariables {
// add top level vars keyed by short name
res[k] = v
}
// copy ROOT variables for each top level dependency
for _, depVars := range m.DependencyVariables {
for _, v := range depVars.RootVariables {
// add dependency vars keyed by full name
res[v.FullName] = v
}
}
m.PublicVariables = res
}
// GetPublicVariableValues converts public variables into a map of string variable values
func (m *ModVariableMap) GetPublicVariableValues() (map[string]string, error) {
utils.LogTime("GetPublicVariableValues")
defer utils.LogTime("GetPublicVariableValues end")
res := make(map[string]string, len(m.PublicVariables))
for k, v := range m.PublicVariables {
// TODO investigate workspace usage of value string and determine whether we can simply format ValueGo
valueString, err := hclhelpers.CtyToString(v.Value)
if err != nil {
return nil, err
}
res[k] = valueString
}
return res, nil
}