In a Helm chart YAML, how do i include multiple lines of properties in one call?

10/8/2020

I want to be able to take multiple sub-properties from a values.yaml property and put them all under a property in a template. For example:

values.yaml

selectors:
  propA: valueA
  propB: valueB
  propC: valueC

/templates/deployment.yaml

# ...elided...
spec:
  selector:
    matchLabels:
      # This is pseudo code
      {{ includeAll .Values.selectors | nindent 6 }}

And then this would result in K8s getting a yaml of:

# ...elided...
spec:
  selector:
    matchLabels:
      propA: valueA
      propB: valueB
      propC: valueC

How can I do something like that?

-- Don Rhummy
kubernetes
kubernetes-helm
yaml

1 Answer

10/8/2020

It's turns out not to be super simple. It depends (from what I can tell) on which type of thing is underneath.

Simple name:value pairs

You can use the range function which acts a lot like a for-each loop. The

{{- range $name, $labelValue := .Values.labels }}
{{ $name }}: {{ $labelValue }}
{{- end }}

Nested properties of many levels

If you have a nested, multi-level property, then the only way I could find is to convert it to a yaml. And you need to be very careful about the indenting. It does a couple things:

  1. It starts it with a new line (a full empty line)
  2. Whatever indent you add will be in front of every line
  3. If you start it indented in your template, that will be included too

Example from values.yaml

envVariables:
  - name: MYSQL_ROOT_PASSWORD
    valueFrom: 
      secretKeyRef:
        name: db-creds
        key: db-pass

First valid way:

spec:
  containers:
    - image: "{{ .Values.image.name }}:{{ .Values.image.tag }}"
      imagePullPolicy: {{ .Values.image.pullPolicy }}
      env: {{ toYaml .Values.envVariables | nindent 12 }}

This will result in:

spec:
  containers:
    - image: "{{ .Values.image.name }}:{{ .Values.image.tag }}"
      imagePullPolicy: {{ .Values.image.pullPolicy }}
      env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom: 
            secretKeyRef:
              name: db-creds
              key: db-pass

Second valid way:

spec:
  containers:
    - image: "{{ .Values.image.name }}:{{ .Values.image.tag }}"
      imagePullPolicy: {{ .Values.image.pullPolicy }}
      env: 
{{ toYaml .Values.envVariables | nindent 12 }}

Notice it's left aligned. This will result in a blank line after env: but will have the right indentation.

INVALID WAY:

spec:
  containers:
    - image: "{{ .Values.image.name }}:{{ .Values.image.tag }}"
      imagePullPolicy: {{ .Values.image.pullPolicy }}
      env: 
        {{ toYaml .Values.envVariables | nindent 12 }}

With the above, there is no way to get the indenting correct as the first line only will have additional indentation and the other lines will not.

-- Don Rhummy
Source: StackOverflow