Files
kustomize/kyaml/fn/framework/template.go
Katrina Verey 5c4b5b1bf0 Improvements to kyaml fn framework
This commit creates a new version of the alpha configuration functions framework. Goals include:
- Make it easy to build multi-version APIs with the framework (not previously facilitated at all).
- Simplify the framework's APIs where redundant configuration options exist (leaving the most powerful, replacing others with helpers to maintain usability they provided).
- Make the Framework's APIs more consistent (e.g. between the various template types, usage of kio.Filter, field names)
- Decouple responsibilities (e.g. command creation, resource list processing, generation of templating functions).
- Make the framework even more powerfully pluggable (e.g. any kio.Filter can be a selector, and the selector the framework provides is itself a filter built from reusable abstractions).
- Improve documentation.
- Make container patches merge fields (notably list fields like `env`) correctly.
2021-03-03 08:27:19 -08:00

81 lines
2.1 KiB
Go

// 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 is a function that returns a list of templates to render into one or more resources.
Templates TemplatesFunc
// TemplateData is the data to use when rendering the templates provided by the Templates field.
TemplateData interface{}
}
// 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()
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
}