From 9eeaf1c5b56b142c09967201dd3f2713a226f803 Mon Sep 17 00:00:00 2001 From: fermin Date: Thu, 14 Oct 2021 17:11:24 +0200 Subject: [PATCH] Docs - add code-block:: wrapping for playbooks filter doc (#75953) * Add code-block Co-authored-by: Abhijeet Kasurde --- .../rst/user_guide/playbooks_filters.rst | 662 +++++++++++++----- 1 file changed, 494 insertions(+), 168 deletions(-) diff --git a/docs/docsite/rst/user_guide/playbooks_filters.rst b/docs/docsite/rst/user_guide/playbooks_filters.rst index 9116172beae..67456e36845 100644 --- a/docs/docsite/rst/user_guide/playbooks_filters.rst +++ b/docs/docsite/rst/user_guide/playbooks_filters.rst @@ -21,7 +21,9 @@ Filters can help you manage missing or undefined variables by providing defaults Providing default values ------------------------ -You can provide default values for variables directly in your templates using the Jinja2 'default' filter. This is often a better approach than failing if a variable is not defined:: +You can provide default values for variables directly in your templates using the Jinja2 'default' filter. This is often a better approach than failing if a variable is not defined: + +.. code-block:: yaml+jinja {{ some_variable | default(5) }} @@ -30,7 +32,9 @@ In the above example, if the variable 'some_variable' is not defined, Ansible us Beginning in version 2.8, attempting to access an attribute of an Undefined value in Jinja will return another Undefined value, rather than throwing an error immediately. This means that you can now simply use a default with a value in a nested data structure (in other words, :code:`{{ foo.bar.baz | default('DEFAULT') }}`) when you do not know if the intermediate values are defined. -If you want to use the default value when variables evaluate to false or an empty string you have to set the second parameter to ``true``:: +If you want to use the default value when variables evaluate to false or an empty string you have to set the second parameter to ``true``: + +.. code-block:: yaml+jinja {{ lookup('env', 'MY_USER') | default('admin', true) }} @@ -39,7 +43,9 @@ If you want to use the default value when variables evaluate to false or an empt Making variables optional ------------------------- -By default Ansible requires values for all variables in a templated expression. However, you can make specific variables optional. For example, you might want to use a system default for some items and control the value for others. To make a variable optional, set the default value to the special variable ``omit``:: +By default Ansible requires values for all variables in a templated expression. However, you can make specific variables optional. For example, you might want to use a system default for some items and control the value for others. To make a variable optional, set the default value to the special variable ``omit``: + +.. code-block:: yaml+jinja - name: Touch files with an optional mode ansible.builtin.file: @@ -62,7 +68,9 @@ In this example, the default mode for the files ``/tmp/foo`` and ``/tmp/bar`` is Defining mandatory values ------------------------- -If you configure Ansible to ignore undefined variables, you may want to define some values as mandatory. By default, Ansible fails if a variable in your playbook or command is undefined. You can configure Ansible to allow undefined variables by setting :ref:`DEFAULT_UNDEFINED_VAR_BEHAVIOR` to ``false``. In that case, you may want to require some variables to be defined. You can do this with:: +If you configure Ansible to ignore undefined variables, you may want to define some values as mandatory. By default, Ansible fails if a variable in your playbook or command is undefined. You can configure Ansible to allow undefined variables by setting :ref:`DEFAULT_UNDEFINED_VAR_BEHAVIOR` to ``false``. In that case, you may want to require some variables to be defined. You can do this with: + +.. code-block:: yaml+jinja {{ variable | mandatory }} @@ -78,11 +86,15 @@ A convenient way of requiring a variable to be overridden is to give it an undef Defining different values for true/false/null (ternary) ======================================================= -You can create a test, then define one value to use when the test returns true and another when the test returns false (new in version 1.9):: +You can create a test, then define one value to use when the test returns true and another when the test returns false (new in version 1.9): + +.. code-block:: yaml+jinja {{ (status == 'needs_restart') | ternary('restart', 'continue') }} -In addition, you can define a one value to use on true, one value on false and a third value on null (new in version 2.8):: +In addition, you can define a one value to use on true, one value on false and a third value on null (new in version 2.8): + +.. code-block:: yaml+jinja {{ enabled | ternary('no shutdown', 'shutdown', omit) }} @@ -96,7 +108,9 @@ Discovering the data type .. versionadded:: 2.3 -If you are unsure of the underlying Python type of a variable, you can use the ``type_debug`` filter to display it. This is useful in debugging when you need a particular type of variable:: +If you are unsure of the underlying Python type of a variable, you can use the ``type_debug`` filter to display it. This is useful in debugging when you need a particular type of variable: + +.. code-block:: yaml+jinja {{ myvar | type_debug }} @@ -109,17 +123,23 @@ Transforming dictionaries into lists .. versionadded:: 2.6 -Use the ``dict2items`` filter to transform a dictionary into a list of items suitable for :ref:`looping `:: +Use the ``dict2items`` filter to transform a dictionary into a list of items suitable for :ref:`looping `: + +.. code-block:: yaml+jinja {{ dict | dict2items }} -Dictionary data (before applying the ``dict2items`` filter):: +Dictionary data (before applying the ``dict2items`` filter): + +.. code-block:: yaml tags: Application: payment Environment: dev -List data (after applying the ``dict2items`` filter):: +List data (after applying the ``dict2items`` filter): + +.. code-block:: yaml - key: Application value: payment @@ -130,17 +150,23 @@ List data (after applying the ``dict2items`` filter):: The ``dict2items`` filter is the reverse of the ``items2dict`` filter. -If you want to configure the names of the keys, the ``dict2items`` filter accepts 2 keyword arguments. Pass the ``key_name`` and ``value_name`` arguments to configure the names of the keys in the list output:: +If you want to configure the names of the keys, the ``dict2items`` filter accepts 2 keyword arguments. Pass the ``key_name`` and ``value_name`` arguments to configure the names of the keys in the list output: + +.. code-block:: yaml+jinja {{ files | dict2items(key_name='file', value_name='path') }} -Dictionary data (before applying the ``dict2items`` filter):: +Dictionary data (before applying the ``dict2items`` filter): + +.. code-block:: yaml files: users: /etc/passwd groups: /etc/group -List data (after applying the ``dict2items`` filter):: +List data (after applying the ``dict2items`` filter): + +.. code-block:: yaml - file: users path: /etc/passwd @@ -153,11 +179,15 @@ Transforming lists into dictionaries .. versionadded:: 2.7 -Use the ``items2dict`` filter to transform a list into a dictionary, mapping the content into ``key: value`` pairs:: +Use the ``items2dict`` filter to transform a list into a dictionary, mapping the content into ``key: value`` pairs: + +.. code-block:: yaml+jinja {{ tags | items2dict }} -List data (before applying the ``items2dict`` filter):: +List data (before applying the ``items2dict`` filter): + +.. code-block:: yaml tags: - key: Application @@ -165,14 +195,18 @@ List data (before applying the ``items2dict`` filter):: - key: Environment value: dev -Dictionary data (after applying the ``items2dict`` filter):: +Dictionary data (after applying the ``items2dict`` filter): + +.. code-block:: text Application: payment Environment: dev The ``items2dict`` filter is the reverse of the ``dict2items`` filter. -Not all lists use ``key`` to designate keys and ``value`` to designate values. For example:: +Not all lists use ``key`` to designate keys and ``value`` to designate values. For example: + +.. code-block:: yaml fruits: - fruit: apple @@ -182,7 +216,9 @@ Not all lists use ``key`` to designate keys and ``value`` to designate values. F - fruit: grapefruit color: yellow -In this example, you must pass the ``key_name`` and ``value_name`` arguments to configure the transformation. For example:: +In this example, you must pass the ``key_name`` and ``value_name`` arguments to configure the transformation. For example: + +.. code-block:: yaml+jinja {{ tags | items2dict(key_name='fruit', value_name='color') }} @@ -191,13 +227,17 @@ If you do not pass these arguments, or do not pass the correct values for your l Forcing the data type --------------------- -You can cast values as certain types. For example, if you expect the input "True" from a :ref:`vars_prompt ` and you want Ansible to recognize it as a boolean value instead of a string:: +You can cast values as certain types. For example, if you expect the input "True" from a :ref:`vars_prompt ` and you want Ansible to recognize it as a boolean value instead of a string: + +.. code-block:: yaml - ansible.builtin.debug: msg: test when: some_string_value | bool -If you want to perform a mathematical comparison on a fact and you want Ansible to recognize it as an integer instead of a string:: +If you want to perform a mathematical comparison on a fact and you want Ansible to recognize it as an integer instead of a string: + +.. code-block:: yaml - shell: echo "only on Red Hat 6, derivatives, and later" when: ansible_facts['os_family'] == "RedHat" and ansible_facts['lsb']['major_release'] | int >= 6 @@ -210,35 +250,47 @@ If you want to perform a mathematical comparison on a fact and you want Ansible Formatting data: YAML and JSON ============================== -You can switch a data structure in a template from or to JSON or YAML format, with options for formatting, indenting, and loading data. The basic filters are occasionally useful for debugging:: +You can switch a data structure in a template from or to JSON or YAML format, with options for formatting, indenting, and loading data. The basic filters are occasionally useful for debugging: + +.. code-block:: yaml+jinja {{ some_variable | to_json }} {{ some_variable | to_yaml }} -For human readable output, you can use:: +For human readable output, you can use: + +.. code-block:: yaml+jinja {{ some_variable | to_nice_json }} {{ some_variable | to_nice_yaml }} -You can change the indentation of either format:: +You can change the indentation of either format: + +.. code-block:: yaml+jinja {{ some_variable | to_nice_json(indent=2) }} {{ some_variable | to_nice_yaml(indent=8) }} The ``to_yaml`` and ``to_nice_yaml`` filters use the `PyYAML library`_ which has a default 80 symbol string length limit. That causes unexpected line break after 80th symbol (if there is a space after 80th symbol) -To avoid such behavior and generate long lines, use the ``width`` option. You must use a hardcoded number to define the width, instead of a construction like ``float("inf")``, because the filter does not support proxying Python functions. For example:: +To avoid such behavior and generate long lines, use the ``width`` option. You must use a hardcoded number to define the width, instead of a construction like ``float("inf")``, because the filter does not support proxying Python functions. For example: + +.. code-block:: yaml+jinja {{ some_variable | to_yaml(indent=8, width=1337) }} {{ some_variable | to_nice_yaml(indent=8, width=1337) }} The filter does support passing through other YAML parameters. For a full list, see the `PyYAML documentation`_. -If you are reading in some already formatted data:: +If you are reading in some already formatted data: + +.. code-block:: yaml+jinja {{ some_variable | from_json }} {{ some_variable | from_yaml }} -for example:: +for example: + +.. code-block:: yaml+jinja tasks: - name: Register JSON output as a variable @@ -253,15 +305,21 @@ for example:: Filter `to_json` and Unicode support ------------------------------------ -By default `to_json` and `to_nice_json` will convert data received to ASCII, so:: +By default `to_json` and `to_nice_json` will convert data received to ASCII, so: + +.. code-block:: yaml+jinja {{ 'München'| to_json }} -will return:: +will return: + +.. code-block:: text 'M\u00fcnchen' -To keep Unicode characters, pass the parameter `ensure_ascii=False` to the filter:: +To keep Unicode characters, pass the parameter `ensure_ascii=False` to the filter: + +.. code-block:: yaml+jinja {{ 'München'| to_json(ensure_ascii=False) }} @@ -272,7 +330,9 @@ To keep Unicode characters, pass the parameter `ensure_ascii=False` to the filte To parse multi-document YAML strings, the ``from_yaml_all`` filter is provided. The ``from_yaml_all`` filter will return a generator of parsed YAML documents. -for example:: +for example: + +.. code-block:: yaml+jinja tasks: - name: Register a file content as a variable @@ -296,7 +356,9 @@ Combining items from multiple lists: zip and zip_longest .. versionadded:: 2.3 -To get a list combining the elements of other lists use ``zip``:: +To get a list combining the elements of other lists use ``zip``: + +.. code-block:: yaml+jinja - name: Give me list combo of two lists ansible.builtin.debug: @@ -310,7 +372,9 @@ To get a list combining the elements of other lists use ``zip``:: # => [[1, "a"], [2, "b"], [3, "c"]] -To always exhaust all lists use ``zip_longest``:: +To always exhaust all lists use ``zip_longest``: + +.. code-block:: yaml+jinja - name: Give me longest combo of three lists , fill with X ansible.builtin.debug: @@ -318,11 +382,15 @@ To always exhaust all lists use ``zip_longest``:: # => [[1, "a", 21], [2, "b", 22], [3, "c", 23], ["X", "d", "X"], ["X", "e", "X"], ["X", "f", "X"]] -Similarly to the output of the ``items2dict`` filter mentioned above, these filters can be used to construct a ``dict``:: +Similarly to the output of the ``items2dict`` filter mentioned above, these filters can be used to construct a ``dict``: + +.. code-block:: yaml+jinja {{ dict(keys_list | zip(values_list)) }} -List data (before applying the ``zip`` filter):: +List data (before applying the ``zip`` filter): + +.. code-block:: yaml keys_list: - one @@ -331,7 +399,9 @@ List data (before applying the ``zip`` filter):: - apple - orange -Dictionary data (after applying the ``zip`` filter):: +Dictionary data (after applying the ``zip`` filter): + +.. code-block:: yaml one: apple two: orange @@ -341,11 +411,15 @@ Combining objects and subelements .. versionadded:: 2.7 -The ``subelements`` filter produces a product of an object and the subelement values of that object, similar to the ``subelements`` lookup. This lets you specify individual subelements to use in a template. For example, this expression:: +The ``subelements`` filter produces a product of an object and the subelement values of that object, similar to the ``subelements`` lookup. This lets you specify individual subelements to use in a template. For example, this expression: + +.. code-block:: yaml+jinja {{ users | subelements('groups', skip_missing=True) }} -Data before applying the ``subelements`` filter:: +Data before applying the ``subelements`` filter: + +.. code-block:: yaml users: - name: alice @@ -361,7 +435,9 @@ Data before applying the ``subelements`` filter:: groups: - docker -Data after applying the ``subelements`` filter:: +Data after applying the ``subelements`` filter: + +.. code-block:: yaml - - name: alice @@ -389,7 +465,9 @@ Data after applying the ``subelements`` filter:: - docker - docker -You can use the transformed data with ``loop`` to iterate over the same subelement for multiple objects:: +You can use the transformed data with ``loop`` to iterate over the same subelement for multiple objects: + +.. code-block:: yaml+jinja - name: Set authorized ssh key, extracting just that data from 'users' ansible.posix.authorized_key: @@ -404,15 +482,21 @@ Combining hashes/dictionaries .. versionadded:: 2.0 -The ``combine`` filter allows hashes to be merged. For example, the following would override keys in one hash:: +The ``combine`` filter allows hashes to be merged. For example, the following would override keys in one hash: + +.. code-block:: yaml+jinja {{ {'a':1, 'b':2} | combine({'b':3}) }} -The resulting hash would be:: +The resulting hash would be: + +.. code-block:: text {'a':1, 'b':3} -The filter can also take multiple arguments to merge:: +The filter can also take multiple arguments to merge: + +.. code-block:: yaml+jinja {{ a | combine(b, c, d) }} {{ [a, b, c, d] | combine }} @@ -444,11 +528,15 @@ list_merge z: patch b: patch -If ``recursive=False`` (the default), nested hash aren't merged:: +If ``recursive=False`` (the default), nested hash aren't merged: + +.. code-block:: yaml+jinja {{ default | combine(patch) }} -This would result in:: +This would result in: + +.. code-block:: yaml a: y: patch @@ -456,11 +544,15 @@ This would result in:: b: patch c: default -If ``recursive=True``, recurse into nested hash and merge their keys:: +If ``recursive=True``, recurse into nested hash and merge their keys: + +.. code-block:: yaml+jinja {{ default | combine(patch, recursive=True) }} -This would result in:: +This would result in: + +.. code-block:: yaml a: x: default @@ -469,7 +561,9 @@ This would result in:: b: patch c: default -If ``list_merge='replace'`` (the default), arrays from the right hash will "replace" the ones in the left hash:: +If ``list_merge='replace'`` (the default), arrays from the right hash will "replace" the ones in the left hash: + +.. code-block:: yaml default: a: @@ -478,45 +572,61 @@ If ``list_merge='replace'`` (the default), arrays from the right hash will "repl a: - patch -.. code-block:: jinja +.. code-block:: yaml+jinja {{ default | combine(patch) }} -This would result in:: +This would result in: + +.. code-block:: yaml a: - patch -If ``list_merge='keep'``, arrays from the left hash will be kept:: +If ``list_merge='keep'``, arrays from the left hash will be kept: + +.. code-block:: yaml+jinja {{ default | combine(patch, list_merge='keep') }} -This would result in:: +This would result in: + +.. code-block:: yaml a: - default -If ``list_merge='append'``, arrays from the right hash will be appended to the ones in the left hash:: +If ``list_merge='append'``, arrays from the right hash will be appended to the ones in the left hash: + +.. code-block:: yaml+jinja {{ default | combine(patch, list_merge='append') }} -This would result in:: +This would result in: + +.. code-block:: yaml a: - default - patch -If ``list_merge='prepend'``, arrays from the right hash will be prepended to the ones in the left hash:: +If ``list_merge='prepend'``, arrays from the right hash will be prepended to the ones in the left hash: + +.. code-block:: yaml+jinja {{ default | combine(patch, list_merge='prepend') }} -This would result in:: +This would result in: + +.. code-block:: yaml a: - patch - default -If ``list_merge='append_rp'``, arrays from the right hash will be appended to the ones in the left hash. Elements of arrays in the left hash that are also in the corresponding array of the right hash will be removed ("rp" stands for "remove present"). Duplicate elements that aren't in both hashes are kept:: +If ``list_merge='append_rp'``, arrays from the right hash will be appended to the ones in the left hash. Elements of arrays in the left hash that are also in the corresponding array of the right hash will be removed ("rp" stands for "remove present"). Duplicate elements that aren't in both hashes are kept: + +.. code-block:: yaml default: a: @@ -531,11 +641,13 @@ If ``list_merge='append_rp'``, arrays from the right hash will be appended to th - 5 - 5 -.. code-block:: jinja +.. code-block:: yaml+jinja {{ default | combine(patch, list_merge='append_rp') }} -This would result in:: +This would result in: + +.. code-block:: yaml a: - 1 @@ -546,11 +658,15 @@ This would result in:: - 5 - 5 -If ``list_merge='prepend_rp'``, the behavior is similar to the one for ``append_rp``, but elements of arrays in the right hash are prepended:: +If ``list_merge='prepend_rp'``, the behavior is similar to the one for ``append_rp``, but elements of arrays in the right hash are prepended: + +.. code-block:: yaml+jinja {{ default | combine(patch, list_merge='prepend_rp') }} -This would result in:: +This would result in: + +.. code-block:: yaml a: - 3 @@ -561,7 +677,9 @@ This would result in:: - 1 - 2 -``recursive`` and ``list_merge`` can be used together:: +``recursive`` and ``list_merge`` can be used together: + +.. code-block:: yaml default: a: @@ -588,11 +706,13 @@ This would result in:: - 4 - key: value -.. code-block:: jinja +.. code-block:: yaml+jinja {{ default | combine(patch, recursive=True, list_merge='append_rp') }} -This would result in:: +This would result in: + +.. code-block:: yaml a: a': @@ -619,23 +739,31 @@ Selecting values from arrays or hashtables .. versionadded:: 2.1 -The `extract` filter is used to map from a list of indices to a list of values from a container (hash or array):: +The `extract` filter is used to map from a list of indices to a list of values from a container (hash or array): + +.. code-block:: yaml+jinja {{ [0,2] | map('extract', ['x','y','z']) | list }} {{ ['x','y'] | map('extract', {'x': 42, 'y': 31}) | list }} -The results of the above expressions would be:: +The results of the above expressions would be: + +.. code-block:: none ['x', 'z'] [42, 31] -The filter can take another argument:: +The filter can take another argument: + +.. code-block:: yaml+jinja {{ groups['x'] | map('extract', hostvars, 'ec2_ip_address') | list }} This takes the list of hosts in group 'x', looks them up in `hostvars`, and then looks up the `ec2_ip_address` of the result. The final result is a list of IP addresses for the hosts in group 'x'. -The third argument to the filter can also be a list, for a recursive lookup inside the container:: +The third argument to the filter can also be a list, for a recursive lookup inside the container: + +.. code-block:: yaml+jinja {{ ['a'] | map('extract', b, ['x','y']) | list }} @@ -649,7 +777,9 @@ This set of filters returns a list of combined lists. permutations ^^^^^^^^^^^^ -To get permutations of a list:: +To get permutations of a list: + +.. code-block:: yaml+jinja - name: Give me largest permutations (order matters) ansible.builtin.debug: @@ -661,7 +791,9 @@ To get permutations of a list:: combinations ^^^^^^^^^^^^ -Combinations always require a set size:: +Combinations always require a set size: + +.. code-block:: yaml+jinja - name: Give me combinations for sets of two ansible.builtin.debug: @@ -673,13 +805,17 @@ products ^^^^^^^^ The product filter returns the `cartesian product `_ of the input iterables. This is roughly equivalent to nested for-loops in a generator expression. -For example:: +For example: + +.. code-block:: yaml+jinja - name: Generate multiple hostnames ansible.builtin.debug: msg: "{{ ['foo', 'bar'] | product(['com']) | map('join', '.') | join(',') }}" -This would result in:: +This would result in: + +.. code-block:: json { "msg": "foo.com,bar.com" } @@ -697,7 +833,9 @@ To select a single element or a data subset from a complex data structure in JSO .. note:: You must manually install the **jmespath** dependency on the Ansible controller before using this filter. This filter is built upon **jmespath**, and you can use the same syntax. For examples, see `jmespath examples `_. -Consider this data structure:: +Consider this data structure: + +.. code-block:: json { "domain_definition": { @@ -746,21 +884,27 @@ Consider this data structure:: } } -To extract all clusters from this structure, you can use the following query:: +To extract all clusters from this structure, you can use the following query: + +.. code-block:: yaml+jinja - name: Display all cluster names ansible.builtin.debug: var: item loop: "{{ domain_definition | community.general.json_query('domain.cluster[*].name') }}" -To extract all server names:: +To extract all server names: + +.. code-block:: yaml+jinja - name: Display all server names ansible.builtin.debug: var: item loop: "{{ domain_definition | community.general.json_query('domain.server[*].name') }}" -To extract ports from cluster1:: +To extract ports from cluster1: + +.. code-block:: yaml+jinja - name: Display all ports from cluster1 ansible.builtin.debug: @@ -771,7 +915,9 @@ To extract ports from cluster1:: .. note:: You can use a variable to make the query more readable. -To print out the ports from cluster1 in a comma separated string:: +To print out the ports from cluster1 in a comma separated string: + +.. code-block:: yaml+jinja - name: Display all ports from cluster1 as a string ansible.builtin.debug: @@ -779,7 +925,9 @@ To print out the ports from cluster1 in a comma separated string:: .. note:: In the example above, quoting literals using backticks avoids escaping quotes and maintains readability. -You can use YAML `single quote escaping `_:: +You can use YAML `single quote escaping `_: + +.. code-block:: yaml+jinja - name: Display all ports from cluster1 ansible.builtin.debug: @@ -788,7 +936,9 @@ You can use YAML `single quote escaping `_ collection. Follow the installation instructions to install that collection. -To get a random MAC address from a string prefix starting with '52:54:00':: +To get a random MAC address from a string prefix starting with '52:54:00': + +.. code-block:: yaml+jinja "{{ '52:54:00' | community.general.random_mac }}" # => '52:54:00:ef:1c:03' @@ -844,7 +1000,9 @@ Note that if anything is wrong with the prefix string, the filter will issue an .. versionadded:: 2.9 -As of Ansible version 2.9, you can also initialize the random number generator from a seed to create random-but-idempotent MAC addresses:: +As of Ansible version 2.9, you can also initialize the random number generator from a seed to create random-but-idempotent MAC addresses: + +.. code-block:: yaml+jinja "{{ '52:54:00' | community.general.random_mac(seed=inventory_hostname) }}" @@ -856,29 +1014,39 @@ Random items or numbers The ``random`` filter in Ansible is an extension of the default Jinja2 random filter, and can be used to return a random item from a sequence of items or to generate a random number based on a range. -To get a random item from a list:: +To get a random item from a list: + +.. code-block:: yaml+jinja "{{ ['a','b','c'] | random }}" # => 'c' -To get a random number between 0 (inclusive) and a specified integer (exclusive):: +To get a random number between 0 (inclusive) and a specified integer (exclusive): + +.. code-block:: yaml+jinja "{{ 60 | random }} * * * * root /script/from/cron" # => '21 * * * * root /script/from/cron' -To get a random number from 0 to 100 but in steps of 10:: +To get a random number from 0 to 100 but in steps of 10: + +.. code-block:: yaml+jinja {{ 101 | random(step=10) }} # => 70 -To get a random number from 1 to 100 but in steps of 10:: +To get a random number from 1 to 100 but in steps of 10: + +.. code-block:: yaml+jinja {{ 101 | random(1, 10) }} # => 31 {{ 101 | random(start=1, step=10) }} # => 51 -You can initialize the random number generator from a seed to create random-but-idempotent numbers:: +You can initialize the random number generator from a seed to create random-but-idempotent numbers: + +.. code-block:: yaml+jinja "{{ 60 | random(seed=inventory_hostname) }} * * * * root /script/from/cron" @@ -887,14 +1055,18 @@ Shuffling a list The ``shuffle`` filter randomizes an existing list, giving a different order every invocation. -To get a random list from an existing list:: +To get a random list from an existing list: + +.. code-block:: yaml+jinja {{ ['a','b','c'] | shuffle }} # => ['c','a','b'] {{ ['a','b','c'] | shuffle }} # => ['b','c','a'] -You can initialize the shuffle generator from a seed to generate a random-but-idempotent order:: +You can initialize the shuffle generator from a seed to generate a random-but-idempotent order: + +.. code-block:: yaml+jinja {{ ['a','b','c'] | shuffle(seed=inventory_hostname) }} # => ['b','a','c'] @@ -909,34 +1081,46 @@ Managing list variables You can search for the minimum or maximum value in a list, or flatten a multi-level list. -To get the minimum value from list of numbers:: +To get the minimum value from list of numbers: + +.. code-block:: yaml+jinja {{ list1 | min }} .. versionadded:: 2.11 -To get the minimum value in a list of objects:: +To get the minimum value in a list of objects: + +.. code-block:: yaml+jinja {{ [{'val': 1}, {'val': 2}] | min(attribute='val') }} -To get the maximum value from a list of numbers:: +To get the maximum value from a list of numbers: + +.. code-block:: yaml+jinja {{ [3, 4, 2] | max }} .. versionadded:: 2.11 -To get the maximum value in a list of objects:: +To get the maximum value in a list of objects: + +.. code-block:: yaml+jinja {{ [{'val': 1}, {'val': 2}] | max(attribute='val') }} .. versionadded:: 2.5 -Flatten a list (same thing the `flatten` lookup does):: +Flatten a list (same thing the `flatten` lookup does): + +.. code-block:: yaml+jinja {{ [3, [4, 2] ] | flatten }} # => [3, 4, 2] -Flatten only the first level of a list (akin to the `items` lookup):: +Flatten only the first level of a list (akin to the `items` lookup): + +.. code-block:: yaml+jinja {{ [3, [4, [2]] ] | flatten(levels=1) }} # => [3, 4, [2]] @@ -944,7 +1128,9 @@ Flatten only the first level of a list (akin to the `items` lookup):: .. versionadded:: 2.11 -Preserve nulls in a list, by default flatten removes them. :: +Preserve nulls in a list, by default flatten removes them. : + +.. code-block:: yaml+jinja {{ [3, None, [4, [2]] ] | flatten(levels=1, skip_nulls=False) }} # => [3, None, 4, [2]] @@ -959,34 +1145,44 @@ You can select or combine items from sets or lists. .. versionadded:: 1.4 -To get a unique set from a list:: +To get a unique set from a list: + +.. code-block:: yaml+jinja # list1: [1, 2, 5, 1, 3, 4, 10] {{ list1 | unique }} # => [1, 2, 5, 3, 4, 10] -To get a union of two lists:: +To get a union of two lists: + +.. code-block:: yaml+jinja # list1: [1, 2, 5, 1, 3, 4, 10] # list2: [1, 2, 3, 4, 5, 11, 99] {{ list1 | union(list2) }} # => [1, 2, 5, 1, 3, 4, 10, 11, 99] -To get the intersection of 2 lists (unique list of all items in both):: +To get the intersection of 2 lists (unique list of all items in both): + +.. code-block:: yaml+jinja # list1: [1, 2, 5, 3, 4, 10] # list2: [1, 2, 3, 4, 5, 11, 99] {{ list1 | intersect(list2) }} # => [1, 2, 5, 3, 4] -To get the difference of 2 lists (items in 1 that don't exist in 2):: +To get the difference of 2 lists (items in 1 that don't exist in 2): + +.. code-block:: yaml+jinja # list1: [1, 2, 5, 1, 3, 4, 10] # list2: [1, 2, 3, 4, 5, 11, 99] {{ list1 | difference(list2) }} # => [10] -To get the symmetric difference of 2 lists (items exclusive to each list):: +To get the symmetric difference of 2 lists (items exclusive to each list): + +.. code-block:: yaml+jinja # list1: [1, 2, 5, 1, 3, 4, 10] # list2: [1, 2, 3, 4, 5, 11, 99] @@ -1002,22 +1198,30 @@ Calculating numbers (math) You can calculate logs, powers, and roots of numbers with Ansible filters. Jinja2 provides other mathematical functions like abs() and round(). -Get the logarithm (default is e):: +Get the logarithm (default is e): + +.. code-block:: yaml+jinja {{ 8 | log }} # => 2.0794415416798357 -Get the base 10 logarithm:: +Get the base 10 logarithm: + +.. code-block:: yaml+jinja {{ 8 | log(10) }} # => 0.9030899869919435 -Give me the power of 2! (or 5):: +Give me the power of 2! (or 5): + +.. code-block:: yaml+jinja {{ 8 | pow(5) }} # => 32768.0 -Square root, or the 5th:: +Square root, or the 5th: + +.. code-block:: yaml+jinja {{ 8 | root }} # => 2.8284271247461903 @@ -1042,17 +1246,23 @@ IP address filters .. versionadded:: 1.9 -To test if a string is a valid IP address:: +To test if a string is a valid IP address: + +.. code-block:: yaml+jinja {{ myvar | ansible.netcommon.ipaddr }} -You can also require a specific IP protocol version:: +You can also require a specific IP protocol version: + +.. code-block:: yaml+jinja {{ myvar | ansible.netcommon.ipv4 }} {{ myvar | ansible.netcommon.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:: +address. For example, to get the IP address itself from a CIDR, you can use: + +.. code-block:: yaml+jinja {{ '192.0.2.1/24' | ansible.netcommon.ipaddr('address') }} # => 192.168.0.1 @@ -1068,7 +1278,9 @@ Network CLI filters .. versionadded:: 2.4 To convert the output of a network device CLI command into structured JSON -output, use the ``parse_cli`` filter:: +output, use the ``parse_cli`` filter: + +.. code-block:: yaml+jinja {{ output | ansible.netcommon.parse_cli('path/to/spec') }} @@ -1152,7 +1364,9 @@ hashes. The network filters also support parsing the output of a CLI command using the TextFSM library. To parse the CLI output with TextFSM use the following -filter:: +filter: + +.. code-block:: yaml+jinja {{ output.stdout[0] | ansible.netcommon.parse_cli_textfsm('path/to/fsm') }} @@ -1164,7 +1378,9 @@ Network XML filters .. versionadded:: 2.5 To convert the XML output of a network device command into structured JSON -output, use the ``parse_xml`` filter:: +output, use the ``parse_xml`` filter: + +.. code-block:: yaml+jinja {{ output | ansible.netcommon.parse_xml('path/to/spec') }} @@ -1242,7 +1458,9 @@ For example, the ``vlan_id`` in the spec file is a user defined name and its val relative to the value of XPath in ``top`` Attributes of XML tags can be extracted using XPath expressions. The value of ``state`` in the spec -is an XPath expression used to get the attributes of the ``vlan`` tag in output XML.:: +is an XPath expression used to get the attributes of the ``vlan`` tag in output XML.: + +.. code-block:: none @@ -1272,16 +1490,22 @@ sorted string list of integers according to IOS-like VLAN list rules. This list * The first line of the list can be first_line_len characters long. * Subsequent list lines can be other_line_len characters. -To sort a VLAN list:: +To sort a VLAN list: + +.. code-block:: yaml+jinja {{ [3003, 3004, 3005, 100, 1688, 3002, 3999] | ansible.netcommon.vlan_parser }} -This example renders the following sorted list:: +This example renders the following sorted list: + +.. code-block:: text ['100,1688,3002-3005,3999'] -Another example Jinja template:: +Another example Jinja template: + +.. code-block:: yaml+jinja {% set parsed_vlans = vlans | ansible.netcommon.vlan_parser %} switchport trunk allowed vlan {{ parsed_vlans[0] }} @@ -1299,36 +1523,50 @@ Encrypting and checksumming strings and passwords .. versionadded:: 1.9 -To get the sha1 hash of a string:: +To get the sha1 hash of a string: + +.. code-block:: yaml+jinja {{ 'test1' | hash('sha1') }} # => "b444ac06613fc8d63795be9ad0beaf55011936ac" -To get the md5 hash of a string:: +To get the md5 hash of a string: + +.. code-block:: yaml+jinja {{ 'test1' | hash('md5') }} # => "5a105e8b9d40e1329780d62ea2265d8a" -Get a string checksum:: +Get a string checksum: + +.. code-block:: yaml+jinja {{ 'test2' | checksum }} # => "109f4b3c50d7b0df729d299bc6f8e9ef9066971f" -Other hashes (platform dependent):: +Other hashes (platform dependent): + +.. code-block:: yaml+jinja {{ 'test2' | hash('blowfish') }} -To get a sha512 password hash (random salt):: +To get a sha512 password hash (random salt): + +.. code-block:: yaml+jinja {{ 'passwordsaresecret' | password_hash('sha512') }} # => "$6$UIv3676O/ilZzWEE$ktEfFF19NQPF2zyxqxGkAceTnbEgpEKuGBtk6MlU4v2ZorWaVQUMyurgmHCh2Fr4wpmQ/Y.AlXMJkRnIS4RfH/" -To get a sha256 password hash with a specific salt:: +To get a sha256 password hash with a specific salt: + +.. code-block:: yaml+jinja {{ 'secretpassword' | password_hash('sha256', 'mysecretsalt') }} # => "$5$mysecretsalt$ReKNyDYjkKNqRVwouShhsEqZ3VOE8eoVO4exihOfvG4" -An idempotent method to generate unique hashes per system is to use a salt that is consistent between runs:: +An idempotent method to generate unique hashes per system is to use a salt that is consistent between runs: + +.. code-block:: yaml+jinja {{ 'secretpassword' | password_hash('sha512', 65534 | random(seed=inventory_hostname) | string) }} # => "$6$43927$lQxPKz2M2X.NWO.gK.t7phLwOKQMcSq72XxDZQ0XzYV6DlL1OD72h417aj16OnHTGxNzhftXJQBcjbunLEepM0" @@ -1337,14 +1575,16 @@ Hash types available depend on the control system running Ansible, 'hash' depend .. versionadded:: 2.7 -Some hash types allow providing a rounds parameter:: +Some hash types allow providing a rounds parameter: + +.. code-block:: yaml+jinja {{ 'secretpassword' | password_hash('sha256', 'mysecretsalt', rounds=10000) }} # => "$5$rounds=10000$mysecretsalt$Tkm80llAxD4YHll6AgNIztKn0vzAACsuuEfYeGP7tm7" Hash type 'blowfish' (BCrypt) provides the facility to specify the version of the BCrypt algorithm -.. code-block:: jinja +.. code-block:: yaml+jinja {{ 'secretpassword' | password_hash('blowfish', '1234567890123456789012', ident='2b') }} # => "$2b$12$123456789012345678901uuJ4qFdej6xnWjOQT.FStqfdoY8dYUPC" @@ -1356,7 +1596,9 @@ Hash type 'blowfish' (BCrypt) provides the facility to specify the version of th .. versionadded:: 2.12 -You can also use the Ansible :ref:`vault ` filter to encrypt data:: +You can also use the Ansible :ref:`vault ` filter to encrypt data: + +.. code-block:: yaml+jinja # simply encrypt my key in a vault vars: @@ -1369,7 +1611,9 @@ You can also use the Ansible :ref:`vault ` filter to encrypt data:: template_data: '{{ secretdata|vault(vaultsecret, salt=mysalt) }}' -And then decrypt it using the unvault filter:: +And then decrypt it using the unvault filter: + +.. code-block:: yaml+jinja # simply decrypt my key from a vault vars: @@ -1393,7 +1637,9 @@ Several filters work with text, including URLs, file names, and path names. Adding comments to files ------------------------ -The ``comment`` filter lets you create comments in a file from text in a template, with a variety of comment styles. By default Ansible uses ``#`` to start a comment line and adds a blank comment line above and below your comment text. For example the following:: +The ``comment`` filter lets you create comments in a file from text in a template, with a variety of comment styles. By default Ansible uses ``#`` to start a comment line and adds a blank comment line above and below your comment text. For example the following: + +.. code-block:: yaml+jinja {{ "Plain style (default)" | comment }} @@ -1406,14 +1652,18 @@ produces this output: # Ansible offers styles for comments in C (``//...``), C block -(``/*...*/``), Erlang (``%...``) and XML (````):: +(``/*...*/``), Erlang (``%...``) and XML (````): + +.. code-block:: yaml+jinja {{ "C style" | comment('c') }} {{ "C block style" | comment('cblock') }} {{ "Erlang style" | comment('erlang') }} {{ "XML style" | comment('xml') }} -You can define a custom comment character. This filter:: +You can define a custom comment character. This filter: + +.. code-block:: yaml+jinja {{ "My Special Case" | comment(decoration="! ") }} @@ -1425,7 +1675,9 @@ produces: ! My Special Case ! -You can fully customize the comment style:: +You can fully customize the comment style: + +.. code-block:: yaml+jinja {{ "Custom style" | comment('plain', prefix='#######\n#', postfix='#\n#######\n ###\n #') }} @@ -1445,7 +1697,7 @@ The filter can also be applied to any Ansible variable. For example to make the output of the ``ansible_managed`` variable more readable, we can change the definition in the ``ansible.cfg`` file to this: -.. code-block:: jinja +.. code-block:: ini [defaults] @@ -1455,7 +1707,9 @@ change the definition in the ``ansible.cfg`` file to this: user: {uid} host: {host} -and then use the variable with the `comment` filter:: +and then use the variable with the `comment` filter: + +.. code-block:: yaml+jinja {{ ansible_managed | comment }} @@ -1475,7 +1729,9 @@ which produces this output: URLEncode Variables ------------------- -The ``urlencode`` filter quotes data for use in a URL path or query using UTF-8:: +The ``urlencode`` filter quotes data for use in a URL path or query using UTF-8: + +.. code-block:: yaml+jinja {{ 'Trollhättan' | urlencode }} # => 'Trollh%C3%A4ttan' @@ -1485,7 +1741,9 @@ Splitting URLs .. versionadded:: 2.4 -The ``urlsplit`` filter extracts the fragment, hostname, netloc, password, path, port, query, scheme, and username from an URL. With no arguments, returns a dictionary of all the fields:: +The ``urlsplit`` filter extracts the fragment, hostname, netloc, password, path, port, query, scheme, and username from an URL. With no arguments, returns a dictionary of all the fields: + +.. code-block:: yaml+jinja {{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit('hostname') }} # => 'www.acme.com' @@ -1531,7 +1789,9 @@ The ``urlsplit`` filter extracts the fragment, hostname, netloc, password, path, Searching strings with regular expressions ------------------------------------------ -To search in a string or extract parts of a string with a regular expression, use the ``regex_search`` filter:: +To search in a string or extract parts of a string with a regular expression, use the ``regex_search`` filter: + +.. code-block:: yaml+jinja # Extracts the database name from a string {{ 'server1/database42' | regex_search('database[0-9]+') }} @@ -1549,12 +1809,16 @@ To search in a string or extract parts of a string with a regular expression, us {{ '21/42' | regex_search('(?P[0-9]+)/(?P[0-9]+)', '\\g', '\\g') }} # => ['21', '42'] -The ``regex_search`` filter returns an empty string if it cannot find a match:: +The ``regex_search`` filter returns an empty string if it cannot find a match: + +.. code-block:: yaml+jinja {{ 'ansible' | regex_search('foobar') }} # => '' -Note that due to historic behavior and custom re-implementation of some of the Jinja internals in Ansible there is an exception to the behavior. When used in a Jinja expression (for example in conjunction with operators, other filters, and so on) the return value differs, in those situations the return value is ``none``. See the two examples below:: +Note that due to historic behavior and custom re-implementation of some of the Jinja internals in Ansible there is an exception to the behavior. When used in a Jinja expression (for example in conjunction with operators, other filters, and so on) the return value differs, in those situations the return value is ``none``. See the two examples below: + +.. code-block:: yaml+jinja {{ 'ansible' | regex_search('foobar') == '' }} # => False @@ -1563,7 +1827,9 @@ Note that due to historic behavior and custom re-implementation of some of the J When ``jinja2_native`` setting is enabled, the ``regex_search`` filter always returns ``none`` if it cannot find a match. -To extract all occurrences of regex matches in a string, use the ``regex_findall`` filter:: +To extract all occurrences of regex matches in a string, use the ``regex_findall`` filter: + +.. code-block:: yaml+jinja # Returns a list of all IPv4 addresses in the string {{ 'Some DNS servers are 8.8.8.8 and 8.8.4.4' | regex_findall('\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b') }} @@ -1574,7 +1840,9 @@ To extract all occurrences of regex matches in a string, use the ``regex_findall # => ['CAR', 'tar', 'bar'] -To replace text in a string with regex, use the ``regex_replace`` filter:: +To replace text in a string with regex, use the ``regex_replace`` filter: + +.. code-block:: yaml+jinja # Convert "ansible" to "able" {{ 'ansible' | regex_replace('^a.*i(.*)$', 'a\\1') }} @@ -1597,7 +1865,9 @@ To replace text in a string with regex, use the ``regex_replace`` filter:: # => '#CAR\n#tar\nfoo\n#bar\n' .. note:: - If you want to match the whole string and you are using ``*`` make sure to always wraparound your regular expression with the start/end anchors. For example ``^(.*)$`` will always match only one result, while ``(.*)`` on some Python versions will match the whole string and an empty string at the end, which means it will make two replacements:: + If you want to match the whole string and you are using ``*`` make sure to always wraparound your regular expression with the start/end anchors. For example ``^(.*)$`` will always match only one result, while ``(.*)`` on some Python versions will match the whole string and an empty string at the end, which means it will make two replacements: + +.. code-block:: yaml+jinja # add "https://" prefix to each item in a list GOOD: @@ -1622,14 +1892,18 @@ To replace text in a string with regex, use the ``regex_replace`` filter:: .. versionadded:: 2.0 -To escape special characters within a standard Python regex, use the ``regex_escape`` filter (using the default ``re_type='python'`` option):: +To escape special characters within a standard Python regex, use the ``regex_escape`` filter (using the default ``re_type='python'`` option): + +.. code-block:: yaml+jinja # convert '^f.*o(.*)$' to '\^f\.\*o\(\.\*\)\$' {{ '^f.*o(.*)$' | regex_escape() }} .. versionadded:: 2.8 -To escape special characters within a POSIX basic regex, use the ``regex_escape`` filter with the ``re_type='posix_basic'`` option:: +To escape special characters within a POSIX basic regex, use the ``regex_escape`` filter with the ``re_type='posix_basic'`` option: + +.. code-block:: yaml+jinja # convert '^f.*o(.*)$' to '\^f\.\*o(\.\*)\$' {{ '^f.*o(.*)$' | regex_escape('posix_basic') }} @@ -1638,39 +1912,57 @@ To escape special characters within a POSIX basic regex, use the ``regex_escape` Managing file names and path names ---------------------------------- -To get the last name of a file path, like 'foo.txt' out of '/etc/asdf/foo.txt':: +To get the last name of a file path, like 'foo.txt' out of '/etc/asdf/foo.txt': + +.. code-block:: yaml+jinja {{ path | basename }} -To get the last name of a windows style file path (new in version 2.0):: +To get the last name of a windows style file path (new in version 2.0): + +.. code-block:: yaml+jinja {{ path | win_basename }} -To separate the windows drive letter from the rest of a file path (new in version 2.0):: +To separate the windows drive letter from the rest of a file path (new in version 2.0): + +.. code-block:: yaml+jinja {{ path | win_splitdrive }} -To get only the windows drive letter:: +To get only the windows drive letter: + +.. code-block:: yaml+jinja {{ path | win_splitdrive | first }} -To get the rest of the path without the drive letter:: +To get the rest of the path without the drive letter: + +.. code-block:: yaml+jinja {{ path | win_splitdrive | last }} -To get the directory from a path:: +To get the directory from a path: + +.. code-block:: yaml+jinja {{ path | dirname }} -To get the directory from a windows path (new version 2.0):: +To get the directory from a windows path (new version 2.0): + +.. code-block:: yaml+jinja {{ path | win_dirname }} -To expand a path containing a tilde (`~`) character (new in version 1.5):: +To expand a path containing a tilde (`~`) character (new in version 1.5): + +.. code-block:: yaml+jinja {{ path | expanduser }} -To expand a path containing environment variables:: +To expand a path containing environment variables: + +.. code-block:: yaml+jinja {{ path | expandvars }} @@ -1678,20 +1970,28 @@ To expand a path containing environment variables:: .. versionadded:: 2.6 -To get the real path of a link (new in version 1.8):: +To get the real path of a link (new in version 1.8): + +.. code-block:: yaml+jinja {{ path | realpath }} -To get the relative path of a link, from a start point (new in version 1.7):: +To get the relative path of a link, from a start point (new in version 1.7): + +.. code-block:: yaml+jinja {{ path | relpath('/etc') }} -To get the root and extension of a path or file name (new in version 2.0):: +To get the root and extension of a path or file name (new in version 2.0): + +.. code-block:: yaml+jinja # with path == 'nginx.conf' the return would be ('nginx', '.conf') {{ path | splitext }} -The ``splitext`` filter always returns a pair of strings. The individual components can be accessed by using the ``first`` and ``last`` filters:: +The ``splitext`` filter always returns a pair of strings. The individual components can be accessed by using the ``first`` and ``last`` filters: + +.. code-block:: yaml+jinja # with path == 'nginx.conf' the return would be 'nginx' {{ path | splitext | first }} @@ -1699,7 +1999,9 @@ The ``splitext`` filter always returns a pair of strings. The individual compone # with path == 'nginx.conf' the return would be '.conf' {{ path | splitext | last }} -To join one or more path components:: +To join one or more path components: + +.. code-block:: yaml+jinja {{ ('/etc', path, 'subdir', file) | path_join }} @@ -1708,27 +2010,37 @@ To join one or more path components:: Manipulating strings ==================== -To add quotes for shell usage:: +To add quotes for shell usage: + +.. code-block:: yaml+jinja - name: Run a shell command ansible.builtin.shell: echo {{ string_value | quote }} -To concatenate a list into a string:: +To concatenate a list into a string: + +.. code-block:: yaml+jinja {{ list | join(" ") }} -To split a string into a list:: +To split a string into a list: + +.. code-block:: yaml+jinja {{ csv_string | split(",") }} .. versionadded:: 2.11 -To work with Base64 encoded strings:: +To work with Base64 encoded strings: + +.. code-block:: yaml+jinja {{ encoded | b64decode }} {{ decoded | string | b64encode }} -As of version 2.6, you can define the type of encoding to use, the default is ``utf-8``:: +As of version 2.6, you can define the type of encoding to use, the default is ``utf-8``: + +.. code-block:: yaml+jinja {{ encoded | b64decode(encoding='utf-16-le') }} {{ decoded | string | b64encode(encoding='utf-16-le') }} @@ -1740,19 +2052,25 @@ As of version 2.6, you can define the type of encoding to use, the default is `` Managing UUIDs ============== -To create a namespaced UUIDv5:: +To create a namespaced UUIDv5: + +.. code-block:: yaml+jinja {{ string | to_uuid(namespace='11111111-2222-3333-4444-555555555555') }} .. versionadded:: 2.10 -To create a namespaced UUIDv5 using the default Ansible namespace '361E6D51-FAEC-444A-9079-341386DA8E2E':: +To create a namespaced UUIDv5 using the default Ansible namespace '361E6D51-FAEC-444A-9079-341386DA8E2E': + +.. code-block:: yaml+jinja {{ string | to_uuid }} .. versionadded:: 1.9 -To make use of one attribute from each item in a list of complex variables, use the :func:`Jinja2 map filter `:: +To make use of one attribute from each item in a list of complex variables, use the :func:`Jinja2 map filter `: + +.. code-block:: yaml+jinja # get a comma-separated list of the mount points (for example, "/,/mnt/stuff") on a host {{ ansible_mounts | map(attribute='mount') | join(',') }} @@ -1760,7 +2078,9 @@ To make use of one attribute from each item in a list of complex variables, use Handling dates and times ======================== -To get a date object from a string use the `to_datetime` filter:: +To get a date object from a string use the `to_datetime` filter: + +.. code-block:: yaml+jinja # Get total amount of seconds between two dates. Default date format is %Y-%m-%d %H:%M:%S but you can pass your own format {{ (("2016-08-14 20:00:12" | to_datetime) - ("2015-12-25" | to_datetime('%Y-%m-%d'))).total_seconds() }} @@ -1776,7 +2096,9 @@ To get a date object from a string use the `to_datetime` filter:: .. versionadded:: 2.4 -To format a date using a string (like with the shell date command), use the "strftime" filter:: +To format a date using a string (like with the shell date command), use the "strftime" filter: + +.. code-block:: yaml+jinja # Display year-month-day {{ '%Y-%m-%d' | strftime }} @@ -1804,11 +2126,15 @@ Getting Kubernetes resource names These filters have migrated to the `kubernetes.core `_ collection. Follow the installation instructions to install that collection. Use the "k8s_config_resource_name" filter to obtain the name of a Kubernetes ConfigMap or Secret, -including its hash:: +including its hash: + +.. code-block:: yaml+jinja {{ configmap_resource_definition | kubernetes.core.k8s_config_resource_name }} -This can then be used to reference hashes in Pod specifications:: +This can then be used to reference hashes in Pod specifications: + +.. code-block:: yaml+jinja my_secret: kind: Secret