forked from hashicorp/consul-template
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtemplate.go
114 lines (98 loc) · 3.24 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
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
package main
import (
"bytes"
"fmt"
"io/ioutil"
"path/filepath"
"text/template"
dep "github.com/hashicorp/consul-template/dependency"
)
type Template struct {
// Path is the path to this template on disk.
Path string
// contents is string contents for this file when read from disk.
contents string
}
// NewTemplate creates and parses a new Consul Template template at the given
// path. If the template does not exist, an error is returned. During
// initialization, the template is read and is parsed for dependencies. Any
// errors that occur are returned.
func NewTemplate(path string) (*Template, error) {
template := &Template{Path: path}
if err := template.init(); err != nil {
return nil, err
}
return template, nil
}
// Execute evaluates this template in the context of the given brain.
//
// The first return value is the list of used dependencies.
// The second return value is the list of missing dependencies.
// The third return value is the rendered text.
// The fourth return value any error that occurs.
func (t *Template) Execute(brain *Brain) ([]dep.Dependency, []dep.Dependency, []byte, error) {
usedMap := make(map[string]dep.Dependency)
missingMap := make(map[string]dep.Dependency)
name := filepath.Base(t.Path)
funcs := funcMap(brain, usedMap, missingMap)
tmpl, err := template.New(name).Funcs(funcs).Parse(t.contents)
if err != nil {
return nil, nil, nil, fmt.Errorf("template: %s", err)
}
// TODO: accept an io.Writer instead
buff := new(bytes.Buffer)
if err := tmpl.Execute(buff, nil); err != nil {
return nil, nil, nil, fmt.Errorf("template: %s", err)
}
// Update this list of this template's dependencies
var used []dep.Dependency
for _, dep := range usedMap {
used = append(used, dep)
}
// Compile the list of missing dependencies
var missing []dep.Dependency
for _, dep := range missingMap {
missing = append(missing, dep)
}
return used, missing, buff.Bytes(), nil
}
// init reads the template file and initializes required variables.
func (t *Template) init() error {
// Render the template
contents, err := ioutil.ReadFile(t.Path)
if err != nil {
return err
}
t.contents = string(contents)
return nil
}
// funcMap is the map of template functions to their respective functions.
func funcMap(brain *Brain, used, missing map[string]dep.Dependency) template.FuncMap {
return template.FuncMap{
// API functions
"datacenters": datacentersFunc(brain, used, missing),
"file": fileFunc(brain, used, missing),
"key": keyFunc(brain, used, missing),
"ls": lsFunc(brain, used, missing),
"nodes": nodesFunc(brain, used, missing),
"service": serviceFunc(brain, used, missing),
"services": servicesFunc(brain, used, missing),
"tree": treeFunc(brain, used, missing),
"vault": vaultFunc(brain, used, missing),
// Helper functions
"byKey": byKey,
"byTag": byTag,
"env": env,
"loop": loop,
"join": join,
"parseJSON": parseJSON,
"regexReplaceAll": regexReplaceAll,
"regexMatch": regexMatch,
"replaceAll": replaceAll,
"timestamp": timestamp,
"toLower": toLower,
"toTitle": toTitle,
"toUpper": toUpper,
"split": split,
}
}