Reference: Stack Overflow

With the pipe character you pass a value to a filter. There are numerous Jinja 2 filters but Ansible brings some additional filters(Also see Conditionals.)

The term filter might be confusing at times because all the filters work very differently. Some for example reduce a result set of a hash/array, some modify contents of a string, but then there are filters which simply return true or false.

A better explanation might be that those are modifiers and they can do anything with your passed data. You can even write your own filters.

Filters can be chained, passing the result from the first filter to the next and so forth. It works exactly like piping commands on a unix shell.

"value" | filter1 | filter2 | filterN

The failed  filter returns true  if the passed result has failed. It simply checks the failed  property from result .

The changed  filter is the same, but checks if the passed result has changes. It checks the changed property from result .

ipaddr | replace(",", ".")  replaces all occurrences of ,  with . so a value of 127,0,0,1  will be transformed to 127.0.0.1 .

The default  filter will set a default value if the input was null, e.g. an undefined variable. undefined_var default(“var was undefined”)  -> This will either print the contents of undefined_var  or the string “var was undefined” .

Additional Overview Information

Reference: Jinja

Variables can be modified by filters. Filters are separated from the variable by a pipe symbol (  ) and may have optional arguments in parentheses. Multiple filters can be chained. The output of one filter is applied to the next.

For example, `` will remove all HTML Tags from variable name and title-case the output (title(striptags(name))) .

Filters that accept arguments have parentheses around the arguments, just like a function call. For example: {{ listx|join(', ') }} will join a list with commas (str.join(', ', listx)).

The List of Builtin Filters describes all the builtin filters.

Nested Filters

Reference: OzNetNerd.com

Filters such as map( )  can accept another filter as a parameter. As per the documentation:

“map( )  applies a filter on a sequence of objects or looks up an attribute.”

We seen an example of this on the map ( )  page where we used the upper( )  filter as a parameter:

{{ names | map('upper') | list }}

Attributes

Reference: OzNetNerd.com

Filters such as map(  )  can accept attributes as a parameter. As per the documentation:

“map( )  applies a filter on a sequence of objects or looks up an attribute.”

We seen an example of this on the map ( )  page where we used the first and last   attribute as a parameters:

{{ names | map(attribute='first') | list }}
{{ names | map(attribute='last') | list }}

Ansible Filter Source Code

At the time of writing, regex_search  and regex_findall  filters (discussed here) have been integrated into Ansible but not yet documented. Having said this, Ansible has been notified so the issue should soon be resolved.

If you come across a similar situation in the future, after notifying Ansible you can browse the source code and figure out how the filter works yourself. Note that you’ll need to ensure you select the correct code branch for the version of Ansible you’re running.

Tests

Reference: OzNetNerd.com

As per the Jinja documentation:

Beside filters, there are also so-called “tests” available. Tests can be used to test a variable against a common expression.

Filters such as selectattr( )   can accept tests as a parameter. As per the documentation:

“selectattr( ) filters a sequence of objects by applying a test to the specified attribute of each object, and only selecting the objects with the test succeeding. If no test is specified, the attribute’s value will be evaluated as a boolean.

We seen an example of this on the selectattr ( )  page where the undefined  Test is passed as a parameter:

- set_fact:
    emails: "{{ users | selectattr('password', 'undefined') | map(attribute='email') | list }}"

As always, if you have any questions or have a topic that you would like me to discuss, please feel free to post a comment at the bottom of this blog entry, e-mail at will@oznetnerd.com, or drop me a message on Reddit (OzNetNerd).

Note: The opinions expressed in this blog are my own and not those of my employer.

Leave a comment