generated from crossplane/function-template-go
-
Notifications
You must be signed in to change notification settings - Fork 62
Expand file tree
/
Copy pathtemplate.go
More file actions
162 lines (131 loc) · 4.05 KB
/
template.go
File metadata and controls
162 lines (131 loc) · 4.05 KB
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package main
import (
"io/fs"
"path/filepath"
"strings"
"github.com/crossplane-contrib/function-go-templating/input/v1beta1"
"google.golang.org/protobuf/types/known/structpb"
"github.com/crossplane/function-sdk-go/errors"
)
const dotCharacter = 46
// TemplateGetter interface is used to read templates from different sources.
type TemplateGetter interface {
// GetTemplates returns the templates from the datasource
GetTemplates() string
}
// NewTemplateSourceGetter returns a TemplateGetter based on the cd source.
func NewTemplateSourceGetter(fsys fs.FS, ctx *structpb.Struct, in *v1beta1.GoTemplate) (TemplateGetter, error) {
switch in.Source {
case v1beta1.InlineSource:
return newInlineSource(in)
case v1beta1.FileSystemSource:
return newFileSource(fsys, in)
case v1beta1.EnvironmentSource:
return newEnvironmentSource(ctx, in)
case "":
return nil, errors.Errorf("source is required")
default:
return nil, errors.Errorf("invalid source: %s", in.Source)
}
}
// InlineSource is a datasource that reads a template from the composition.
type InlineSource struct {
Template string
}
// FileSource is a datasource that reads a template from a folder.
type FileSource struct {
FolderPath string
Template string
}
// EnvironmentSource is a datasource that reads a template from the environment.
type EnvironmentSource struct {
Key string
Template string
}
// GetTemplates returns the inline template.
func (is *InlineSource) GetTemplates() string {
return is.Template
}
func newInlineSource(in *v1beta1.GoTemplate) (*InlineSource, error) {
if in.Inline == nil || (in.Inline.Template == "" && len(in.Inline.Templates) == 0) {
return nil, errors.New("inline.template or inline.templates should be provided")
}
template := strings.Join(in.Inline.Templates, "\n---\n")
if in.Inline.Template != "" {
template = in.Inline.Template
}
return &InlineSource{
Template: template,
}, nil
}
// GetTemplates returns the templates in the folder.
func (fs *FileSource) GetTemplates() string {
return fs.Template
}
func newFileSource(fsys fs.FS, in *v1beta1.GoTemplate) (*FileSource, error) {
if in.FileSystem == nil || in.FileSystem.DirPath == "" {
return nil, errors.New("fileSystem.dirPath should be provided")
}
d := in.FileSystem.DirPath
tmpl, err := readTemplates(fsys, d)
if err != nil {
return nil, errors.Errorf("cannot read tmpl from the folder %s: %s", *in.FileSystem, err)
}
return &FileSource{
FolderPath: in.FileSystem.DirPath,
Template: tmpl,
}, nil
}
func (es *EnvironmentSource) GetTemplates() string {
return es.Template
}
func newEnvironmentSource(ctx *structpb.Struct, in *v1beta1.GoTemplate) (*EnvironmentSource, error) {
if in.Environment == nil || in.Environment.Key == "" {
return nil, errors.New("environment.key should be provided")
}
env, ok := ctx.AsMap()["apiextensions.crossplane.io/environment"].(map[string]any)
if !ok {
return nil, errors.New("cannot read tmpl from the environment: apiextensions.crossplane.io/environment key does not exist in context")
}
tpl, ok := env[in.Environment.Key]
if !ok {
return nil, errors.Errorf("cannot read tmpl from the environment: key: %s does not exist", in.Environment.Key)
}
t, err := tpl.(string)
if !err {
return nil, errors.Errorf("cannot read tmpl from the environment: key: %s value is not a string", in.Environment.Key)
}
return &EnvironmentSource{
Template: t,
}, nil
}
func readTemplates(fsys fs.FS, dir string) (string, error) {
tmpl := ""
if err := fs.WalkDir(fsys, dir, func(path string, dirEntry fs.DirEntry, e error) error {
if e != nil {
return e
}
// skip hidden directories
if dirEntry.IsDir() && dirEntry.Name()[0] == dotCharacter {
return filepath.SkipDir
}
info, err := dirEntry.Info()
if err != nil {
return err
}
// check for directory and hidden files/folders
if info.IsDir() || info.Name()[0] == dotCharacter {
return nil
}
data, err := fs.ReadFile(fsys, path)
if err != nil {
return err
}
tmpl += string(data)
tmpl += "\n---\n"
return nil
}); err != nil {
return "", err
}
return tmpl, nil
}