Understanding Ansible and Jinja2's default() filter

Posted on Oct 3, 2016

I have been using Ansible at work for the past month to set up some infrastructure. I wanted to express the following in the setup script:

ansible_ssh_user: "{{ lookup('env', 'SSH_USER') }}"

but wanted to set the user to ubuntu if SSH_USER was not set.

For some reason, this would not work:

ansible_ssh_user: "{{ lookup('env', 'SSH_USER') | default('ubuntu') }}"

Ansible provides several functions that can extract various string values from the environment. You are most likely to encounter lookup(). The behavior of lookup() is defined by what plugin is used (based on the first parameter). The env plugin returns an empty string when the requested environment variable is not set. An empty string is False-y in Python. Why wasn’t this working?

The default() filter provided by Jinja2 treats the special class Undefined differently from False-y Python values. By default, default() will only return its first argument if the prior expression evaluates to Undefined. The second boolean parameter asks the function to also accept Python False-y values as undefined and return the default value. This can be seen in the source code

So the fix is:

ansible_ssh_user: "{{ lookup('env', 'SSH_USER') | default('ubuntu', true) }}"