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
|
// Copyright 2021 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package framework
import (
"bytes"
"strings"
"text/template"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
// ResourceTemplate generates resources from templates.
type ResourceTemplate struct {
// Templates provides a list of templates to render into one or more resources.
Templates TemplateParser
// TemplateData is the data to use when rendering the templates provided by the Templates field.
TemplateData interface{}
}
type TemplateParser interface {
Parse() ([]*template.Template, error)
}
type TemplateParserFunc func() ([]*template.Template, error)
func (s TemplateParserFunc) Parse() ([]*template.Template, error) {
return s()
}
// DefaultTemplateData sets TemplateData to the provided default values if it has not already
// been set.
func (rt *ResourceTemplate) DefaultTemplateData(data interface{}) {
if rt.TemplateData == nil {
rt.TemplateData = data
}
}
// Render renders the Templates into resource nodes using TemplateData.
func (rt *ResourceTemplate) Render() ([]*yaml.RNode, error) {
var items []*yaml.RNode
if rt.Templates == nil {
return items, nil
}
templates, err := rt.Templates.Parse()
if err != nil {
return nil, errors.WrapPrefixf(err, "failed to retrieve ResourceTemplates")
}
for i := range templates {
newItems, err := rt.doTemplate(templates[i])
if err != nil {
return nil, err
}
items = append(items, newItems...)
}
return items, nil
}
func (rt *ResourceTemplate) doTemplate(t *template.Template) ([]*yaml.RNode, error) {
// invoke the template
var b bytes.Buffer
err := t.Execute(&b, rt.TemplateData)
if err != nil {
return nil, errors.WrapPrefixf(err, "failed to render template %v", t.DefinedTemplates())
}
var items []*yaml.RNode
// split the resources so the error messaging is better
for _, s := range strings.Split(b.String(), "\n---\n") {
s = strings.TrimSpace(s)
if s == "" {
continue
}
newItems, err := (&kio.ByteReader{Reader: bytes.NewBufferString(s)}).Read()
if err != nil {
return nil, errors.WrapPrefixf(err,
"failed to parse rendered template into a resource:\n%s\n", addLineNumbers(s))
}
items = append(items, newItems...)
}
return items, nil
}
|