How to know, when I have to use {{- instead of {{ when producing yaml?

Viewed 29

Completely new to helm, I cannot understand how this whitespace removal work. I've read that {{- should just remove whitespaces/newlines. I'd expect it to remove from expression within brackets, but I would put my had into mildly warm water that I saw removing white spaces before brackets. What does it actually do?

Also, using helm producing yaml(where whitespaces, indentation and newlines are significant characters :| ), single missing/extra dash will produce error.

Is there some recommendation which pattern of dashes to use to avoid issues? Since I really didn't find reliable definition of what is removed I constantly have to test all permutations to find winning combination...

EDIT: or how to debug it to know what is wrong? Unable to parse yaml to json is not enough to find out what is the actual problem.

2 Answers

First of all, you may need to know that helm essentially uses golang for template replacement, so the underlying implementation can refer to go template

According helm doc

Notice that we received a few empty lines in our YAML. Why? When the template engine runs, it removes the contents inside of {{ and }}, but it leaves the remaining whitespace exactly as is.

YAML ascribes meaning to whitespace, so managing the whitespace becomes pretty important. Fortunately, Helm templates have a few tools to help.

First, the curly brace syntax of template declarations can be modified with special characters to tell the template engine to chomp whitespace. {{- (with the dash and space added) indicates that whitespace should be chomped left, while -}} means whitespace to the right should be consumed. Be careful! Newlines are whitespace!

Make sure there is a space between the - and the rest of your directive. {{- 3 }} means "trim left whitespace and print 3" while {{-3 }} means "print -3".

e.g.

values.yaml

atest: test

templates/cm.yaml
```yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: test
data: 
  cfg1: |-
    {{ if eq $.Values.atest "test" }}
              ok1
    {{ end }}
  cfg2: |-


    {{- if eq $.Values.atest "test" }}

         ok2
    {{- end }}

  cfg3: |-
    ok

    {{- if eq $.Values.atest "test" -}}

       3      
    {{- end -}}

    xxxxx

cmd

helm template --debug test .

output

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: test
data: 
  cfg1: |-
    
              ok1
    
  cfg2: |-

         ok2

  cfg3: |-
    ok3xxxxx

In detail:

  • For cfg1, there is no - in {{ or }}, after rendering, the carriage returns at the beginning and end of lines {{ if }} and {{ end }} are preserved, and the spaces before ok1 are also preserved
  • For cfg2, there is a - in {{, after rendering, the carriage returns at the end of lines {{ if }} and {{ end }} are retained, but the enter or spaces at the beginning are deleted
  • For cfg3, there is - in {{ and }}, after rendering, Therefore, after rendering, all enter and spaces before and after lines {{ if }} and {{ end }}, including those before ok 3, all will be deleted

Last, For debug.

helm Debugging Templates

helm template --debug test .

It's a great way to have the server render your templates, then return the resulting manifest file.

In the Go text/template language, a hyphen - directly inside curly braces {{ ... }} causes whitespace outside the curly braces to be removed. It's any whitespace (space, tab, carriage return, newline) on the same side as the hyphen.

plain text: two words

has two spaces between words: two {{ printf "" }} words
has only one space: two {{- printf "" }} words
has only one space: two {{ printf "" -}} words
has no spaces: two {{- printf "" -}} words

#                      kept vv                vvvv dropped
has exactly two spaces:  two  {{ printf "" -}}    words
has exactly four spaces: two  {{- printf "" }}    words
#                   dropped ^^                ^^^^ kept

on one line since newlines are whitespace: two
{{- printf "" }} words

Other punctuation, including hyphens outside of curly braces, is always kept as-is.

As a rule of thumb it's often right to start template expressions at the first column and include a hyphen inside the open brace but not the closing brace. That preserves a newline and indentation for the following line.

metadata:
  labels:
{{- include "common.labels" . | indent 4 }}
    another: label

Running helm template on your chart will render it to YAML, and also try to parse it. helm template --debug will print out the output even on a parse failure. In this situation I tend to visually scan through the generated YAML to look for indentation errors or especially missing newlines (that is, a line like value: foovolumeMounts: that's two lines concatenated together).

Related