I'm working on a Helm chart and trying to create a general-purpose templating function. The goal is to pass in any parameter (e.g., .Values.name) and have the function template it without knowing the specifics of the parameter.
The function should accept a parameter like .Values.name.
It should evaluate the parameter using tpl if a certain condition (e.g., .Values.enableTpl) is met.
The function should handle various types, such as strings and lists.
{{- define "function" -}}
{{- $value := . -}} <-- this should pick up the parameter
{{- if .Values.enableTpl }}
{{ tpl $value $ }}
{{- else }}
{{ $value }}
{{- end }}
{{- end }}
# Usage in template
{{ include "function" .Values.name }} <-- function should not know about this parameter
When trying this, I’m encountering the error: "can't evaluate field Values in type string" when trying to check the enableTpl condition. Removing the enableTpl check also fails, as the . is not the actual parameter ".Values.name"
Note that this is an abstraction of my problem, so please don't question the reasoning for not just doing it without the include :)
The Helm syntax for this is a little tricky. A Go-template function only takes a single parameter, and within that function both the default value of .
and $
are set to that parameter.
This means that, if you need both some value and also the top-level Helm object, you need to pack them together into a single object. I've historically done this via putting both objects into a list
{{ include "function" (list .Values.name .) }}
and then in the function unpacking them.
{{- define "function" -}}
{{- $value := index . 0 -}}
{{- $top := index . 1 -}}
{{- if $top.Values.enableTpl -}}
{{- tpl $value $top -}}
...
Note that we've passed the top-level Helm object explicitly as a parameter; unpacked it to $top
within the function; and then anywhere we need a field off of that, qualified it as access to $top
.
You can also pass the two "parameters" as a map dict "value" .Values.name "top" .
. If you do then you don't need to unpack them in the function, and can directly refer to e.g. .top.Values.enableTpl
or tpl .value .top
. This pushes some complexity from the function to the caller. Neither pattern is that common but I've seen both.