mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-05-04 00:01:30 -07:00
Merge pull request #10312 from drybjed/docs-filters
Reorganization of Jinja2 filter documentation
This commit is contained in:
commit
84e18b00d6
3 changed files with 866 additions and 338 deletions
391
docsite/rst/playbooks_filters.rst
Normal file
391
docsite/rst/playbooks_filters.rst
Normal file
|
@ -0,0 +1,391 @@
|
||||||
|
Jinja2 filters
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. contents:: Topics
|
||||||
|
|
||||||
|
Filters in Jinja2 are a way of transforming template expressions from one kind of data into another. Jinja2
|
||||||
|
ships with many of these. See `builtin filters`_ in the official Jinja2 template documentation.
|
||||||
|
|
||||||
|
In addition to those, Ansible supplies many more.
|
||||||
|
|
||||||
|
.. _filters_for_formatting_data:
|
||||||
|
|
||||||
|
Filters For Formatting Data
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The following filters will take a data structure in a template and render it in a slightly different format. These
|
||||||
|
are occasionally useful for debugging::
|
||||||
|
|
||||||
|
{{ some_variable | to_nice_json }}
|
||||||
|
{{ some_variable | to_nice_yaml }}
|
||||||
|
|
||||||
|
.. _filters_used_with_conditionals:
|
||||||
|
|
||||||
|
Filters Often Used With Conditionals
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
The following tasks are illustrative of how filters can be used with conditionals::
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
|
||||||
|
- shell: /usr/bin/foo
|
||||||
|
register: result
|
||||||
|
ignore_errors: True
|
||||||
|
|
||||||
|
- debug: msg="it failed"
|
||||||
|
when: result|failed
|
||||||
|
|
||||||
|
# in most cases you'll want a handler, but if you want to do something right now, this is nice
|
||||||
|
- debug: msg="it changed"
|
||||||
|
when: result|changed
|
||||||
|
|
||||||
|
- debug: msg="it succeeded"
|
||||||
|
when: result|success
|
||||||
|
|
||||||
|
- debug: msg="it was skipped"
|
||||||
|
when: result|skipped
|
||||||
|
|
||||||
|
.. _forcing_variables_to_be_defined:
|
||||||
|
|
||||||
|
Forcing Variables To Be Defined
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
The default behavior from ansible and ansible.cfg is to fail if variables are undefined, but you can turn this off.
|
||||||
|
|
||||||
|
This allows an explicit check with this feature off::
|
||||||
|
|
||||||
|
{{ variable | mandatory }}
|
||||||
|
|
||||||
|
The variable value will be used as is, but the template evaluation will raise an error if it is undefined.
|
||||||
|
|
||||||
|
|
||||||
|
.. _defaulting_undefined_variables:
|
||||||
|
|
||||||
|
Defaulting Undefined Variables
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Jinja2 provides a useful 'default' filter, that is often a better approach to failing if a variable is not defined::
|
||||||
|
|
||||||
|
{{ some_variable | default(5) }}
|
||||||
|
|
||||||
|
In the above example, if the variable 'some_variable' is not defined, the value used will be 5, rather than an error
|
||||||
|
being raised.
|
||||||
|
|
||||||
|
|
||||||
|
.. _omitting_undefined_variables:
|
||||||
|
|
||||||
|
Omitting Undefined Variables and Parameters
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
As of Ansible 1.8, it is possible to use the default filter to omit variables and module parameters using the special
|
||||||
|
`omit` variable::
|
||||||
|
|
||||||
|
- name: touch files with an optional mode
|
||||||
|
file: dest={{item.path}} state=touch mode={{item.mode|default(omit)}}
|
||||||
|
with_items:
|
||||||
|
- path: /tmp/foo
|
||||||
|
- path: /tmp/bar
|
||||||
|
- path: /tmp/baz
|
||||||
|
mode: "0444"
|
||||||
|
|
||||||
|
For the first two files in the list, the default mode will be determined by the umask of the system as the `mode=`
|
||||||
|
parameter will not be sent to the file module while the final file will receive the `mode=0444` option.
|
||||||
|
|
||||||
|
|
||||||
|
.. _list_filters:
|
||||||
|
|
||||||
|
List Filters
|
||||||
|
------------
|
||||||
|
|
||||||
|
These filters all operate on list variables.
|
||||||
|
|
||||||
|
.. versionadded:: 1.8
|
||||||
|
|
||||||
|
To get the minimum value from list of numbers::
|
||||||
|
|
||||||
|
{{ list1 | min }}
|
||||||
|
|
||||||
|
To get the maximum value from a list of numbers::
|
||||||
|
|
||||||
|
{{ [3, 4, 2] | max }}
|
||||||
|
|
||||||
|
.. _set_theory_filters:
|
||||||
|
|
||||||
|
Set Theory Filters
|
||||||
|
------------------
|
||||||
|
All these functions return a unique set from sets or lists.
|
||||||
|
|
||||||
|
.. versionadded:: 1.4
|
||||||
|
|
||||||
|
To get a unique set from a list::
|
||||||
|
|
||||||
|
{{ list1 | unique }}
|
||||||
|
|
||||||
|
To get a union of two lists::
|
||||||
|
|
||||||
|
{{ list1 | union(list2) }}
|
||||||
|
|
||||||
|
To get the intersection of 2 lists (unique list of all items in both)::
|
||||||
|
|
||||||
|
{{ list1 | intersect(list2) }}
|
||||||
|
|
||||||
|
To get the difference of 2 lists (items in 1 that don't exist in 2)::
|
||||||
|
|
||||||
|
{{ list1 | difference(list2) }}
|
||||||
|
|
||||||
|
To get the symmetric difference of 2 lists (items exclusive to each list)::
|
||||||
|
|
||||||
|
{{ list1 | symmetric_difference(list2) }}
|
||||||
|
|
||||||
|
.. _version_comparison_filters:
|
||||||
|
|
||||||
|
Version Comparison Filters
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 1.6
|
||||||
|
|
||||||
|
To compare a version number, such as checking if the ``ansible_distribution_version``
|
||||||
|
version is greater than or equal to '12.04', you can use the ``version_compare`` filter.
|
||||||
|
|
||||||
|
The ``version_compare`` filter can also be used to evaluate the ``ansible_distribution_version``::
|
||||||
|
|
||||||
|
{{ ansible_distribution_version | version_compare('12.04', '>=') }}
|
||||||
|
|
||||||
|
If ``ansible_distribution_version`` is greater than or equal to 12, this filter will return True, otherwise it will return False.
|
||||||
|
|
||||||
|
The ``version_compare`` filter accepts the following operators::
|
||||||
|
|
||||||
|
<, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne
|
||||||
|
|
||||||
|
This filter also accepts a 3rd parameter, ``strict`` which defines if strict version parsing should
|
||||||
|
be used. The default is ``False``, and if set as ``True`` will use more strict version parsing::
|
||||||
|
|
||||||
|
{{ sample_version_var | version_compare('1.0', operator='lt', strict=True) }}
|
||||||
|
|
||||||
|
.. _random_filter:
|
||||||
|
|
||||||
|
Random Number Filter
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
.. versionadded:: 1.6
|
||||||
|
|
||||||
|
This filter can be used similar to the default jinja2 random filter (returning a random item from a sequence of
|
||||||
|
items), but can also generate a random number based on a range.
|
||||||
|
|
||||||
|
To get a random item from a list::
|
||||||
|
|
||||||
|
{{ ['a','b','c']|random }} => 'c'
|
||||||
|
|
||||||
|
To get a random number from 0 to supplied end::
|
||||||
|
|
||||||
|
{{ 59 |random}} * * * * root /script/from/cron
|
||||||
|
|
||||||
|
Get a random number from 0 to 100 but in steps of 10::
|
||||||
|
|
||||||
|
{{ 100 |random(step=10) }} => 70
|
||||||
|
|
||||||
|
Get a random number from 1 to 100 but in steps of 10::
|
||||||
|
|
||||||
|
{{ 100 |random(1, 10) }} => 31
|
||||||
|
{{ 100 |random(start=1, step=10) }} => 51
|
||||||
|
|
||||||
|
|
||||||
|
Shuffle Filter
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. versionadded:: 1.8
|
||||||
|
|
||||||
|
This filter will randomize an existing list, giving a different order every invocation.
|
||||||
|
|
||||||
|
To get a random list from an existing list::
|
||||||
|
|
||||||
|
{{ ['a','b','c']|shuffle }} => ['c','a','b']
|
||||||
|
{{ ['a','b','c']|shuffle }} => ['b','c','a']
|
||||||
|
|
||||||
|
note that when used with a non 'listable' item it is a noop, otherwise it always returns a list
|
||||||
|
|
||||||
|
|
||||||
|
.. _math_stuff:
|
||||||
|
|
||||||
|
Math
|
||||||
|
--------------------
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
|
||||||
|
To see if something is actually a number::
|
||||||
|
|
||||||
|
{{ myvar | isnan }}
|
||||||
|
|
||||||
|
Get the logarithm (default is e)::
|
||||||
|
|
||||||
|
{{ myvar | log }}
|
||||||
|
|
||||||
|
Get the base 10 logarithm::
|
||||||
|
|
||||||
|
{{ myvar | log(10) }}
|
||||||
|
|
||||||
|
Give me the power of 2! (or 5)::
|
||||||
|
|
||||||
|
{{ myvar | pow(2) }}
|
||||||
|
{{ myvar | pow(5) }}
|
||||||
|
|
||||||
|
Square root, or the 5th::
|
||||||
|
|
||||||
|
{{ myvar | root }}
|
||||||
|
{{ myvar | root(5) }}
|
||||||
|
|
||||||
|
Note that jinja2 already provides some like abs() and round().
|
||||||
|
|
||||||
|
.. _ipaddr_filter:
|
||||||
|
|
||||||
|
IP address filter
|
||||||
|
-----------------
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
To test if a string is a valid IP address::
|
||||||
|
|
||||||
|
{{ myvar | ipaddr }}
|
||||||
|
|
||||||
|
You can also require a specific IP protocol version::
|
||||||
|
|
||||||
|
{{ myvar | ipv4 }}
|
||||||
|
{{ myvar | ipv6 }}
|
||||||
|
|
||||||
|
IP address filter can also be used to extract specific information from an IP
|
||||||
|
address. For example, to get the IP address itself from a CIDR, you can use::
|
||||||
|
|
||||||
|
{{ '192.0.2.1/24' | ipaddr('address') }}
|
||||||
|
|
||||||
|
More information about ``ipaddr`` filter and complete usage guide can be found
|
||||||
|
in :doc:`playbooks_filters_ipaddr`.
|
||||||
|
|
||||||
|
.. _hash_filters:
|
||||||
|
|
||||||
|
Hashing filters
|
||||||
|
--------------------
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
To get the sha1 hash of a string::
|
||||||
|
|
||||||
|
{{ 'test1'|hash('sha1') }}
|
||||||
|
|
||||||
|
To get the md5 hash of a string::
|
||||||
|
|
||||||
|
{{ 'test1'|hash('md5') }}
|
||||||
|
|
||||||
|
Get a string checksum::
|
||||||
|
|
||||||
|
{{ 'test2'|checksum }}
|
||||||
|
|
||||||
|
Other hashes (platform dependant)::
|
||||||
|
|
||||||
|
{{ 'test2'|hash('blowfish') }}
|
||||||
|
|
||||||
|
To get a sha512 password hash (random salt)::
|
||||||
|
|
||||||
|
{{ 'passwordsaresecret'|password_hash('sha512') }}
|
||||||
|
|
||||||
|
To get a sha256 password hash with a specific salt::
|
||||||
|
|
||||||
|
{{ 'secretpassword'|password_hash('sha256', 'mysecretsalt') }}
|
||||||
|
|
||||||
|
|
||||||
|
Hash types available depend on the master system running ansible,
|
||||||
|
'hash' depends on hashlib password_hash depends on crypt.
|
||||||
|
|
||||||
|
|
||||||
|
.. _other_useful_filters:
|
||||||
|
|
||||||
|
Other Useful Filters
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
To use one value on true and another on false::
|
||||||
|
|
||||||
|
{{ name == "John" | ternary('Mr','Ms') }}
|
||||||
|
|
||||||
|
To concatenate a list into a string::
|
||||||
|
|
||||||
|
{{ list | join(" ") }}
|
||||||
|
|
||||||
|
To get the last name of a file path, like 'foo.txt' out of '/etc/asdf/foo.txt'::
|
||||||
|
|
||||||
|
{{ path | basename }}
|
||||||
|
|
||||||
|
To get the directory from a path::
|
||||||
|
|
||||||
|
{{ path | dirname }}
|
||||||
|
|
||||||
|
To expand a path containing a tilde (`~`) character (new in version 1.5)::
|
||||||
|
|
||||||
|
{{ path | expanduser }}
|
||||||
|
|
||||||
|
To get the real path of a link (new in version 1.8)::
|
||||||
|
|
||||||
|
{{ path | readlink }}
|
||||||
|
|
||||||
|
To work with Base64 encoded strings::
|
||||||
|
|
||||||
|
{{ encoded | b64decode }}
|
||||||
|
{{ decoded | b64encode }}
|
||||||
|
|
||||||
|
To create a UUID from a string (new in version 1.9)::
|
||||||
|
|
||||||
|
{{ hostname | to_uuid }}
|
||||||
|
|
||||||
|
To cast values as certain types, such as when you input a string as "True" from a vars_prompt and the system
|
||||||
|
doesn't know it is a boolean value::
|
||||||
|
|
||||||
|
- debug: msg=test
|
||||||
|
when: some_string_value | bool
|
||||||
|
|
||||||
|
To match strings against a regex, use the "match" or "search" filter::
|
||||||
|
|
||||||
|
vars:
|
||||||
|
url: "http://example.com/users/foo/resources/bar"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- shell: "msg='matched pattern 1'"
|
||||||
|
when: url | match("http://example.com/users/.*/resources/.*")
|
||||||
|
|
||||||
|
- debug: "msg='matched pattern 2'"
|
||||||
|
when: url | search("/users/.*/resources/.*")
|
||||||
|
|
||||||
|
'match' will require a complete match in the string, while 'search' will require a match inside of the string.
|
||||||
|
|
||||||
|
To replace text in a string with regex, use the "regex_replace" filter::
|
||||||
|
|
||||||
|
# convert "ansible" to "able"
|
||||||
|
{{ 'ansible' | regex_replace('^a.*i(.*)$', 'a\\1') }}
|
||||||
|
|
||||||
|
# convert "foobar" to "bar"
|
||||||
|
{{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }}
|
||||||
|
|
||||||
|
.. note:: If "regex_replace" filter is used with variables inside YAML arguments (as opposed to simpler 'key=value' arguments),
|
||||||
|
then you need to escape backreferences (e.g. ``\\1``) with 4 backslashes (``\\\\``) instead of 2 (``\\``).
|
||||||
|
|
||||||
|
A few useful filters are typically added with each new Ansible release. The development documentation shows
|
||||||
|
how to extend Ansible filters by writing your own as plugins, though in general, we encourage new ones
|
||||||
|
to be added to core so everyone can make use of them.
|
||||||
|
|
||||||
|
.. _builtin filters: http://jinja.pocoo.org/docs/templates/#builtin-filters
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:doc:`playbooks`
|
||||||
|
An introduction to playbooks
|
||||||
|
:doc:`playbooks_conditionals`
|
||||||
|
Conditional statements in playbooks
|
||||||
|
:doc:`playbooks_variables`
|
||||||
|
All about variables
|
||||||
|
:doc:`playbooks_loops`
|
||||||
|
Looping in playbooks
|
||||||
|
:doc:`playbooks_roles`
|
||||||
|
Playbook organization by roles
|
||||||
|
:doc:`playbooks_best_practices`
|
||||||
|
Best practices in playbooks
|
||||||
|
`User Mailing List <http://groups.google.com/group/ansible-devel>`_
|
||||||
|
Have a question? Stop by the google group!
|
||||||
|
`irc.freenode.net <http://irc.freenode.net>`_
|
||||||
|
#ansible IRC chat channel
|
||||||
|
|
||||||
|
|
471
docsite/rst/playbooks_filters_ipaddr.rst
Normal file
471
docsite/rst/playbooks_filters_ipaddr.rst
Normal file
|
@ -0,0 +1,471 @@
|
||||||
|
Jinja2 'ipaddr()' filter
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
``ipaddr()`` is a Jinja2 filter designed to provide an interface to `netaddr`_
|
||||||
|
Python package from within Ansible. It can operate on strings or lists of
|
||||||
|
items, test various data to check if they are valid IP addresses and manipulate
|
||||||
|
the input data to extract requested information. ``ipaddr()`` works both with
|
||||||
|
IPv4 and IPv6 addresses in various forms, there are also additional functions
|
||||||
|
available to manipulate IP subnets and MAC addresses.
|
||||||
|
|
||||||
|
To use this filter in Ansible, you need to install `netaddr`_ Python library on
|
||||||
|
a computer on which you use Ansible (it is not required on remote hosts).
|
||||||
|
It can usually be installed either via your system package manager, or using
|
||||||
|
``pip``::
|
||||||
|
|
||||||
|
pip install netaddr
|
||||||
|
|
||||||
|
.. _netaddr: https://pypi.python.org/pypi/netaddr
|
||||||
|
|
||||||
|
.. contents:: Topics
|
||||||
|
:local:
|
||||||
|
:depth: 2
|
||||||
|
:backlinks: top
|
||||||
|
|
||||||
|
Basic tests
|
||||||
|
-----------
|
||||||
|
|
||||||
|
``ipaddr()`` is designed to return the input value if a query is True, and
|
||||||
|
``False`` if query is False. This way it can be very easily used in chained
|
||||||
|
filters. To use the filter, pass a string to it::
|
||||||
|
|
||||||
|
{{ '192.0.2.0' | ipaddr }}
|
||||||
|
|
||||||
|
You can also pass the values as variables::
|
||||||
|
|
||||||
|
{{ myvar | ipaddr }}
|
||||||
|
|
||||||
|
Here are some example tests of various input strings::
|
||||||
|
|
||||||
|
# These values are valid IP addresses or network ranges
|
||||||
|
'192.168.0.1' -> 192.168.0.1
|
||||||
|
'192.168.32.0/24' -> 192.168.32.0/24
|
||||||
|
'fe80::100/10' -> fe80::100/10
|
||||||
|
45443646733 -> ::a:94a7:50d
|
||||||
|
'523454/24' -> 0.7.252.190/24
|
||||||
|
|
||||||
|
# Values that are not valid IP addresses or network ranges:
|
||||||
|
'localhost' -> False
|
||||||
|
True -> False
|
||||||
|
'space bar' -> False
|
||||||
|
False -> False
|
||||||
|
'' -> False
|
||||||
|
':' -> False
|
||||||
|
'fe80:/10' -> False
|
||||||
|
|
||||||
|
Sometimes you need either IPv4 or IPv6 addresses. To filter only for particular
|
||||||
|
type, ``ipaddr()`` filter has two "aliases", ``ipv4()`` and ``ipv6()``.
|
||||||
|
|
||||||
|
Example us of an IPv4 filter::
|
||||||
|
|
||||||
|
{{ myvar | ipv4 }}
|
||||||
|
|
||||||
|
And similar example of an IPv6 filter::
|
||||||
|
|
||||||
|
{{ myvar | ipv6 }}
|
||||||
|
|
||||||
|
Here's an example test to look for IPv4 addresses::
|
||||||
|
|
||||||
|
'192.168.0.1' -> 192.168.0.1
|
||||||
|
'192.168.32.0/24' -> 192.168.32.0/24
|
||||||
|
'fe80::100/10' -> False
|
||||||
|
45443646733 -> False
|
||||||
|
'523454/24' -> 0.7.252.190/24
|
||||||
|
|
||||||
|
And the same data filtered for IPv6 addresses::
|
||||||
|
|
||||||
|
'192.168.0.1' -> False
|
||||||
|
'192.168.32.0/24' -> False
|
||||||
|
'fe80::100/10' -> fe80::100/10
|
||||||
|
45443646733 -> ::a:94a7:50d
|
||||||
|
'523454/24' -> False
|
||||||
|
|
||||||
|
|
||||||
|
Filtering lists
|
||||||
|
---------------
|
||||||
|
|
||||||
|
You can filter entire lists - ``ipaddr()`` will return a list with values
|
||||||
|
valid for a particular query::
|
||||||
|
|
||||||
|
# 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']
|
||||||
|
|
||||||
|
# {{ test_list | ipv4 }}
|
||||||
|
['192.24.2.1', '192.168.32.0/24']
|
||||||
|
|
||||||
|
# {{ test_list | ipv6 }}
|
||||||
|
['::1', 'fe80::100/10', '2001:db8:32c:faad::/64']
|
||||||
|
|
||||||
|
|
||||||
|
Wrapping IPv6 addresses in [ ] brackets
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
Some configuration files require IPv6 addresses to be "wrapped" in square
|
||||||
|
brackets (``[ ]``). To accomplish that, you can use ``ipwrap()`` filter. It
|
||||||
|
will wrap all IPv6 addresses and leave any other strings intact::
|
||||||
|
|
||||||
|
# {{ test_list | ipwrap }}
|
||||||
|
['192.24.2.1', 'host.fqdn', '[::1]', '192.168.32.0/24', '[fe80::100]/10', True, '', '[2001:db8:32c:faad::]/64']
|
||||||
|
|
||||||
|
As you can see, ``ipwrap()`` did not filter out non-IP address values, which is
|
||||||
|
usually what you want when for example you are mixing IP addresses with
|
||||||
|
hostnames. If you still want to filter out all non-IP address values, you can
|
||||||
|
chain both filters together::
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr | ipwrap }}
|
||||||
|
['192.24.2.1', '[::1]', '192.168.32.0/24', '[fe80::100]/10', '[2001:db8:32c:faad::]/64']
|
||||||
|
|
||||||
|
|
||||||
|
Basic queries
|
||||||
|
-------------
|
||||||
|
|
||||||
|
You can provide single argument to each ``ipaddr()`` filter. Filter will then
|
||||||
|
treat it as a query and return values modified by that query. Lists will
|
||||||
|
contain only values that you are querying for.
|
||||||
|
|
||||||
|
Types of queries include:
|
||||||
|
|
||||||
|
- query by name: ``ipaddr('address')``, ``ipv4('network')``;
|
||||||
|
- query by CIDR range: ``ipaddr('192.168.0.0/24')``, ``ipv6('2001:db8::/32')``;
|
||||||
|
- query by index number: ``ipaddr('1')``, ``ipaddr('-1')``;
|
||||||
|
|
||||||
|
If a query type is not recognized, Ansible will raise an error.
|
||||||
|
|
||||||
|
|
||||||
|
Getting information about hosts and networks
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
Here's our test list again::
|
||||||
|
|
||||||
|
# Example list of values
|
||||||
|
test_list = ['192.24.2.1', 'host.fqdn', '::1', '192.168.32.0/24', 'fe80::100/10', True, '', '42540766412265424405338506004571095040/64']
|
||||||
|
|
||||||
|
Lets take above list and get only those elements that are host IP addresses,
|
||||||
|
and not network ranges::
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('address') }}
|
||||||
|
['192.24.2.1', '::1', 'fe80::100']
|
||||||
|
|
||||||
|
As you can see, even though some values had a host address with a CIDR prefix,
|
||||||
|
it was dropped by the filter. If you want host IP addresses with their correct
|
||||||
|
CIDR prefixes (as is common with IPv6 addressing), you can use
|
||||||
|
``ipaddr('host')`` filter::
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('host') }}
|
||||||
|
['192.24.2.1/32', '::1/128', 'fe80::100/10']
|
||||||
|
|
||||||
|
Filtering by IP address types also works::
|
||||||
|
|
||||||
|
# {{ test_list | ipv4('address') }}
|
||||||
|
['192.24.2.1']
|
||||||
|
|
||||||
|
# {{ test_list | ipv6('address') }}
|
||||||
|
['::1', 'fe80::100']
|
||||||
|
|
||||||
|
You can check if IP addresses or network ranges are accessible on a public
|
||||||
|
Internet, or if they are in private networks::
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('public') }}
|
||||||
|
['192.24.2.1', '2001:db8:32c:faad::/64']
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('private') }}
|
||||||
|
['192.168.32.0/24', 'fe80::100/10']
|
||||||
|
|
||||||
|
You can check which values are specifically network ranges::
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('net') }}
|
||||||
|
['192.168.32.0/24', '2001:db8:32c:faad::/64']
|
||||||
|
|
||||||
|
You can also check how many IP addresses can be in a certain range::
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('net') | ipaddr('size') }}
|
||||||
|
[256, 18446744073709551616L]
|
||||||
|
|
||||||
|
By specifying a network range as a query, you can check if given value is in
|
||||||
|
that range::
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('192.0.0.0/8') }}
|
||||||
|
['192.24.2.1', '192.168.32.0/24']
|
||||||
|
|
||||||
|
If you specify a positive or negative integer as a query, ``ipaddr()`` will
|
||||||
|
treat this as an index and will return specific IP address from a network
|
||||||
|
range, in the 'host/prefix' format::
|
||||||
|
|
||||||
|
# First IP address (network address)
|
||||||
|
# {{ test_list | ipaddr('net') | ipaddr('0') }}
|
||||||
|
['192.168.32.0/24', '2001:db8:32c:faad::/64']
|
||||||
|
|
||||||
|
# Second IP address (usually gateway host)
|
||||||
|
# {{ test_list | ipaddr('net') | ipaddr('1') }}
|
||||||
|
['192.168.32.1/24', '2001:db8:32c:faad::1/64']
|
||||||
|
|
||||||
|
# Last IP address (broadcast in IPv4 networks)
|
||||||
|
# {{ test_list | ipaddr('net') | ipaddr('-1') }}
|
||||||
|
['192.168.32.255/24', '2001:db8:32c:faad:ffff:ffff:ffff:ffff/64']
|
||||||
|
|
||||||
|
You can also select IP addresses from a range by their index, from the start or
|
||||||
|
end of the range::
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('net') | ipaddr('200') }}
|
||||||
|
['192.168.32.200/24', '2001:db8:32c:faad::c8/64']
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('net') | ipaddr('-200') }}
|
||||||
|
['192.168.32.56/24', '2001:db8:32c:faad:ffff:ffff:ffff:ff38/64']
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('net') | ipaddr('400') }}
|
||||||
|
['2001:db8:32c:faad::190/64']
|
||||||
|
|
||||||
|
|
||||||
|
Getting information from host/prefix values
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
Very frequently you use combination of IP addresses and subnet prefixes
|
||||||
|
("CIDR"), this is even more common with IPv6. ``ipaddr()`` filter can extract
|
||||||
|
useful data from these prefixes.
|
||||||
|
|
||||||
|
Here's an example set of two host prefixes (with some "control" values)::
|
||||||
|
|
||||||
|
host_prefix = ['2001:db8:deaf:be11::ef3/64', '192.0.2.48/24', '127.0.0.1', '192.168.0.0/16']
|
||||||
|
|
||||||
|
First, let's make sure that we only work with correct host/prefix values, not
|
||||||
|
just subnets or single IP addresses::
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('host/prefix') }}
|
||||||
|
['2001:db8:deaf:be11::ef3/64', '192.0.2.48/24']
|
||||||
|
|
||||||
|
In Debian-based systems, network configuration stored in ``/etc/network/interfaces`` file uses combination of IP address, network address, netmask and broadcast address to configure IPv4 network interface. We can get these values from single 'host/prefix' combination::
|
||||||
|
|
||||||
|
# Jinja2 template
|
||||||
|
{% set ipv4_host = host_prefix | unique | ipv4('host/prefix') | first %}
|
||||||
|
iface eth0 inet static
|
||||||
|
address {{ ipv4_host | ipaddr('address') }}
|
||||||
|
network {{ ipv4_host | ipaddr('network') }}
|
||||||
|
netmask {{ ipv4_host | ipaddr('netmask') }}
|
||||||
|
broadcast {{ ipv4_host | ipaddr('broadcast') }}
|
||||||
|
|
||||||
|
# Generated configuration file
|
||||||
|
iface eth0 inet static
|
||||||
|
address 192.0.2.48
|
||||||
|
network 192.0.2.0
|
||||||
|
netmask 255.255.255.0
|
||||||
|
broadcast 192.0.2.255
|
||||||
|
|
||||||
|
In above example, we needed to handle the fact that values were stored in
|
||||||
|
a list, which is unusual in IPv4 networks, where only single IP address can be
|
||||||
|
set on an interface. However, IPv6 networks can have multiple IP addresses set
|
||||||
|
on an interface::
|
||||||
|
|
||||||
|
# Jinja2 template
|
||||||
|
iface eth0 inet6 static
|
||||||
|
{% set ipv6_list = host_prefix | unique | ipv6('host/prefix') %}
|
||||||
|
address {{ ipv6_list[0] }}
|
||||||
|
{% if ipv6_list | length > 1 %}
|
||||||
|
{% for subnet in ipv6_list[1:] %}
|
||||||
|
up /sbin/ip address add {{ subnet }} dev eth0
|
||||||
|
down /sbin/ip address del {{ subnet }} dev eth0
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# Generated configuration file
|
||||||
|
iface eth0 inet6 static
|
||||||
|
address 2001:db8:deaf:be11::ef3/64
|
||||||
|
|
||||||
|
If needed, you can extract subnet and prefix information from 'host/prefix' value::
|
||||||
|
|
||||||
|
# {{ host_prefix | ipaddr('host/prefix') | ipaddr('subnet') }}
|
||||||
|
['2001:db8:deaf:be11::/64', '192.0.2.0/24']
|
||||||
|
|
||||||
|
# {{ host_prefix | ipaddr('host/prefix') | ipaddr('prefix') }}
|
||||||
|
[64, 24]
|
||||||
|
|
||||||
|
|
||||||
|
IP address conversion
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Here's our test list again::
|
||||||
|
|
||||||
|
# Example list of values
|
||||||
|
test_list = ['192.24.2.1', 'host.fqdn', '::1', '192.168.32.0/24', 'fe80::100/10', True, '', '42540766412265424405338506004571095040/64']
|
||||||
|
|
||||||
|
You can convert IPv4 addresses into IPv6 addresses::
|
||||||
|
|
||||||
|
# {{ test_list | ipv4('ipv6') }}
|
||||||
|
['::ffff:192.24.2.1/128', '::ffff:192.168.32.0/120']
|
||||||
|
|
||||||
|
Converting from IPv6 to IPv4 works very rarely::
|
||||||
|
|
||||||
|
# {{ test_list | ipv6('ipv4') }}
|
||||||
|
['0.0.0.1/32']
|
||||||
|
|
||||||
|
But we can make double conversion if needed::
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('ipv6') | ipaddr('ipv4') }}
|
||||||
|
['192.24.2.1/32', '0.0.0.1/32', '192.168.32.0/24']
|
||||||
|
|
||||||
|
You can convert IP addresses to integers, the same way that you can convert
|
||||||
|
integers into IP addresses::
|
||||||
|
|
||||||
|
# {{ test_list | ipaddr('address') | ipaddr('int') }}
|
||||||
|
[3222798849, 1, '3232243712/24', '338288524927261089654018896841347694848/10', '42540766412265424405338506004571095040/64']
|
||||||
|
|
||||||
|
You can convert IP addresses to PTR records::
|
||||||
|
|
||||||
|
# {% for address in test_list | ipaddr %}
|
||||||
|
# {{ address | ipaddr('revdns') }}
|
||||||
|
# {% endfor %}
|
||||||
|
1.2.24.192.in-addr.arpa.
|
||||||
|
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.
|
||||||
|
0.32.168.192.in-addr.arpa.
|
||||||
|
0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa.
|
||||||
|
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.a.a.f.c.2.3.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||||
|
|
||||||
|
|
||||||
|
Converting IPv4 address to 6to4 address
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
`6to4`_ tunnel is a way to access IPv6 Internet from IPv4-only network. If you
|
||||||
|
have a public IPv4 address, you automatically can configure it's IPv6
|
||||||
|
equivalent in ``2002::/16`` network range - after conversion you will gain
|
||||||
|
access to a ``2002:xxxx:xxxx::/48`` subnet which could be split into 65535
|
||||||
|
``/64`` subnets if needed.
|
||||||
|
|
||||||
|
To convert your IPv4 address, just send it through ``'6to4'`` filter. It will
|
||||||
|
be automatically converted to a router address (with ``::1/48`` host address)::
|
||||||
|
|
||||||
|
# {{ '193.0.2.0' | ipaddr('6to4') }}
|
||||||
|
2002:c100:0200::1/48
|
||||||
|
|
||||||
|
.. _6to4: https://en.wikipedia.org/wiki/6to4
|
||||||
|
|
||||||
|
|
||||||
|
Subnet manipulation
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
``ipsubnet()`` filter can be used to manipulate network subnets in several ways.
|
||||||
|
|
||||||
|
Here is some example IP address and subnet::
|
||||||
|
|
||||||
|
address = '192.168.144.5'
|
||||||
|
subnet = '192.168.0.0/16'
|
||||||
|
|
||||||
|
To check if a given string is a subnet, pass it through the filter without any
|
||||||
|
arguments. If given string is an IP address, it will be converted into
|
||||||
|
a subnet::
|
||||||
|
|
||||||
|
# {{ address | ipsubnet }}
|
||||||
|
192.168.144.5/32
|
||||||
|
|
||||||
|
# {{ subnet | ipsubnet }}
|
||||||
|
192.168.0.0/16
|
||||||
|
|
||||||
|
If you specify a subnet size as first parameter of ``ipsubnet()`` filter, and
|
||||||
|
subnet size is **smaller than current one**, you will get number of subnets
|
||||||
|
a given subnet can be split into::
|
||||||
|
|
||||||
|
# {{ subnet | ipsubnet(20) }}
|
||||||
|
16
|
||||||
|
|
||||||
|
Second argument of ``ipsubnet()`` filter is an index number; by specifying it
|
||||||
|
you can get new subnet with specified size::
|
||||||
|
|
||||||
|
# First subnet
|
||||||
|
# {{ subnet | ipsubnet(20, 0) }}
|
||||||
|
192.168.0.0/20
|
||||||
|
|
||||||
|
# Last subnet
|
||||||
|
# {{ subnet | ipsubnet(20, -1) }}
|
||||||
|
192.168.240.0/20
|
||||||
|
|
||||||
|
# Fifth subnet
|
||||||
|
# {{ subnet | ipsubnet(20, 5) }}
|
||||||
|
192.168.80.0/20
|
||||||
|
|
||||||
|
# Fifth to last subnet
|
||||||
|
# {{ subnet | ipsubnet(20, -5) }}
|
||||||
|
192.168.176.0/20
|
||||||
|
|
||||||
|
If you specify an IP address instead of a subnet, and give a subnet size as
|
||||||
|
a first argument, ``ipsubnet()`` filter will instead return biggest subnet that
|
||||||
|
contains a given IP address::
|
||||||
|
|
||||||
|
# {{ address | ipsubnet(20) }}
|
||||||
|
192.168.128.0/18
|
||||||
|
|
||||||
|
By specifying an index number as a second argument, you can select smaller and
|
||||||
|
smaller subnets::
|
||||||
|
|
||||||
|
# First subnet
|
||||||
|
# {{ subnet | ipsubnet(18, 0) }}
|
||||||
|
192.168.128.0/18
|
||||||
|
|
||||||
|
# Last subnet
|
||||||
|
# {{ subnet | ipsubnet(18, -1) }}
|
||||||
|
192.168.144.4/31
|
||||||
|
|
||||||
|
# Fifth subnet
|
||||||
|
# {{ subnet | ipsubnet(18, 5) }}
|
||||||
|
192.168.144.0/23
|
||||||
|
|
||||||
|
# Fifth to last subnet
|
||||||
|
# {{ subnet | ipsubnet(18, -5) }}
|
||||||
|
192.168.144.0/27
|
||||||
|
|
||||||
|
You can use ``ipsubnet()`` filter with ``ipaddr()`` filter to for example split
|
||||||
|
given ``/48`` prefix into smaller, ``/64`` subnets::
|
||||||
|
|
||||||
|
# {{ '193.0.2.0' | ipaddr('6to4') | ipsubnet(64, 58820) | ipaddr('1') }}
|
||||||
|
2002:c100:200:e5c4::1/64
|
||||||
|
|
||||||
|
Because of the size of IPv6 subnets, iteration over all of them to find the
|
||||||
|
correct one may take some time on slower computers, depending on the size
|
||||||
|
difference between subnets.
|
||||||
|
|
||||||
|
|
||||||
|
MAC address filter
|
||||||
|
------------------
|
||||||
|
|
||||||
|
You can use ``hwaddr()`` filter to check if a given string is a MAC address or
|
||||||
|
convert it between various formats. Examples::
|
||||||
|
|
||||||
|
# Example MAC address
|
||||||
|
macaddress = '1a:2b:3c:4d:5e:6f'
|
||||||
|
|
||||||
|
# Check if given string is a MAC address
|
||||||
|
# {{ macaddress | hwaddr }}
|
||||||
|
1a:2b:3c:4d:5e:6f
|
||||||
|
|
||||||
|
# Convert MAC address to PostgreSQL format
|
||||||
|
# {{ macaddress | hwaddr('pgsql') }}
|
||||||
|
1a2b3c:4d5e6f
|
||||||
|
|
||||||
|
# Convert MAC address to Cisco format
|
||||||
|
# {{ macaddress | hwaddr('cisco') }}
|
||||||
|
1a2b.3c4d.5e6f
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
:doc:`playbooks`
|
||||||
|
An introduction to playbooks
|
||||||
|
:doc:`playbooks_filters`
|
||||||
|
Introduction to Jinja2 filters and their uses
|
||||||
|
:doc:`playbooks_conditionals`
|
||||||
|
Conditional statements in playbooks
|
||||||
|
:doc:`playbooks_variables`
|
||||||
|
All about variables
|
||||||
|
:doc:`playbooks_loops`
|
||||||
|
Looping in playbooks
|
||||||
|
:doc:`playbooks_roles`
|
||||||
|
Playbook organization by roles
|
||||||
|
:doc:`playbooks_best_practices`
|
||||||
|
Best practices in playbooks
|
||||||
|
`User Mailing List <http://groups.google.com/group/ansible-devel>`_
|
||||||
|
Have a question? Stop by the google group!
|
||||||
|
`irc.freenode.net <http://irc.freenode.net>`_
|
||||||
|
#ansible IRC chat channel
|
||||||
|
|
||||||
|
|
|
@ -113,344 +113,8 @@ Jinja2 Filters
|
||||||
Filters in Jinja2 are a way of transforming template expressions from one kind of data into another. Jinja2
|
Filters in Jinja2 are a way of transforming template expressions from one kind of data into another. Jinja2
|
||||||
ships with many of these. See `builtin filters`_ in the official Jinja2 template documentation.
|
ships with many of these. See `builtin filters`_ in the official Jinja2 template documentation.
|
||||||
|
|
||||||
In addition to those, Ansible supplies many more.
|
In addition to those, Ansible supplies many more. See the :doc:`playbooks_filters` document
|
||||||
|
for a list of available filters and example usage guide.
|
||||||
.. _filters_for_formatting_data:
|
|
||||||
|
|
||||||
Filters For Formatting Data
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
The following filters will take a data structure in a template and render it in a slightly different format. These
|
|
||||||
are occasionally useful for debugging::
|
|
||||||
|
|
||||||
{{ some_variable | to_nice_json }}
|
|
||||||
{{ some_variable | to_nice_yaml }}
|
|
||||||
|
|
||||||
.. _filters_used_with_conditionals:
|
|
||||||
|
|
||||||
Filters Often Used With Conditionals
|
|
||||||
------------------------------------
|
|
||||||
|
|
||||||
The following tasks are illustrative of how filters can be used with conditionals::
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
|
|
||||||
- shell: /usr/bin/foo
|
|
||||||
register: result
|
|
||||||
ignore_errors: True
|
|
||||||
|
|
||||||
- debug: msg="it failed"
|
|
||||||
when: result|failed
|
|
||||||
|
|
||||||
# in most cases you'll want a handler, but if you want to do something right now, this is nice
|
|
||||||
- debug: msg="it changed"
|
|
||||||
when: result|changed
|
|
||||||
|
|
||||||
- debug: msg="it succeeded"
|
|
||||||
when: result|success
|
|
||||||
|
|
||||||
- debug: msg="it was skipped"
|
|
||||||
when: result|skipped
|
|
||||||
|
|
||||||
.. _forcing_variables_to_be_defined:
|
|
||||||
|
|
||||||
Forcing Variables To Be Defined
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
The default behavior from ansible and ansible.cfg is to fail if variables are undefined, but you can turn this off.
|
|
||||||
|
|
||||||
This allows an explicit check with this feature off::
|
|
||||||
|
|
||||||
{{ variable | mandatory }}
|
|
||||||
|
|
||||||
The variable value will be used as is, but the template evaluation will raise an error if it is undefined.
|
|
||||||
|
|
||||||
|
|
||||||
.. _defaulting_undefined_variables:
|
|
||||||
|
|
||||||
Defaulting Undefined Variables
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
Jinja2 provides a useful 'default' filter, that is often a better approach to failing if a variable is not defined::
|
|
||||||
|
|
||||||
{{ some_variable | default(5) }}
|
|
||||||
|
|
||||||
In the above example, if the variable 'some_variable' is not defined, the value used will be 5, rather than an error
|
|
||||||
being raised.
|
|
||||||
|
|
||||||
|
|
||||||
.. _omitting_undefined_variables:
|
|
||||||
|
|
||||||
Omitting Undefined Variables and Parameters
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
As of Ansible 1.8, it is possible to use the default filter to omit variables and module parameters using the special
|
|
||||||
`omit` variable::
|
|
||||||
|
|
||||||
- name: touch files with an optional mode
|
|
||||||
file: dest={{item.path}} state=touch mode={{item.mode|default(omit)}}
|
|
||||||
with_items:
|
|
||||||
- path: /tmp/foo
|
|
||||||
- path: /tmp/bar
|
|
||||||
- path: /tmp/baz
|
|
||||||
mode: "0444"
|
|
||||||
|
|
||||||
For the first two files in the list, the default mode will be determined by the umask of the system as the `mode=`
|
|
||||||
parameter will not be sent to the file module while the final file will receive the `mode=0444` option.
|
|
||||||
|
|
||||||
|
|
||||||
.. _list_filters:
|
|
||||||
|
|
||||||
List Filters
|
|
||||||
------------
|
|
||||||
|
|
||||||
These filters all operate on list variables.
|
|
||||||
|
|
||||||
.. versionadded:: 1.8
|
|
||||||
|
|
||||||
To get the minimum value from list of numbers::
|
|
||||||
|
|
||||||
{{ list1 | min }}
|
|
||||||
|
|
||||||
To get the maximum value from a list of numbers::
|
|
||||||
|
|
||||||
{{ [3, 4, 2] | max }}
|
|
||||||
|
|
||||||
.. _set_theory_filters:
|
|
||||||
|
|
||||||
Set Theory Filters
|
|
||||||
------------------
|
|
||||||
All these functions return a unique set from sets or lists.
|
|
||||||
|
|
||||||
.. versionadded:: 1.4
|
|
||||||
|
|
||||||
To get a unique set from a list::
|
|
||||||
|
|
||||||
{{ list1 | unique }}
|
|
||||||
|
|
||||||
To get a union of two lists::
|
|
||||||
|
|
||||||
{{ list1 | union(list2) }}
|
|
||||||
|
|
||||||
To get the intersection of 2 lists (unique list of all items in both)::
|
|
||||||
|
|
||||||
{{ list1 | intersect(list2) }}
|
|
||||||
|
|
||||||
To get the difference of 2 lists (items in 1 that don't exist in 2)::
|
|
||||||
|
|
||||||
{{ list1 | difference(list2) }}
|
|
||||||
|
|
||||||
To get the symmetric difference of 2 lists (items exclusive to each list)::
|
|
||||||
|
|
||||||
{{ list1 | symmetric_difference(list2) }}
|
|
||||||
|
|
||||||
.. _version_comparison_filters:
|
|
||||||
|
|
||||||
Version Comparison Filters
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
.. versionadded:: 1.6
|
|
||||||
|
|
||||||
To compare a version number, such as checking if the ``ansible_distribution_version``
|
|
||||||
version is greater than or equal to '12.04', you can use the ``version_compare`` filter.
|
|
||||||
|
|
||||||
The ``version_compare`` filter can also be used to evaluate the ``ansible_distribution_version``::
|
|
||||||
|
|
||||||
{{ ansible_distribution_version | version_compare('12.04', '>=') }}
|
|
||||||
|
|
||||||
If ``ansible_distribution_version`` is greater than or equal to 12, this filter will return True, otherwise it will return False.
|
|
||||||
|
|
||||||
The ``version_compare`` filter accepts the following operators::
|
|
||||||
|
|
||||||
<, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne
|
|
||||||
|
|
||||||
This filter also accepts a 3rd parameter, ``strict`` which defines if strict version parsing should
|
|
||||||
be used. The default is ``False``, and if set as ``True`` will use more strict version parsing::
|
|
||||||
|
|
||||||
{{ sample_version_var | version_compare('1.0', operator='lt', strict=True) }}
|
|
||||||
|
|
||||||
.. _random_filter:
|
|
||||||
|
|
||||||
Random Number Filter
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
.. versionadded:: 1.6
|
|
||||||
|
|
||||||
This filter can be used similar to the default jinja2 random filter (returning a random item from a sequence of
|
|
||||||
items), but can also generate a random number based on a range.
|
|
||||||
|
|
||||||
To get a random item from a list::
|
|
||||||
|
|
||||||
{{ ['a','b','c']|random }} => 'c'
|
|
||||||
|
|
||||||
To get a random number from 0 to supplied end::
|
|
||||||
|
|
||||||
{{ 59 |random}} * * * * root /script/from/cron
|
|
||||||
|
|
||||||
Get a random number from 0 to 100 but in steps of 10::
|
|
||||||
|
|
||||||
{{ 100 |random(step=10) }} => 70
|
|
||||||
|
|
||||||
Get a random number from 1 to 100 but in steps of 10::
|
|
||||||
|
|
||||||
{{ 100 |random(1, 10) }} => 31
|
|
||||||
{{ 100 |random(start=1, step=10) }} => 51
|
|
||||||
|
|
||||||
|
|
||||||
Shuffle Filter
|
|
||||||
--------------
|
|
||||||
|
|
||||||
.. versionadded:: 1.8
|
|
||||||
|
|
||||||
This filter will randomize an existing list, giving a different order every invocation.
|
|
||||||
|
|
||||||
To get a random list from an existing list::
|
|
||||||
|
|
||||||
{{ ['a','b','c']|shuffle }} => ['c','a','b']
|
|
||||||
{{ ['a','b','c']|shuffle }} => ['b','c','a']
|
|
||||||
|
|
||||||
note that when used with a non 'listable' item it is a noop, otherwise it always returns a list
|
|
||||||
|
|
||||||
|
|
||||||
.. _math_stuff:
|
|
||||||
|
|
||||||
Math
|
|
||||||
--------------------
|
|
||||||
.. versionadded:: 1.9
|
|
||||||
|
|
||||||
|
|
||||||
To see if something is actually a number::
|
|
||||||
|
|
||||||
{{ myvar | isnan }}
|
|
||||||
|
|
||||||
Get the logarithm (default is e)::
|
|
||||||
|
|
||||||
{{ myvar | log }}
|
|
||||||
|
|
||||||
Get the base 10 logarithm::
|
|
||||||
|
|
||||||
{{ myvar | log(10) }}
|
|
||||||
|
|
||||||
Give me the power of 2! (or 5)::
|
|
||||||
|
|
||||||
{{ myvar | pow(2) }}
|
|
||||||
{{ myvar | pow(5) }}
|
|
||||||
|
|
||||||
Square root, or the 5th::
|
|
||||||
|
|
||||||
{{ myvar | root }}
|
|
||||||
{{ myvar | root(5) }}
|
|
||||||
|
|
||||||
Note that jinja2 already provides some like abs() and round().
|
|
||||||
|
|
||||||
|
|
||||||
.. _hash_filters:
|
|
||||||
|
|
||||||
Hashing filters
|
|
||||||
--------------------
|
|
||||||
.. versionadded:: 1.9
|
|
||||||
|
|
||||||
To get the sha1 hash of a string::
|
|
||||||
|
|
||||||
{{ 'test1'|hash('sha1') }}
|
|
||||||
|
|
||||||
To get the md5 hash of a string::
|
|
||||||
|
|
||||||
{{ 'test1'|hash('md5') }}
|
|
||||||
|
|
||||||
Get a string checksum::
|
|
||||||
|
|
||||||
{{ 'test2'|checksum }}
|
|
||||||
|
|
||||||
Other hashes (platform dependant)::
|
|
||||||
|
|
||||||
{{ 'test2'|hash('blowfish') }}
|
|
||||||
|
|
||||||
To get a sha512 password hash (random salt)::
|
|
||||||
|
|
||||||
{{ 'passwordsaresecret'|password_hash('sha512') }}
|
|
||||||
|
|
||||||
To get a sha256 password hash with a specific salt::
|
|
||||||
|
|
||||||
{{ 'secretpassword'|password_hash('sha256', 'mysecretsalt') }}
|
|
||||||
|
|
||||||
|
|
||||||
Hash types available depend on the master system running ansible,
|
|
||||||
'hash' depends on hashlib password_hash depends on crypt.
|
|
||||||
|
|
||||||
|
|
||||||
.. _other_useful_filters:
|
|
||||||
|
|
||||||
Other Useful Filters
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
To use one value on true and another on false::
|
|
||||||
|
|
||||||
{{ name == "John" | ternary('Mr','Ms') }}
|
|
||||||
|
|
||||||
To concatenate a list into a string::
|
|
||||||
|
|
||||||
{{ list | join(" ") }}
|
|
||||||
|
|
||||||
To get the last name of a file path, like 'foo.txt' out of '/etc/asdf/foo.txt'::
|
|
||||||
|
|
||||||
{{ path | basename }}
|
|
||||||
|
|
||||||
To get the directory from a path::
|
|
||||||
|
|
||||||
{{ path | dirname }}
|
|
||||||
|
|
||||||
To expand a path containing a tilde (`~`) character (new in version 1.5)::
|
|
||||||
|
|
||||||
{{ path | expanduser }}
|
|
||||||
|
|
||||||
To get the real path of a link (new in version 1.8)::
|
|
||||||
|
|
||||||
{{ path | readlink }}
|
|
||||||
|
|
||||||
To work with Base64 encoded strings::
|
|
||||||
|
|
||||||
{{ encoded | b64decode }}
|
|
||||||
{{ decoded | b64encode }}
|
|
||||||
|
|
||||||
To create a UUID from a string (new in version 1.9)::
|
|
||||||
|
|
||||||
{{ hostname | to_uuid }}
|
|
||||||
|
|
||||||
To cast values as certain types, such as when you input a string as "True" from a vars_prompt and the system
|
|
||||||
doesn't know it is a boolean value::
|
|
||||||
|
|
||||||
- debug: msg=test
|
|
||||||
when: some_string_value | bool
|
|
||||||
|
|
||||||
To match strings against a regex, use the "match" or "search" filter::
|
|
||||||
|
|
||||||
vars:
|
|
||||||
url: "http://example.com/users/foo/resources/bar"
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
- shell: "msg='matched pattern 1'"
|
|
||||||
when: url | match("http://example.com/users/.*/resources/.*")
|
|
||||||
|
|
||||||
- debug: "msg='matched pattern 2'"
|
|
||||||
when: url | search("/users/.*/resources/.*")
|
|
||||||
|
|
||||||
'match' will require a complete match in the string, while 'search' will require a match inside of the string.
|
|
||||||
|
|
||||||
To replace text in a string with regex, use the "regex_replace" filter::
|
|
||||||
|
|
||||||
# convert "ansible" to "able"
|
|
||||||
{{ 'ansible' | regex_replace('^a.*i(.*)$', 'a\\1') }}
|
|
||||||
|
|
||||||
# convert "foobar" to "bar"
|
|
||||||
{{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }}
|
|
||||||
|
|
||||||
.. note:: If "regex_replace" filter is used with variables inside YAML arguments (as opposed to simpler 'key=value' arguments),
|
|
||||||
then you need to escape backreferences (e.g. ``\\1``) with 4 backslashes (``\\\\``) instead of 2 (``\\``).
|
|
||||||
|
|
||||||
A few useful filters are typically added with each new Ansible release. The development documentation shows
|
|
||||||
how to extend Ansible filters by writing your own as plugins, though in general, we encourage new ones
|
|
||||||
to be added to core so everyone can make use of them.
|
|
||||||
|
|
||||||
.. _yaml_gotchas:
|
.. _yaml_gotchas:
|
||||||
|
|
||||||
|
@ -1168,6 +832,8 @@ how all of these things can work together.
|
||||||
An introduction to playbooks
|
An introduction to playbooks
|
||||||
:doc:`playbooks_conditionals`
|
:doc:`playbooks_conditionals`
|
||||||
Conditional statements in playbooks
|
Conditional statements in playbooks
|
||||||
|
:doc:`playbooks_filters`
|
||||||
|
Jinja2 filters and their uses
|
||||||
:doc:`playbooks_loops`
|
:doc:`playbooks_loops`
|
||||||
Looping in playbooks
|
Looping in playbooks
|
||||||
:doc:`playbooks_roles`
|
:doc:`playbooks_roles`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue