Conditionals in Ansible

From bib. source

Before discussing all the different uses of conditionals in Ansible, it’s worthwhile to cover a small part of Jinja (the syntax Ansible uses both for templates and for conditionals), and available Python functions (often referred to as ‘built-ins’). Ansible uses expressions and built-ins with when, changed_when, and failed_when so you can describe these things to Ansible with as much precision as possible.

Jinja is a templating engine that Ansible makes use of, and, among other things, it can allow the use of literals such as string, integer, float, list / array, tuple, dictionary / associative array, or boolean data types (Geerling 2023, 108-109). It also allows for use of logical, mathematical, identity or comparison operators. Using all of these tools together allows one to create whole boolean expressions that can then be used with the when, changed_when or failed_when YAML fields or Ansible modules (Ibid).

The when field

The when key or field or module for YAML Ansible playbooks or Ansible variable files runs the play if the Jinja expression following it resolves to a boolean that represents veracity, and otherwise skips the play if the Jinja expression following it resolves to a boolean that represents falsehood (Geerling 2023, 111). This allows for running tasks conditionally, but also allows creation of dependency chains between successful tasks or play executions in a playbook so long as it is used in tandem with output registration (Ibid).

The changed_when / failed_when fields

The two variations on the when key/field, changed_when and failed_when, use expressions that evaluate to a boolean value in order to affect the state or status of the given play or task (Geerling 2023, 112).

The former key/field–changed_when–is especially useful because (Geerling 2023, 113):

From bib. source

[…] if you use the command or shell module without also using changed_when, Ansible will always report a change. Most Ansible modules report whether they resulted in changes correctly, but you can also override this behavior by invoking changed_when yourself.

The latter key/field–failed_when–nonetheless can also sometimes be useful because (Ibid):

From bib. source

Many command-line utilities print results to stderr instead of stdout, so failed_when can be used to tell Ansible when a task has actually [sic] failed and is not just reporting its results in the wrong way.

Speaking of errors, they can also be ignored using the ignore_errors field, in case errors do not actually indicate a given task or play has failed (Geerling 2023, 114):

From bib. source

Sometimes there are commands that should be run always, and they often report errors. Or there are scripts you might run that output errors left and right, and the errors don’t actually indicate a problem, but they’re just annoying (and they cause your playbooks to stop executing).

Extending Jinja capabilities with Python

One can do much more with Jinja by making use of “Python’s built-in library functions to manipulate variables and determine whether a given task should be run,” although “[i]t’s generally best to stick with simpler Jinja filters and variables” (Geerling 2023, 109-110).

templating_engine data_type data_types template logical_operators comparison_operators comparators mathematical_operators module field operator comparison_operator comparator mathematical_operator logical_operator Yet_Another_Markup_Language YAML_Aint_Markup_Language expression identity_operator identity_operators variable_files conditional error error_handling configuration_management file files


bibliography

  • “Ansible Playbooks - Beyond the Basics.” In Ansible for DevOps: Server and Configuration Management for Humans, 2nd ed., 84–122. Leanpub, 2023.