Hierarchy of values for dynamic helm chart configuration

1/4/2019

What I'm trying to do

I want to have some default settings and options in values.yaml, and then a hash map of different instances, which will be converted into services and deployments, whose individual settings override the defaults.

values.yaml

someSetting: TheDefault
deployments:
  one:
    role: XYZ
  two:
    role: ABC
    someSetting: Overridden

In the above case, there would be two deployments and services, one and two. The value for someSetting for one would be TheDefault and for two would be Overridden.

actual template yaml

I'm trying this - to build a dictionary, $p, which has the root-scope Chart and Release objects in it, then has the root scope values merged in, then the current deployment value merged in.

{{- range $deploymentKey, $deploymentVal := .Values.deployments }}
{{- $p := dict "deploymentKey" $deploymentKey }}
{{- $_ := set $p "Chart" $.Chart }}
{{- $_ := set $p "Release" $.Release }}
{{- $_ := merge $p $.Values }}
{{- $_ := merge $p . }}
...
{{- end }}

The reason for including Chart and Release is that, despite what the documentation says, $.Chart is not always available - it's literally empty when I pass a scope into a template and that template tries to use $. to refer to root scope.

So I'm doing things like:

name: {{ template "my-app.fullname" $p }}

and

image: {{ $p.image.name }}

The error

The problem is that while helm lint returns no errors, helm template . (or a dry-run) yields:

Error: rendering template failed: runtime error: invalid memory address or nil pointer dereference

What I've tried

  • Removing each merge to try to narrow down the crash - they don't seem to cause it
  • Plain-old merging $ into the dictionary
  • Weeping
  • Asking on Helm Slack
  • Asking on GitHub issues

My question..

How can I fix this crash?

Or, how can I achieve what I'm trying to?

-- Kieren Johnstone
kubernetes-helm

2 Answers

1/8/2019

try this:

deployment.yaml:

{{- range $deploymentKey, $deploymentVal := .Values.deployments }}
{{- $p := dict "deploymentKey" $deploymentKey }}
{{- $_ := set $p "Chart" $.Chart }}
{{- $_ := set $p "Release" $.Release }}
{{- $_ := merge $p . }}
{{- $_ := merge $p $.Values }}
...
{{ end }}

_helpers.tpl:

{{- define "repro.fullname" -}}
{{- printf "%s" .Chart.Name }}
{{- end -}}
-- Maor Friedman
Source: StackOverflow

1/4/2019

You could instead create a common base chart with the defaults and a vanilla service and deployment and then create an umbrella chart that includes the base chart twice under the aliases 'one' and 'two'. Then the values file of the umbrella chart is where you override the defaults and you don't need any dictionary.

As an example here is a base chart - https://github.com/ryandawsonuk/configmaps-transformers/tree/master/helm/transformers/charts/transformer and the umbrella chart includes it multiple times under different aliases - https://github.com/ryandawsonuk/configmaps-transformers/blob/master/helm/transformers/requirements.yaml. The umbrella chart's values file plugs in different values for each instance of the base chart that is included. In the umbrella values each instance is referenced by its alias - https://github.com/ryandawsonuk/configmaps-transformers/blob/master/helm/transformers/values.yaml#L14

-- Ryan Dawson
Source: StackOverflow