From d4bb20976fcf097e651d5c841c1c9a7325130403 Mon Sep 17 00:00:00 2001 From: Ralf Pannemans Date: Mon, 8 May 2023 16:24:24 +0200 Subject: [PATCH] feat(helmExecute): Allow custom delimiter (#4312) Co-authored-by: Ralf Pannemans Co-authored-by: Johannes Dillmann Co-authored-by: Jan von Loewenstein --- cmd/helmExecute.go | 2 +- cmd/helmExecute_generated.go | 22 ++++++++++++++++++++++ pkg/piperenv/templating.go | 9 ++++++++- pkg/piperenv/templating_test.go | 29 +++++++++++++++++++++++++++++ resources/metadata/helmExecute.yaml | 14 ++++++++++++++ 5 files changed, 74 insertions(+), 2 deletions(-) diff --git a/cmd/helmExecute.go b/cmd/helmExecute.go index 51175c0065..c918a907ac 100644 --- a/cmd/helmExecute.go +++ b/cmd/helmExecute.go @@ -175,7 +175,7 @@ func parseAndRenderCPETemplate(config helmExecuteOptions, rootPath string, utils if err != nil { return fmt.Errorf("failed to read file: %v", err) } - generated, err := cpe.ParseTemplate(string(cpeTemplate)) + generated, err := cpe.ParseTemplateWithDelimiter(string(cpeTemplate), config.TemplateStartDelimiter, config.TemplateEndDelimiter) if err != nil { return fmt.Errorf("failed to parse template: %v", err) } diff --git a/cmd/helmExecute_generated.go b/cmd/helmExecute_generated.go index 1d12b8f6fe..936b64ae84 100644 --- a/cmd/helmExecute_generated.go +++ b/cmd/helmExecute_generated.go @@ -46,6 +46,8 @@ type helmExecuteOptions struct { Publish bool `json:"publish,omitempty"` Version string `json:"version,omitempty"` RenderSubchartNotes bool `json:"renderSubchartNotes,omitempty"` + TemplateStartDelimiter string `json:"templateStartDelimiter,omitempty"` + TemplateEndDelimiter string `json:"templateEndDelimiter,omitempty"` } type helmExecuteCommonPipelineEnvironment struct { @@ -226,6 +228,8 @@ func addHelmExecuteFlags(cmd *cobra.Command, stepConfig *helmExecuteOptions) { cmd.Flags().BoolVar(&stepConfig.Publish, "publish", false, "Configures helm to run the deploy command to publish artifacts to a repository.") cmd.Flags().StringVar(&stepConfig.Version, "version", os.Getenv("PIPER_version"), "Defines the artifact version to use from helm package/publish commands.") cmd.Flags().BoolVar(&stepConfig.RenderSubchartNotes, "renderSubchartNotes", true, "If set, render subchart notes along with the parent.") + cmd.Flags().StringVar(&stepConfig.TemplateStartDelimiter, "templateStartDelimiter", `{{`, "When templating value files, use this start delimiter.") + cmd.Flags().StringVar(&stepConfig.TemplateEndDelimiter, "templateEndDelimiter", `}}`, "When templating value files, use this end delimiter.") cmd.MarkFlagRequired("image") } @@ -606,6 +610,24 @@ func helmExecuteMetadata() config.StepData { Aliases: []config.Alias{}, Default: true, }, + { + Name: "templateStartDelimiter", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"STEPS", "PARAMETERS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: `{{`, + }, + { + Name: "templateEndDelimiter", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"STEPS", "PARAMETERS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: `}}`, + }, }, }, Containers: []config.Container{ diff --git a/pkg/piperenv/templating.go b/pkg/piperenv/templating.go index 9bfa6d9f01..51f392d679 100644 --- a/pkg/piperenv/templating.go +++ b/pkg/piperenv/templating.go @@ -7,9 +7,16 @@ import ( "text/template" ) +const DEFAULT_START_DELIMITER = "{{" +const DEFAULT_END_DELIMITER = "}}" + // ParseTemplate allows to parse a template which contains references to the CPE // Utility functions make it simple to access specific parts of the CPE func (c *CPEMap) ParseTemplate(cpeTemplate string) (*bytes.Buffer, error) { + return c.ParseTemplateWithDelimiter(cpeTemplate, DEFAULT_START_DELIMITER, DEFAULT_END_DELIMITER) +} + +func (c *CPEMap) ParseTemplateWithDelimiter(cpeTemplate string, startDelimiter string, endDelimiter string) (*bytes.Buffer, error) { funcMap := template.FuncMap{ "cpe": c.cpe, "cpecustom": c.custom, @@ -21,7 +28,7 @@ func (c *CPEMap) ParseTemplate(cpeTemplate string) (*bytes.Buffer, error) { // This requires alignment on artifact handling before, though } - tmpl, err := template.New("cpetemplate").Funcs(funcMap).Parse(cpeTemplate) + tmpl, err := template.New("cpetemplate").Delims(startDelimiter, endDelimiter).Funcs(funcMap).Parse(cpeTemplate) if err != nil { return nil, fmt.Errorf("failed to parse cpe template '%v': %w", cpeTemplate, err) } diff --git a/pkg/piperenv/templating_test.go b/pkg/piperenv/templating_test.go index 8d6433ee51..5237804d1e 100644 --- a/pkg/piperenv/templating_test.go +++ b/pkg/piperenv/templating_test.go @@ -40,6 +40,35 @@ func TestParseTemplate(t *testing.T) { } } +func TestParseTemplateWithDelimiter(t *testing.T) { + tt := []struct { + template string + cpe CPEMap + expected string + expectedError error + }{ + {template: `version: [[index .CPE "artifactVersion"]], sha: [[git "commitId"]]`, expected: "version: 1.2.3, sha: thisIsMyTestSha"}, + {template: "version: [[", expectedError: fmt.Errorf("failed to parse cpe template 'version: [['")}, + {template: `version: [[index .CPE "artifactVersion"]], release: {{ .RELEASE }}`, expected: "version: 1.2.3, release: {{ .RELEASE }}"}, + } + + cpe := CPEMap{ + "artifactVersion": "1.2.3", + "git/commitId": "thisIsMyTestSha", + } + + for _, test := range tt { + res, err := cpe.ParseTemplateWithDelimiter(test.template, "[[", "]]") + if test.expectedError != nil { + assert.Contains(t, fmt.Sprint(err), fmt.Sprint(test.expectedError)) + } else { + assert.NoError(t, err) + assert.Equal(t, test.expected, (*res).String()) + } + + } +} + func TestTemplateFunctionCpe(t *testing.T) { t.Run("CPE from object", func(t *testing.T) { tt := []struct { diff --git a/resources/metadata/helmExecute.yaml b/resources/metadata/helmExecute.yaml index 8c57b3eae1..045889a3fc 100644 --- a/resources/metadata/helmExecute.yaml +++ b/resources/metadata/helmExecute.yaml @@ -345,6 +345,20 @@ spec: - PARAMETERS - STAGES - STEPS + - name: templateStartDelimiter + type: string + description: When templating value files, use this start delimiter. + default: "{{" + scope: + - STEPS + - PARAMETERS + - name: templateEndDelimiter + type: string + description: When templating value files, use this end delimiter. + default: "}}" + scope: + - STEPS + - PARAMETERS containers: - image: dtzar/helm-kubectl:3 workingDir: /config