Render error when parsing configmap in helm package

10/16/2019

I have a helm package whose values.yaml contains something like:

ere:
  adm-users:
  - userName: test1
    password: test2
  - useName: user3
    password: user4

and I want to include these values in an xml file dynamically for which in the deployment.yaml i've included a configmap. My configmap contains something like:

data:
  PoolServer.xml: {{ tpl (.Files.Get "files/config/PoolServer.xml") . | nindent 4 }}

Inside my PoolServer.xml I have this content:

{{- range $index, $val := .Values.ere.adm-users }}
<User Name="{{ tpl "{{ $val.userName }}" $ }} " Password="{{ tpl "{{ $val.password }}" $ }}" />
{{- end }

This is what it looks like after i did quite a few changes but it doesn't seem to work.

When i lint it fails with error:

[ERROR] templates/: render error in "eric-em-ere/templates/deployment-ere.yaml": template: eric-em-ere/templates/deployment-ere.yaml:25:28: executing "eric-em-ere/templates/deployment-ere.yaml" at <include (print $.Tem...>: error calling include: template: eric-em-ere/templates/configmap.yaml:14:21: executing "eric-em-ere/templates/configmap.yaml" at <tpl (.Files.Get "fil...>: error calling tpl: Error during tpl function execution for "<User Name=\"{{ .Values.ere.adm-users.userName }}\" Password=\"{{ .Values.ere.adm-users.password }}\" />\r\n": parse error in "eric-em-ere/templates/deployment-ere.yaml": template: eric-em-ere/templates/deployment-ere.yaml:1: bad character U+002D '-'

Please help me point out what am i doing wrong here.

-- Lucky Tyagi
go
kubernetes-helm

1 Answer

10/17/2019

The Go text/template documentation kind of hints at your actual error message: in .Values.foo.bar expressions, each of the parts needs to be a valid Go name, which can't include hyphens. Conventionally value names are camelCased, so you can change both the variable reference and the name of the value to admUsers (capital "U", no hyphen).

The multiple layers of tpl are confusing and probably unnecessary if your userName and password will always be simple strings. You're also not required to assign the iterator of a range to anything, and (unlike standard Go) if you assign only one variable it will be the value.

I'd probably write this loop as:

{{/* Protect against .Values.ere being missing entirely */}}
{{- $ere := .Values.ere | default dict -}}
{{- range $ere.admUsers }}
<User Name="{{ .userName }}" Password="{{ .password }}" />
{{- end }}

If you want it to be possible to put template syntax in the values.yaml file for the user names and passwords, you need to construct an appropriate expression for tpl; you can't nest the template syntax the way you've shown.

{{- $top := . -}}
{{- $ere := .Values.ere | default dict -}}
{{- range $ere.admUsers }}
<User Name="{{ tpl .userName $top }}" Password="{{ tpl .password $top }}" />
{{- end }}

If you wanted to construct a string like {{ .userName }} and evaluate it you could, but putting curly braces in templates gets tricky. I think the inner body of your loop is equivalent to my first form (it ultimately prints out the userName and password of each element in the loop).

-- David Maze
Source: StackOverflow