-
Notifications
You must be signed in to change notification settings - Fork 3
/
template.go
90 lines (72 loc) · 1.96 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
package junocfg
import (
"bufio"
"bytes"
"fmt"
"regexp"
"strings"
"text/template"
"gopkg.in/yaml.v2"
)
func CheckTemplate(tmpl []byte) (*template.Template, error) {
helpers := template.FuncMap{
"copy": copyFunc(bytes.NewBuffer([]byte{})),
}
t, err := template.New("template").Funcs(helpers).Parse(string(tmpl))
return t, err
}
func RenderAndCheckTemplate(tmpl []byte, settingsMap map[string]interface{}) (string, error) {
buffer := bytes.NewBuffer([]byte{})
helpers := template.FuncMap{
"copy": copyFunc(buffer),
}
t, err := template.New("template").Funcs(helpers).Parse(string(tmpl))
if err != nil {
return "", fmt.Errorf("check template failed [%s]\n", err)
}
if err := t.Execute(buffer, settingsMap); err != nil {
return "", fmt.Errorf("failed to render template [%s]\n", err)
}
buffer = PreprocessYaml(buffer)
// check yaml
if err = CheckYaml(buffer.Bytes()); err != nil {
fmt.Printf("%s\n", buffer.Bytes())
return "", fmt.Errorf("Not valid output yaml: %s\n", err.Error())
}
return buffer.String(), nil
}
//copy returns a template helper that is aware of it's current indent
//and copies given data to the result YAML according to this indent
func copyFunc(buf *bytes.Buffer) func(interface{}) (string, error) {
return func(in interface{}) (result string, err error) {
b, err := yaml.Marshal(in)
if err != nil {
return "", err
}
indent, err := indent(buf)
if err != nil {
return "", err
}
rr := []string{}
scanner := bufio.NewScanner(bytes.NewBuffer(b))
for scanner.Scan() {
rr = append(rr, scanner.Text()+"\n")
}
return strings.Join(rr, indent), scanner.Err()
}
}
var rxSpaces = regexp.MustCompile("^\\s*$")
func indent(b *bytes.Buffer) (string, error) {
var line string
scanner := bufio.NewScanner(bytes.NewBuffer(b.Bytes()))
for scanner.Scan() {
line = scanner.Text()
}
if err := scanner.Err(); err != nil {
return "", err
}
if rxSpaces.MatchString(line) {
return line, nil
}
return "", nil
}