Search code examples
kubernetes-helm

$ does not resolve to the root context from within a helm template


I'm trying to iterate over .Files.Glob in a Helm template. I pass a string value into the template, so I've swapped over to using $.Files.Glob to refer back to the root context. However I get an error saying that there's no field "Files" on type string.

The error:

error calling include: template: example/templates/_helpers.tpl:77:29: executing "apiMounts" at <$.Files.Glob>: can't evaluate field Files in type string

The template:

{{- define "apiMounts" -}}
{{- range $path, $_ := $.Files.Glob . }}
{{- $name := (base $path) }}
- name: specs
  mountPath: {{ printf "/etc/apis/%s" $name }}
  subPath: {{ sha256sum $name }}
{{- end }}
{{- end }}

How I'm using the template (deployment):

          volumeMounts:
            {{- include "apiMounts" "common/**.json" | indent 12 }}
            {{- include "apiMounts" "v1/**.json" | indent 12 }}

According to the Helm documentation, $ should always refer back to the root context, but in this case it seems to still be referring to the string that I've passed to the template.

However, there is one variable that is always global - $ - this variable will always point to the root context. This can be very useful when you are looping in a range and you need to know the chart's release name.

How can I used .Files.Glob in this template, while still passing in the string value?


Solution

  • The value you pass into the include function becomes the root context.

    You can get the original root context inside the template function by passing in a list which includes it and your argument:

    {{- include "apiMounts" (list $ "common/**.json") | indent 12 }}
    

    Inside your template function, restore the "root" context and grab your argument:

    {{- define "apiMounts" -}}
    {{- $ := index . 0 }}
    {{- $arg := index . 1 }}
    {{- range $path, $_ := $.Files.Glob $arg }}
    ...