… updated on Thursday, March 7, 2024 16:05 +0100
Multiline Expressions in Ansible Playbooks
Another week, another Ansible quirk 🤷♂️ Imagine you have a long Jinja2 expression, and you want to wrap it into multiple lines to improve readability. Using multiline YAML format seems to be the ideal choice:
---
- name: Test playbook
hosts: localhost
tasks:
- set_fact:
a: >
{{ 123 == 345 or
123 > 345 }}
It works every time 50% of the time (this time depending on your Ansible version).
If you use the community version of Ansible, you’ll get the expected results: a is false:
$ ansible-playbook -v x.yml
...
TASK [set_fact] ********************************************************************************************************************
ok: [localhost] => {"ansible_facts": {"a": false}, "changed": false}
However, if you use an older Ansible core release (for example, Ansible core 2.12.10 that you could find in RHEL 9.0), you’ll get this outstanding result:
$ ansible-playbook -v x.yml
...
TASK [set_fact] ********************************************************************************************************************
ok: [localhost] => {"ansible_facts": {"a": "False\n"}, "changed": false}
Notice how the extra newline throws off Ansible? It evaluates the expression as a string; a non-empty string is true, not false.
Lesson learned: you MUST NOT use multiline YAML format in Ansible expressions.
You could enclose expressions in quotes like this:
---
- name: Test playbook
hosts: localhost
tasks:
- set_fact:
a:
"{{ 123 == 345 or
123 > 345 }}"
You could also use the YAML Block Chomping Indicator to remove the trailing newline:
---
- name: Test playbook
hosts: localhost
tasks:
- set_fact:
a: >-
{{ 123 == 345 or
123 > 345 }}
You’ll find more details on a website dedicated to multiline YAML strings.
Revision History
- 2024-03-07
- Added Block Chomping as an alternate solution based on Miguel’s comment.
Hello,
First of all, thank you for all the information you share here. It is really useful.
For several reason we have been dealing with ansible 2.10 for a while and the solution we found to this problem was to remove the endline by using YAML multiline block definition options. We always use ">-" instead of ">" when we want to define a variable using set_fact, so it removes that final endline.
Here it is an example based on yours for this behaviour in ansible 2.10.17.
Variable a is set using '>' and variable b using '>-'. First one is set to a string while the second one is set as intended to false.
Hope it helps. Best regards