From 5cf9d53e80accaeede1b4e38772d7d53c0190549 Mon Sep 17 00:00:00 2001 From: Phillip Johnsen Date: Wed, 30 May 2018 21:43:31 +0200 Subject: [PATCH] feat(context): allow explicit variables to be defined as argument These changes allows variables to be defined when executing `kontemplate` via one or more `--variable` arguments. With this in place one can either define new variables or override existing variables loaded from a file: ``` $ kontemplate apply --variable version=v1.0 example/fancy-app.yaml ``` This avoids the need to write variables into a temporary file that is only needed to provide "external variables" into resource sets. Closes https://github.com/tazjin/kontemplate/issues/122 --- context/context.go | 21 +++++++++++++++++++++ context/context_test.go | 22 ++++++++++++++++++++++ main.go | 6 ++++++ 3 files changed, 49 insertions(+) diff --git a/context/context.go b/context/context.go index 9996f31fa..1a2e5c88c 100644 --- a/context/context.go +++ b/context/context.go @@ -12,6 +12,7 @@ package context import ( "fmt" "path" + "strings" "github.com/tazjin/kontemplate/util" ) @@ -158,3 +159,23 @@ func loadDefaultValues(rs *ResourceSet, c *Context) *map[string]interface{} { // errors here. return &rs.Values } + +// New variables can be defined or default values overridden with command line arguments when executing kontemplate. +func (ctx *Context) SetVariablesFromArguments(vars *[]string) error { + // Resource set files might not have defined any global variables, if so we have to + // create that a map before potentially writing variables into it + if ctx.Global == nil { + ctx.Global = make(map[string]interface{}, len(*vars)) + } + + for _, v := range *vars { + varParts := strings.Split(v, "=") + if len(varParts) != 2 { + return fmt.Errorf(`invalid explicit variable provided (%s), name and value should be divided with "="`, v) + } + + ctx.Global[varParts[0]] = varParts[1] + } + + return nil +} diff --git a/context/context_test.go b/context/context_test.go index 38b6a76e7..6dc27466a 100644 --- a/context/context_test.go +++ b/context/context_test.go @@ -280,3 +280,25 @@ func TestExplicitSubresourcePathLoading(t *testing.T) { t.Fail() } } + +func TestSetVariablesFromArguments(t *testing.T) { + vars := []string{"version=some-service-version"} + ctx, _ := LoadContextFromFile("testdata/default-loading.yaml") + + if err := ctx.SetVariablesFromArguments(&vars); err != nil { + t.Error(err) + } + + if version := ctx.Global["version"]; version != "some-service-version" { + t.Errorf(`Expected variable "version" to have value "some-service-version" but was "%s"`, version) + } +} + +func TestSetInvalidVariablesFromArguments(t *testing.T) { + vars := []string{"version: some-service-version"} + ctx, _ := LoadContextFromFile("testdata/default-loading.yaml") + + if err := ctx.SetVariablesFromArguments(&vars); err == nil { + t.Error("Expected invalid variable to return an error") + } +} diff --git a/main.go b/main.go index 13aabd248..ee70bdae5 100644 --- a/main.go +++ b/main.go @@ -37,6 +37,7 @@ var ( // Global flags includes = app.Flag("include", "Resource sets to include explicitly").Short('i').Strings() excludes = app.Flag("exclude", "Resource sets to exclude explicitly").Short('e').Strings() + variables = app.Flag("var", "Provide variables to templates explicitly").Strings() // Commands template = app.Command("template", "Template resource sets and print them") @@ -188,6 +189,11 @@ func loadContextAndResources(file *string) (*context.Context, *[]templater.Rende app.Fatalf("Error loading context: %v\n", err) } + err = ctx.SetVariablesFromArguments(variables) + if err != nil { + app.Fatalf("Error setting explicit variables in context: %v\n", err) + } + resources, err := templater.LoadAndApplyTemplates(includes, excludes, ctx) if err != nil { app.Fatalf("Error templating resource sets: %v\n", err)