From f7526fef6e7c7bc001b5f6819945b420fcc28638 Mon Sep 17 00:00:00 2001 From: Justin Kulikauskas Date: Fri, 26 Apr 2024 11:58:24 -0400 Subject: [PATCH] Add resolve option to error on missing keys By default, the template engine uses "" when a key is missing from a lookup, and it does not return an error. That behavior can make it less obvious when something is going wrong in a template. Signed-off-by: Justin Kulikauskas --- pkg/templates/templates.go | 10 ++++++++++ pkg/templates/templates_test.go | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/pkg/templates/templates.go b/pkg/templates/templates.go index e8d03e3d..91d52d57 100644 --- a/pkg/templates/templates.go +++ b/pkg/templates/templates.go @@ -59,6 +59,7 @@ var ( ErrCacheDisabled = client.ErrCacheDisabled ErrNoCacheEntry = client.ErrNoCacheEntry ErrContextTransformerFailed = errors.New("the context transformer failed") + ErrMissingKey = errors.New("missing key while resolving template") ) // Config is a struct containing configuration for the API. @@ -121,6 +122,7 @@ type ResolveOptions struct { DisableAutoCacheCleanUp bool LookupNamespace string Watcher *client.ObjectIdentifier + ErrorOnMissingKey bool } type ClusterScopedObjectIdentifier struct { @@ -629,11 +631,19 @@ func (t *TemplateResolver) ResolveTemplate( } } + if options.ErrorOnMissingKey { + tmpl = tmpl.Option("missingkey=error") + } + err = tmpl.Execute(&buf, ctx) if err != nil { tmplRawStr := string(tmplRaw) klog.Errorf("error resolving the template %v,\n template str %v,\n error: %v", tmplRawStr, templateStr, err) + if options.ErrorOnMissingKey && strings.Contains(err.Error(), "no entry for key") { + return resolvedResult, fmt.Errorf("%w %v: %w", ErrMissingKey, tmplRawStr, err) + } + return resolvedResult, fmt.Errorf("failed to resolve the template %v: %w", tmplRawStr, err) } diff --git a/pkg/templates/templates_test.go b/pkg/templates/templates_test.go index 4e8c7328..8198ece1 100644 --- a/pkg/templates/templates_test.go +++ b/pkg/templates/templates_test.go @@ -725,6 +725,13 @@ func TestResolveTemplateErrors(t *testing.T) { ErrInvalidInput, ), }, + "error_on_missing_key": { + inputTmpl: `foo: '{{ (lookup "v1" "ConfigMap" "testns" "nonexist-cm").data }}'`, + resolveOptions: ResolveOptions{ + ErrorOnMissingKey: true, + }, + expectedErr: ErrMissingKey, + }, } for testName, test := range testcases {