Using Jinja Template Filters in Ansible

February 6, 2021

Jinja is a templating language that is built for Python.

Ansible has support for using Jinja Templating in its playbooks (Learn More).

Note: All the code snippets used in this post are available on GitHub

While working with some of the filters that have an option to pass in additional arguments, it wasn’t very clear to me how to pass in the arguments within an Ansible playbook.

For example, I wanted to use the trim filter to remove specific characters from a string I was working with.

# Original string: *.helloworld.com
# Required string: helloworld.com

By default, the trim filter strips leading and trailing whitespace from the string provided.

# word_with_whitespace = "    helloworld   "
- name: "Show default functionality of trim filter"
ansible.builtin.debug:
  msg: "Before: [{{ word_with_whitespace }}] | After: [{{ word_with_whitespace | trim }}]"
TASK [Show default functionality of trim filter]
ok: [localhost] => {
    "changed": false,
    "msg": "Before: [    helloworld   ] | After: [helloworld]"
}

Now, let’s say you want to trim the "*." characters from our example above.

According to the Jinja trim documentation, the signature for the method is as follows:

trim(value, chars=None)
But what does this translate to when using it in Ansible?

It turns out that when working with the Jinja filters, the value to which you’re applying the filter is automatically passed on to the filter as the first argument.

Therefore, the following snippet in Ansible:

{{ word_with_whitespace | trim }}

gets translated to this (in Python):

trim(word_with_whitespace)

So if we want to trim "*." from our string, we need to ensure that the Python code that gets executed is:

trim(word_with_whitespace, "*.")

In Ansible, this becomes:

{{ word_with_whitespace | trim("*.") }}

So the snippet to trim this from our string in a playbook becomes:

# word_with_other_chars = "*.helloworld.com"
- name: Show trim filter with additional arguments
ansible.builtin.debug:
  msg: "Before: [{{ word_with_other_chars }}] | After: [{{ word_with_other_chars | trim('*.') }}]"

which yields:

TASK [Show trim filter with additional arguments]
ok: [localhost] => {
    "changed": false,
    "msg": "Before: [*.helloworld.com] | After: [helloworld.com]"
}

The same principle applies to other Jinja filters; for example, the int() filter, which converts a given value to an integer.

int Jinja Filter Method Signature
trim(value, chars=None)
Ansible Task Snippets
# str_value_to_convert_to_int: "5278"
# hex_value_to_convert_to_int: "0x149E"
- name: Show trim filter with additional arguments
  - name: Show int filter without arguments
    ansible.builtin.debug:
      msg: "Original Value: [{{ str_value_to_convert_to_int }}] | Converted to int: [{{ str_value_to_convert_to_int | int }}]"

  - name: Show int filter with arguments (convert string from hexadecimal (base 16) to decimal (base 10))
    ansible.builtin.debug:
      msg: "Original Value: [{{ hex_value_to_convert_to_int }}] | Converted to int: [{{ hex_value_to_convert_to_int | int(0, 16) }}]"
Ansible Output
TASK [Show int filter without arguments]
ok: [localhost] => {
    "changed": false,
    "msg": "Original Value: [5278] | Converted to int: [5278]"
}

TASK [Show int filter with arguments (convert string from hexadecimal (base 16) to decimal (base 10))]
ok: [localhost] => {
    "changed": false,
    "msg": "Original Value: [0x149E] | Converted to int: [5278]"
}

In this blog post, we demonstrated how to use Jinja filters that have multiple arguments, within Ansible.

Happy coding, and stay safe!