Control Whitespace in Ansible Templates

Ansible uses the powerful Jinja templating engine. However, the way it handles whitespace in templates is not ideal. Specifically, the fact that it preserves leading whitespace around Jinja blocks. So, you can either not indent Jinja syntax, making the templates hard to comprehend, or accept broken indentation in the resulting file (not an option with whitespace-sensitive formats such as yaml).

Luckily, there is a third option. Jinja has two configuration options regarding whitespace:

  • trim_blocks - first newline after template tag is removed automatically
  • lstrip_blocks - strip tabs and spaces from beginning of the line to the start of a block

While trim_blocks has been on by default since Ansible 2.4, that is not the case with lstrip_blocks. In order to turn it on, you need to put the following line at the very top of your template:

#jinja2: lstrip_blocks: "True"

Comparison

Let’s take the following template:

{% set _dataset = datasets[dataset] %}
[{{ dataset }}]
    {% for key, value in _dataset.items() %}
    {{ key }} = {{ value }}
    {% endfor %}

without lstrip_blocks, the result would look like this:

[home]
        recursive = yes
    use_template = default

Now, with lstrip_blocks on, you get correct indentation:

[home]
    recursive = yes
    use_template = default

Naturally, you can locally overwrite the configuration by adding + to the Jinja block:

    {%+ if foo %}Preserve indentation{% endif %}

Conclusion

This configuration option was a lifesaver for me. Hopefully, it will help you make your Ansible templates more readable as well. You can find more examples in the Jinja documentation.