Ansible has a lot of ways to manipulate variables and their content. We shed some light on the different possibilities – and how to combine them.
Ansible inbuilt filters
One way to manipulate variables in Ansible is to use filters. Filters are connected to variables via pipes, |
, and the result is the modified variable. Ansible offers a set of inbuilt filters. For example the ipaddr
filter can be used to find IP addresses with certain properties in a list of given strings:
# Example list of values test_list = ['192.24.2.1', 'host.fqdn', '::1', '192.168.32.0/24', 'fe80::100/10', True, '', '42540766412265424405338506004571095040/64'] # {{ test_list | ipaddr }} ['192.24.2.1', '::1', '192.168.32.0/24', 'fe80::100/10', '2001:db8:32c:faad::/64']
Jinja2 filters
Another set of filters which can be utilized in Ansible are the Jinja2 filters of the template engine Jinja2, which is the default templating engine in Ansible.
For example the map
filter can be used to pick certain values from a given dictionary. Note the following code snippet where from a list of names only the first names are given out as a list due to the mapping filter (and the list filter for the output).
vars: names: - first: Foo last: Bar - first: John last: Doe tasks: - debug: msg: "{{ names | map(attribute='first') |list }}"
Python methods
Besides filters, variables can also be modified by the Python string methods: Python is the scripting language Ansible is written in, and and provides string manipulation methods Ansible can just use. In contrast to filters, methods are not attached to variables with a pipe, but with dot notation:
vars: - mystring: foobar something - name: endswith method debug: msg: "{{ mystring.endswith('thing') }}" ... TASK [endswith method] ***************************************************************** ok: [localhost] => { "msg": true }
Due to the close relation between Python and Jinja2 many of the above mentioned Jinja2 filters are quite similar to the string methods in Python and as a result, some capabilities like capitalize
are available as a filter as well as a method:
vars: - mystring: foobar something tasks: - name: capitalize filter debug: msg: "{{ mystring|capitalize() }}" - name: capitalize method debug: msg: "{{ mystring.capitalize() }}"
Connecting filters and methods
Due to the different ways of invoking filters and methods, it is sometimes difficult to bring both together. Caution needs to be applied if filters and methods are to be mixed.
For example, if a list of IP addresses is given and we want the last element of the included address of the range 10.0.0.0/8
, we first can use the ipaddr
filter to only output the IP within the appropriate range, and afterwards use the split method to break up the address in a list with four elements:
vars: - myaddresses: ['192.24.2.1', '10.0.3.5', '171.17.32.1'] tasks: - name: get last element of 10* IP debug: msg: "{{ (myaddresses|ipaddr('10.0.0.0/8'))[0].split('.')[-1] }}" ... TASK [get last element of 10* IP] ************************************************************** ok: [localhost] => { "msg": "5" }
As can be seen above, to attach a method to a filtered object, another set of brackets – ( )
– is needed. Also, since the result of this filter is a list, we need to take the list element – in this case this is easy since we only have one result, so we take the element 0
. Afterwards, the split method is called upon the result, gives back a list of elements, and we take the last element (-1
, but element 3
would have worked here as well).
Conclusion
There are many ways in Ansible to manipulate strings, however since they are coming from various sources it is sometimes a little bit tricky to find what is actually needed.