0
votes

I'm trying to use a Helm named template that I plan to include with several different contexts, and the template has many values that are the same for all contexts.

Whenever I pass a context to template or include to invoke the named template, the references to .Values do not work, which is understandable because I'm explicitly setting a lower context.

In the Helm documentation for with, it claims there is a "global" variable $ that will allow reference to the global .Values, e.g., {{ $.Values... }}. This does not work (the example below shows the error).

I've also tried defining variables (using :=) and "enclosing" the include inside that variable definition (via indentation - I don't know if it matters) to make that variable available within the named template, but this doesn't work either.

I've also tried putting these in "globals" as described here which is more of a subchart thing and this doesn't work either.

So, I'm out of Helm tricks to make this work and will sadly have to re-define these many same variable many times - which makes the entire named template solution a bit less elegant - or just go back to having largely duplicate partially-parameterized templates.

What am I missing?

$ helm version
Client: &version.Version{SemVer:"v2.9+unreleased", GitCommit:"", GitTreeState:"clean"}

Values.yaml:

---
commonSetting1: "common1"
commonSetting2: "common2"
context1:
  setting1: "c1s1"
  setting2: "c1s2"
context2:
  setting1: "c2s1"
  setting2: "c2s2"

deployment.yaml:

---
{{- define "myNamedTemplate" }}
      - name: {{ .setting1 }}
        image: {{ $.Values.commonSetting1 }}

{{- include "myNamedTemplate" .Values.context1 }}
{{- include "myNamedTemplate" .Values.context2 }}
$ helm template test-0.1.0.tgz 
Error: render error in "test/templates/deployment.yaml": template: test/templates/deployment.yaml:7:4: executing "test/templates/deployment.yaml" at <include "myNamedTemp...>: error calling include: template: test/templates/deployment.yaml:4:19: executing "myNamedTemplate" at <$.Values.commonSetti...>: can't evaluate field commonSetting1 in type interface {}
1

1 Answers

2
votes

When I do this, I tend to explicitly pass in the top-level context object as a parameter. This gets a little tricky because the Go text/template templates only take a single parameter, so you need to use the (Helm/Sprig) list function to package multiple parameters together, and then the (standard text/template) index function to unpack them.

The template definition would look like:

{{- define "myNamedTemplate" }}
{{- $top := index . 0 }}
{{- $context := index . 1 }}
- name: {{ $context.setting1 }}
  image: {{ $top.Values.commonSetting1 }}
{{ end }}

When you invoke it, you would then need to explicitly pass the current context as a parameter:

{{ include "myNamedTemplate" (list . .Values.context1) }}