Add template function for preferred version

This commit is contained in:
Ole Markus With 2020-12-05 15:00:40 +01:00
parent 2b0e84b432
commit 5fe948bb5c
6 changed files with 98 additions and 27 deletions

View File

@ -32,6 +32,7 @@ import (
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kops/cmd/kops/util"
kopsapi "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/try"
"k8s.io/kops/pkg/util/templater"
"k8s.io/kops/upup/pkg/fi/utils"
@ -68,6 +69,7 @@ type toolboxTemplateOption struct {
templatePath []string
values []string
stringValues []string
channel string
}
// NewCmdToolboxTemplate returns a new templating command
@ -96,6 +98,7 @@ func NewCmdToolboxTemplate(f *util.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringArrayVar(&options.stringValues, "set-string", options.stringValues, "Set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
cmd.Flags().StringSliceVar(&options.templatePath, "template", options.templatePath, "Path to template file or directory of templates to render")
cmd.Flags().StringSliceVar(&options.snippetsPath, "snippets", options.snippetsPath, "Path to directory containing snippets used for templating")
cmd.Flags().StringVar(&options.channel, "channel", options.channel, "Channel to use for the channel* functions")
cmd.Flags().StringVar(&options.outputPath, "output", options.outputPath, "Path to output file, otherwise defaults to stdout")
cmd.Flags().StringVar(&options.configValue, "config-value", "", "Show the value of a specific configuration value")
cmd.Flags().BoolVar(&options.failOnMissing, "fail-on-missing", true, "Fail on referencing unset variables in templates")
@ -158,8 +161,18 @@ func runToolBoxTemplate(f *util.Factory, out io.Writer, options *toolboxTemplate
}
}
channelLocation := ""
if channelLocation == "" {
channelLocation = kopsapi.DefaultChannel
}
channel, err := kopsapi.LoadChannel(channelLocation)
if err != nil {
return fmt.Errorf("error loading channel %q: %v", channelLocation, err)
}
// @step: render each of the templates, splitting on the documents
r := templater.NewTemplater()
r := templater.NewTemplater(channel)
var documents []string
for _, x := range templates {
content, err := ioutil.ReadFile(x)

View File

@ -29,6 +29,7 @@ kops toolbox template [flags]
### Options
```
--channel string Channel to use for the channel* functions
--config-value string Show the value of a specific configuration value
--fail-on-missing Fail on referencing unset variables in templates (default true)
--format-yaml Attempt to format the generated yaml content before output

View File

@ -2,10 +2,17 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["templater.go"],
srcs = [
"template_functions.go",
"templater.go",
],
importpath = "k8s.io/kops/pkg/util/templater",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/Masterminds/sprig/v3:go_default_library"],
deps = [
"//:go_default_library",
"//pkg/apis/kops:go_default_library",
"//vendor/github.com/Masterminds/sprig/v3:go_default_library",
],
)
go_test(
@ -15,6 +22,7 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/diff:go_default_library",
"//tests/integration/channel/simple:go_default_library",
"//vendor/gopkg.in/yaml.v2:go_default_library",
],
)

View File

@ -0,0 +1,48 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package templater
import (
"text/template"
"github.com/Masterminds/sprig/v3"
"k8s.io/kops"
kopsapi "k8s.io/kops/pkg/apis/kops"
)
// templateFuncsMap returns a map if the template functions for this template
func (r *Templater) templateFuncsMap(tm *template.Template) template.FuncMap {
// grab the template functions from sprig which are pretty awesome
funcs := sprig.TxtFuncMap()
funcs["indent"] = indentContent
// @step: as far as i can see there's no native way in sprig in include external snippets of code
funcs["include"] = func(name string, context map[string]interface{}) string {
content, err := includeSnippet(tm, name, context)
if err != nil {
panic(err.Error())
}
return content
}
funcs["ChannelRecommendedKubernetesVersion"] = func() string {
return kopsapi.RecommendedKubernetesVersion(r.channel, kops.Version).String()
}
return funcs
}

View File

@ -22,7 +22,7 @@ import (
"strings"
"text/template"
"github.com/Masterminds/sprig/v3"
"k8s.io/kops/pkg/apis/kops"
)
const (
@ -30,11 +30,15 @@ const (
)
// Templater is golang template renders
type Templater struct{}
type Templater struct {
channel *kops.Channel
}
// NewTemplater returns a new renderer implementation
func NewTemplater() *Templater {
return &Templater{}
func NewTemplater(channel *kops.Channel) *Templater {
return &Templater{
channel: channel,
}
}
// Render is responsible for actually rendering the template
@ -72,25 +76,6 @@ func (r *Templater) Render(content string, context map[string]interface{}, snipp
return writer.String(), nil
}
// templateFuncsMap returns a map if the template functions for this template
func (r *Templater) templateFuncsMap(tm *template.Template) template.FuncMap {
// grab the template functions from sprig which are pretty awesome
funcs := sprig.TxtFuncMap()
funcs["indent"] = indentContent
// @step: as far as i can see there's no native way in sprig in include external snippets of code
funcs["include"] = func(name string, context map[string]interface{}) string {
content, err := includeSnippet(tm, name, context)
if err != nil {
panic(err.Error())
}
return content
}
return funcs
}
// indentContent is responsible for indenting the string content
func indentContent(indent int, content string) string {
var b bytes.Buffer

View File

@ -21,6 +21,7 @@ import (
"testing"
"k8s.io/kops/pkg/diff"
"k8s.io/kops/tests/integration/channel/simple"
yaml "gopkg.in/yaml.v2"
)
@ -81,6 +82,17 @@ func TestRenderIndent(t *testing.T) {
makeRenderTests(t, cases)
}
func TestRenderChannelFunctions(t *testing.T) {
cases := []renderTest{
{
Context: map[string]interface{}{},
Template: `{{ ChannelRecommendedKubernetesVersion }}`,
Expected: "1.5.2",
},
}
makeRenderTests(t, cases)
}
func TestRenderSnippet(t *testing.T) {
cases := []renderTest{
{
@ -182,7 +194,11 @@ type renderTest struct {
}
func makeRenderTests(t *testing.T, tests []renderTest) {
r := NewTemplater()
channel, err := simple.NewMockChannel()
if err != nil {
t.Fatalf("could not load channel: %v", err)
}
r := NewTemplater(channel)
for i, x := range tests {
render, err := r.Render(x.Template, x.Context, x.Snippets, !x.DisableMissing)
if x.NotOK {