Search code examples
kubernetes-helmgo-templates

Helm template not being rendered with appropriate indentation


I am trying to helm-template this Secret

kind: Secret
apiVersion: v1
metadata:
  name: my-roles-secret
stringData:
  roles.yml: |-
    click_admins:
      run_as: [ 'clicks_watcher_1' ]
      cluster: [ 'monitor' ]
      indices:
      - names: [ 'events-*' ]
        privileges: [ 'read' ]
        field_security:
          grant: ['category', '@timestamp', 'message' ]
        query: '{"match": {"category": "click"}}'

Here is my template

{{ if .Values.customRoles }}
{{ if .Values.customRoles.enabled }}
kind: Secret
apiVersion: v1
metadata:
  name: my-roles-secret
stringData:
  roles.yml: |-
    {{ .Values.customRoles.definition -}}
{{ end }}
{{ end }}

and the corresponding values

customRoles:
  enabled: true
  definition: |-
      click_admins:
        run_as: [ 'clicks_watcher_1' ]
        cluster: [ 'monitor' ]
        indices:
        - names: [ 'events-*' ]
          privileges: [ 'read' ]
          field_security:
            grant: ['category', '@timestamp', 'message' ]
          query: '{"match": {"category": "click"}}'

Why am I getting the following output?

helm template -f values.yaml
(...)

kind: Secret
apiVersion: v1
metadata:
  name: my-roles-secret
stringData:
  roles.yml: |-
    click_admins:
  run_as: [ 'clicks_watcher_1' ]
  cluster: [ 'monitor' ]
  indices:
  - names: [ 'events-*' ]
    privileges: [ 'read' ]
    field_security:
      grant: ['category', '@timestamp', 'message' ]
    query: '{"match": {"category": "click"}}'

Why is click_admins so badly indented?

How can I produce the first snippet using helm templating?


Solution

  • Change the template to:

    stringData:
      roles.yml: |-
    {{ .Values.customRoles.definition | indent 4 }}
    

    (So do not indent the last line, but do include ... | indent 4 at the end of it.)


    When Helm's YAML parser reads the values.yaml file, there it loads the customRoles.definition value into a string. YAML's rules are to strip a consistent amount of leading whitespace from each line, so that value will be a string, starting with the first character, with indented lines below it:

    # .Values.customRoles.definition -- note, the first line is not indented
    click_admins:
      run_as: [ 'clicks_watcher_1' ]
      ...
    

    In your original template, there are several spaces before the first line, but then the remaining lines are unindented. The Helm indent function inserts a consistent number of spaces before each line. This includes the first line, so you need to remove the extra indentation in the template file.

    If you're familiar with other languages, the string has the value

    "click_admins:\n  run_as: [...]\n  cluster: ..."
    

    In your original form you are putting four spaces at the front of the string, but not affecting the embedded newlines. indent 4 puts 4 spaces at the front of the string and also after each newline.