4

I have k8s manifest such as below, packaged with Helm.

apiVersion: v1
kind: ServiceAccount
metadata:
  {{- template "myFunction" "blah" -}}

I have _helper.tpl defining myFunction as below.

{{- define "myFunction" }}
  {{- if .Values.nameOverride }}
  name: {{ . }}
  {{- else }}
  name: "test"
  {{- end }}
{{- end }}

Finally, I have values.yaml defining nameOverride: "". From my understanding, as I haven't defined anything for nameOverride, myFunction should output name: "test", and when I define something for nameOverride, the output should be name: "blah". However, I'm getting the error below.

Error: template: product-search/templates/_helpers.tpl:2:16: executing "myFunction" at <.Values.nameOverride>: can't evaluate field Values in type string
helm.go:88: [debug] template: product-search/templates/_helpers.tpl:2:16: executing 
"myFunction" at <.Values.nameOverride>: can't evaluate field Values in type string

Any ideas why? Thanks!

Piljae Chae
  • 987
  • 10
  • 23

1 Answers1

4

Inside the Go text/template language, .Values is a lookup of a field named Values in the special variable .. This variable changes meaning in different context. Inside a define template, . starts off as the value of the parameter to the template, which is not necessarily the top-level Helm object.

{{ template "myFunction" "blah" }}

{{ define "myFunction" }}
{{/* with the call above, . is the string "blah" */}}
{{ end }}

A template only takes one parameter. There are a couple of things you can do here. One approach is to figure out the field value in the caller, and pass that in as the template parameter:

{{-/* Emit a name: label.  The parameter is a string. */-}}
{{- define "myFunction" -}}
name: {{ . }}
{{ end -}}

{{-/* if .Values.nameOverride then "blah" else "test" */-}}
{{- $label := ternary "blah" "test" .Values.nameOverride -}}
{{ include "myFunction" $label | indent 4 }}

Another approach could be to pack the two values into a single parameter. I tend to use the Helm list function for this. However, this makes the template logic significantly more complicated.

{{/* Emit a name: label.  The parameter is a list of two values,
     the top-level Helm object and the alternate label name to use
     if .Values.nameOverride is defined. */}}
{{- define "myFunction" -}}
{{/* . is a list of two values; unpack them */}}
{{- $top := index . 0 -}}
{{- $label := index . 1 -}}
{{/* Now we can look up .Values within the passed top-level object */}}
{{- if $top.Values.nameOverride -}}
name: {{ $label }}
{{ else -}}
name: "test"
{{ end -}}
{{- end -}}

{{/* When calling the function manually construct the parameter list */}}
{{ include "myFunction" (list . "blah") | indent 4 }}
David Maze
  • 130,717
  • 29
  • 175
  • 215