Helm charts define helper templates in _helpers.tpl
which are used to create normalized names for the services. The standard form of the template for a service (DNS) name is:
{{- define "postgresql.fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
If using postgresql as a subchart, how are you supposed to use DNS-based service discovery to refer to it? A common pattern seems to be to copy the subchart helpers into the parent chart.
{{- define "keycloak.postgresql.fullname" -}}
{{- $name := default "postgresql" .Values.postgresql.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
This is total madness for obvious reasons!!!
Surely there's a better way to use the subchart helper? If you could create a context object then it would be possible to invoke it, something like:
value: {{ template "postgresql.fullname" ({Chart: {Name: 'not-used'}, Release: {Name: .Release.Name}, Values: { nameOverride: .Values.postgresql.nameOverride}}) }}
Sadly I have no idea how to actually create such a context dynamically. This would still break if the helper function changed to reference new properties, but in an obvious way.
Alternatively, a different way to make available the service name from a subchart?
A subchart is considered "stand-alone", which means a subchart can never explicitly depend on its parent chart. For that reason, a subchart cannot access the values of its parent. A parent chart can override values for subcharts. Helm has a concept of global values that can be accessed by all charts.
If you want to check the templates for given chart you can use helm template [chartname] command. The docs describe it as : Render chart templates locally and display the output. Any values that would normally be looked up or retrieved in-cluster will be faked locally.
I wrote an issue helm/helm#4535
that summarizes the status-quo and proposes an enhancement to Helm which will solve this case.
For anyone looking for an interim solution, I wrote (see my follow-up comment for details) a meta-template that calls any given template in an "ersatz" subchart's scope. It works by synthesizing a dot-object. It is not perfect (not all fields are synthesized), but it will do:
{{- define "call-nested" }} {{- $dot := index . 0 }} {{- $subchart := index . 1 }} {{- $template := index . 2 }} {{- include $template (dict "Chart" (dict "Name" $subchart) "Values" (index $dot.Values $subchart) "Release" $dot.Release "Capabilities" $dot.Capabilities) }} {{- end }}
Usage (to call a redis.fullname
template of a redis
subchart):
{{ include "call-nested" (list . "redis" "redis.fullname") }}
As of https://github.com/helm/helm/pull/9957 (merged August 31, 2021 and released in Helm 3.7), you can invoke the subchart's named template in the context of that subchart by using .Subcharts.[chartName]
as the second argument.
For example, assuming your keycloak subchart names it service like {{ template "keycloak.fullname" . }}-http
you could refer to that service's name from a parent chart as follows:
{{ template "keycloak.fullname" .Subcharts.keycloak }}-http
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With