-
Notifications
You must be signed in to change notification settings - Fork 21
/
template.go
84 lines (78 loc) · 2.54 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
package template
import (
"bytes"
"embed"
"io"
"io/fs"
"text/template"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/kubernetes/scheme"
)
// Variables contains all the available variables that are supported by the templates
type Variables struct {
Namespace string
}
// LoadObjectsFromEmbedFS loads all the kubernetes objects from an embedded filesystem and returns a list of Unstructured objects that can be applied in the cluster.
// The function will return all the objects it finds starting from the root of the embedded filesystem.
func LoadObjectsFromEmbedFS(efs *embed.FS, variables *Variables) ([]*unstructured.Unstructured, error) {
var objects []*unstructured.Unstructured
entries, err := getAllTemplateNames(efs)
if err != nil {
return objects, err
}
for _, templatePath := range entries {
templateContent, err := efs.ReadFile(templatePath)
if err != nil {
return objects, err
}
buf, err := replaceTemplateVariables(templatePath, templateContent, variables)
if err != nil {
return objects, err
}
decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewReader(buf.Bytes()), 100)
for {
var rawExt runtime.RawExtension
if err := decoder.Decode(&rawExt); err != nil {
if errors.Is(err, io.EOF) {
break
}
return objects, err
}
rawExt.Raw = bytes.TrimSpace(rawExt.Raw)
if len(rawExt.Raw) == 0 || bytes.Equal(rawExt.Raw, []byte("null")) {
continue
}
unstructuredObj := &unstructured.Unstructured{}
_, _, err = scheme.Codecs.UniversalDeserializer().Decode(rawExt.Raw, nil, unstructuredObj)
if err != nil {
return objects, err
}
objects = append(objects, unstructuredObj)
}
}
return objects, nil
}
// replaceTemplateVariables replaces all the variables in the given template and returns a buffer with the evaluated content
func replaceTemplateVariables(templateName string, templateContent []byte, variables *Variables) (bytes.Buffer, error) {
var buf bytes.Buffer
tmpl, err := template.New(templateName).Parse(string(templateContent))
if err != nil {
return buf, err
}
err = tmpl.Execute(&buf, variables)
return buf, err
}
// getAllTemplateNames reads the embedded filesystem and returns a list with all the filenames
func getAllTemplateNames(efs *embed.FS) (files []string, err error) {
err = fs.WalkDir(efs, ".", func(path string, d fs.DirEntry, err error) error {
if d.IsDir() {
return nil
}
files = append(files, path)
return nil
})
return files, err
}