forked from cloudfoundry/bosh-cli
/
template.go
80 lines (68 loc) · 1.63 KB
/
template.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
package template
import (
"gopkg.in/yaml.v2"
"regexp"
)
var templateFormatRegex = regexp.MustCompile(`^\(\(([-\w\p{L}]+)\)\)$`)
type Template struct {
bytes []byte
}
func NewTemplate(bytes []byte) Template {
return Template{bytes: bytes}
}
func (t Template) Evaluate(vars Variables) ([]byte, error) {
var templateYaml interface{}
err := yaml.Unmarshal(t.bytes, &templateYaml)
if err != nil {
return []byte{}, err
}
compiledTemplate := t.interpolate(templateYaml, vars)
bytes, err := yaml.Marshal(compiledTemplate)
if err != nil {
return []byte{}, err
}
return bytes, nil
}
func (t Template) interpolate(node interface{}, vars Variables) interface{} {
switch node.(type) {
case map[interface{}]interface{}:
nodeMap := node.(map[interface{}]interface{})
for k, v := range nodeMap {
evaluatedValue := t.interpolate(v, vars)
keyAsString, ok := k.(string)
if ok {
newKey, ok := t.needsEvaluation(keyAsString)
if ok {
foundVarKey, exists := vars[newKey]
if exists {
delete(nodeMap, k)
k = foundVarKey
}
}
}
nodeMap[k] = evaluatedValue
}
case []interface{}:
nodeArray := node.([]interface{})
for i, x := range nodeArray {
nodeArray[i] = t.interpolate(x, vars)
}
case string:
key, found := t.needsEvaluation(node.(string))
if found {
foundVar, exists := vars[key]
if exists {
return foundVar
}
}
default:
}
return node
}
func (t Template) needsEvaluation(value string) (string, bool) {
found := templateFormatRegex.FindAllSubmatch([]byte(value), 1)
if len(found) != 0 && len(found[0]) != 0 {
return string(found[0][1]), true
}
return "", false
}