[2.10] Doc fixes backporting 71697, 71718, 71717 (#71768)

* Docsite: misc fixes (#71697)

(cherry picked from commit a80131a283)

* Docsite: improve playbooks_loops.rst (#71718)

(cherry picked from commit 13ab9f5932)

* Docsite: fix a typo in user_guide/index.rst (#71717)
This commit is contained in:
Andrew Klychkov 2020-09-21 18:59:05 +03:00 committed by GitHub
parent b6637c0afc
commit ea9a223ab6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 64 deletions

View file

@ -17,14 +17,14 @@ Especially if you want to contribute your module(s) to an existing Ansible Colle
* Each module should have a concise and well-defined functionality. Basically, follow the UNIX philosophy of doing one thing well. * Each module should have a concise and well-defined functionality. Basically, follow the UNIX philosophy of doing one thing well.
* Do not add ``get``, ``list`` or ``info`` state options to an existing module - create a new ``_info`` or ``_facts`` module. * Do not add ``get``, ``list`` or ``info`` state options to an existing module - create a new ``_info`` or ``_facts`` module.
* Modules should not require that a user know all the underlying options of an API/tool to be used. For instance, if the legal values for a required module parameter cannot be documented, the module does not belong in Ansible Core. * Modules should not require that a user know all the underlying options of an API/tool to be used. For instance, if the legal values for a required module option cannot be documented, the module does not belong in Ansible Core.
* Modules should encompass much of the logic for interacting with a resource. A lightweight wrapper around a complex API forces users to offload too much logic into their playbooks. If you want to connect Ansible to a complex API, :ref:`create multiple modules <developing_modules_in_groups>` that interact with smaller individual pieces of the API. * Modules should encompass much of the logic for interacting with a resource. A lightweight wrapper around a complex API forces users to offload too much logic into their playbooks. If you want to connect Ansible to a complex API, :ref:`create multiple modules <developing_modules_in_groups>` that interact with smaller individual pieces of the API.
* Avoid creating a module that does the work of other modules; this leads to code duplication and divergence, and makes things less uniform, unpredictable and harder to maintain. Modules should be the building blocks. If you are asking 'how can I have a module execute other modules' ... you want to write a role. * Avoid creating a module that does the work of other modules; this leads to code duplication and divergence, and makes things less uniform, unpredictable and harder to maintain. Modules should be the building blocks. If you are asking 'how can I have a module execute other modules' ... you want to write a role.
Designing module interfaces Designing module interfaces
=========================== ===========================
* If your module is addressing an object, the parameter for that object should be called ``name`` whenever possible, or accept ``name`` as an alias. * If your module is addressing an object, the option for that object should be called ``name`` whenever possible, or accept ``name`` as an alias.
* Modules accepting boolean status should accept ``yes``, ``no``, ``true``, ``false``, or anything else a user may likely throw at them. The AnsibleModule common code supports this with ``type='bool'``. * Modules accepting boolean status should accept ``yes``, ``no``, ``true``, ``false``, or anything else a user may likely throw at them. The AnsibleModule common code supports this with ``type='bool'``.
* Avoid ``action``/``command``, they are imperative and not declarative, there are other ways to express the same thing. * Avoid ``action``/``command``, they are imperative and not declarative, there are other ways to express the same thing.
@ -34,7 +34,7 @@ General guidelines & tips
* Each module should be self-contained in one file, so it can be auto-transferred by ``ansible-base``. * Each module should be self-contained in one file, so it can be auto-transferred by ``ansible-base``.
* Module name MUST use underscores instead of hyphens or spaces as a word separator. Using hyphens and spaces will prevent ``ansible-base`` from importing your module. * Module name MUST use underscores instead of hyphens or spaces as a word separator. Using hyphens and spaces will prevent ``ansible-base`` from importing your module.
* Always use the ``hacking/test-module.py`` script when developing modules - it will warn you about common pitfalls. * Always use the ``hacking/test-module.py`` script when developing modules - it will warn you about common pitfalls.
* If you have a local module that returns facts specific to your installations, a good name for this module is ``site_facts``. * If you have a local module that returns information specific to your installations, a good name for this module is ``site_info``.
* Eliminate or minimize dependencies. If your module has dependencies, document them at the top of the module file and raise JSON error messages when dependency import fails. * Eliminate or minimize dependencies. If your module has dependencies, document them at the top of the module file and raise JSON error messages when dependency import fails.
* Don't write to files directly; use a temporary file and then use the ``atomic_move`` function from ``ansible.module_utils.basic`` to move the updated temporary file into place. This prevents data corruption and ensures that the correct context for the file is kept. * Don't write to files directly; use a temporary file and then use the ``atomic_move`` function from ``ansible.module_utils.basic`` to move the updated temporary file into place. This prevents data corruption and ensures that the correct context for the file is kept.
* Avoid creating caches. Ansible is designed without a central server or authority, so you cannot guarantee it will not run with different permissions, options or locations. If you need a central authority, have it on top of Ansible (for example, using bastion/cm/ci server or tower); do not try to build it into modules. * Avoid creating caches. Ansible is designed without a central server or authority, so you cannot guarantee it will not run with different permissions, options or locations. If you need a central authority, have it on top of Ansible (for example, using bastion/cm/ci server or tower); do not try to build it into modules.
@ -136,7 +136,7 @@ Modules must output valid JSON only. Follow these guidelines for creating correc
* Make returns reusable--most of the time you don't want to read it, but you do want to process it and re-purpose it. * Make returns reusable--most of the time you don't want to read it, but you do want to process it and re-purpose it.
* Return diff if in diff mode. This is not required for all modules, as it won't make sense for certain ones, but please include it when applicable. * Return diff if in diff mode. This is not required for all modules, as it won't make sense for certain ones, but please include it when applicable.
* Enable your return values to be serialized as JSON with Python's standard `JSON encoder and decoder <https://docs.python.org/3/library/json.html>`_ library. Basic python types (strings, int, dicts, lists, and so on) are serializable. * Enable your return values to be serialized as JSON with Python's standard `JSON encoder and decoder <https://docs.python.org/3/library/json.html>`_ library. Basic python types (strings, int, dicts, lists, and so on) are serializable.
* Do not return an object via exit_json(). Instead, convert the fields you need from the object into the fields of a dictionary and return the dictionary. * Do not return an object using exit_json(). Instead, convert the fields you need from the object into the fields of a dictionary and return the dictionary.
* Results from many hosts will be aggregated at once, so your module should return only relevant output. Returning the entire contents of a log file is generally bad form. * Results from many hosts will be aggregated at once, so your module should return only relevant output. Returning the entire contents of a log file is generally bad form.
If a module returns stderr or otherwise fails to produce valid JSON, the actual output will still be shown in Ansible, but the command will not succeed. If a module returns stderr or otherwise fails to produce valid JSON, the actual output will still be shown in Ansible, but the command will not succeed.
@ -149,12 +149,12 @@ Following Ansible conventions
Ansible conventions offer a predictable user interface across all modules, playbooks, and roles. To follow Ansible conventions in your module development: Ansible conventions offer a predictable user interface across all modules, playbooks, and roles. To follow Ansible conventions in your module development:
* Use consistent names across modules (yes, we have many legacy deviations - don't make the problem worse!). * Use consistent names across modules (yes, we have many legacy deviations - don't make the problem worse!).
* Use consistent parameters (arguments) within your module(s). * Use consistent options (arguments) within your module(s).
* Do not use 'message' or 'syslog_facility' as a parameter name, as this is used internally by Ansible. * Do not use 'message' or 'syslog_facility' as an option name, because this is used internally by Ansible.
* Normalize parameters with other modules - if Ansible and the API your module connects to use different names for the same parameter, add aliases to your parameters so the user can choose which names to use in tasks and playbooks. * Normalize options with other modules - if Ansible and the API your module connects to use different names for the same option, add aliases to your options so the user can choose which names to use in tasks and playbooks.
* Return facts from ``*_facts`` modules in the ``ansible_facts`` field of the :ref:`result dictionary<common_return_values>` so other modules can access them. * Return facts from ``*_facts`` modules in the ``ansible_facts`` field of the :ref:`result dictionary<common_return_values>` so other modules can access them.
* Implement ``check_mode`` in all ``*_info`` and ``*_facts`` modules. Playbooks which conditionalize based on fact information will only conditionalize correctly in ``check_mode`` if the facts are returned in ``check_mode``. Usually you can add ``supports_check_mode=True`` when instantiating ``AnsibleModule``. * Implement ``check_mode`` in all ``*_info`` and ``*_facts`` modules. Playbooks which conditionalize based on fact information will only conditionalize correctly in ``check_mode`` if the facts are returned in ``check_mode``. Usually you can add ``supports_check_mode=True`` when instantiating ``AnsibleModule``.
* Use module-specific environment variables. For example, if you use the helpers in ``module_utils.api`` for basic authentication with ``module_utils.urls.fetch_url()`` and you fall back on environment variables for default values, use a module-specific environment variable like :code:`API_<MODULENAME>_USERNAME` to avoid conflict between modules. * Use module-specific environment variables. For example, if you use the helpers in ``module_utils.api`` for basic authentication with ``module_utils.urls.fetch_url()`` and you fall back on environment variables for default values, use a module-specific environment variable like :code:`API_<MODULENAME>_USERNAME` to avoid conflicts between modules.
* Keep module options simple and focused - if you're loading a lot of choices/states on an existing option, consider adding a new, simple option instead. * Keep module options simple and focused - if you're loading a lot of choices/states on an existing option, consider adding a new, simple option instead.
* Keep options small when possible. Passing a large data structure to an option might save us a few tasks, but it adds a complex requirement that we cannot easily validate before passing on to the module. * Keep options small when possible. Passing a large data structure to an option might save us a few tasks, but it adds a complex requirement that we cannot easily validate before passing on to the module.
* If you want to pass complex data to an option, write an expert module that allows this, along with several smaller modules that provide a more 'atomic' operation against the underlying APIs and services. Complex operations require complex data. Let the user choose whether to reflect that complexity in tasks and plays or in vars files. * If you want to pass complex data to an option, write an expert module that allows this, along with several smaller modules that provide a more 'atomic' operation against the underlying APIs and services. Complex operations require complex data. Let the user choose whether to reflect that complexity in tasks and plays or in vars files.

View file

@ -29,7 +29,7 @@ Writing tasks, plays, and playbooks
* Running tasks only when certain conditions apply with :ref:`conditionals <playbooks_conditionals>` and evaluating conditions with :ref:`tests <playbooks_tests>` * Running tasks only when certain conditions apply with :ref:`conditionals <playbooks_conditionals>` and evaluating conditions with :ref:`tests <playbooks_tests>`
* Grouping a set of tasks together with :ref:`blocks <playbooks_blocks>` * Grouping a set of tasks together with :ref:`blocks <playbooks_blocks>`
* Running tasks only when something has changed with :ref:`handlers <handlers>` * Running tasks only when something has changed with :ref:`handlers <handlers>`
* Changing the way Ansible :ref:`handles failures <playbooks_error_handling>`) * Changing the way Ansible :ref:`handles failures <playbooks_error_handling>`
* Setting remote :ref:`environment values <playbooks_environment>` * Setting remote :ref:`environment values <playbooks_environment>`
* I want to leverage the power of re-usable Ansible artifacts. How do I create re-usable :ref:`files <playbooks_reuse>` and :ref:`roles <playbooks_reuse_roles>`? * I want to leverage the power of re-usable Ansible artifacts. How do I create re-usable :ref:`files <playbooks_reuse>` and :ref:`roles <playbooks_reuse_roles>`?

View file

@ -55,8 +55,8 @@ Iterating over a simple list
Repeated tasks can be written as standard loops over a simple list of strings. You can define the list directly in the task:: Repeated tasks can be written as standard loops over a simple list of strings. You can define the list directly in the task::
- name: add several users - name: Add several users
user: ansible.builtin.user:
name: "{{ item }}" name: "{{ item }}"
state: present state: present
groups: "wheel" groups: "wheel"
@ -70,27 +70,27 @@ You can define the list in a variables file, or in the 'vars' section of your pl
Either of these examples would be the equivalent of:: Either of these examples would be the equivalent of::
- name: add user testuser1 - name: Add user testuser1
user: ansible.builtin.user:
name: "testuser1" name: "testuser1"
state: present state: present
groups: "wheel" groups: "wheel"
- name: add user testuser2 - name: Add user testuser2
user: ansible.builtin.user:
name: "testuser2" name: "testuser2"
state: present state: present
groups: "wheel" groups: "wheel"
You can pass a list directly to a parameter for some plugins. Most of the packaging modules, like :ref:`yum <yum_module>` and :ref:`apt <apt_module>`, have this capability. When available, passing the list to a parameter is better than looping over the task. For example:: You can pass a list directly to a parameter for some plugins. Most of the packaging modules, like :ref:`yum <yum_module>` and :ref:`apt <apt_module>`, have this capability. When available, passing the list to a parameter is better than looping over the task. For example::
- name: optimal yum - name: Optimal yum
yum: ansible.builtin.yum:
name: "{{ list_of_packages }}" name: "{{ list_of_packages }}"
state: present state: present
- name: non-optimal yum, slower and may cause issues with interdependencies - name: Non-optimal yum, slower and may cause issues with interdependencies
yum: ansible.builtin.yum:
name: "{{ item }}" name: "{{ item }}"
state: present state: present
loop: "{{ list_of_packages }}" loop: "{{ list_of_packages }}"
@ -102,8 +102,8 @@ Iterating over a list of hashes
If you have a list of hashes, you can reference subkeys in a loop. For example:: If you have a list of hashes, you can reference subkeys in a loop. For example::
- name: add several users - name: Add several users
user: ansible.builtin.user:
name: "{{ item.name }}" name: "{{ item.name }}"
state: present state: present
groups: "{{ item.groups }}" groups: "{{ item.groups }}"
@ -122,7 +122,7 @@ To loop over a dict, use the :ref:`dict2items <dict_filter>`:
.. code-block:: yaml .. code-block:: yaml
- name: Using dict2items - name: Using dict2items
debug: ansible.builtin.debug:
msg: "{{ item.key }} - {{ item.value }}" msg: "{{ item.key }} - {{ item.value }}"
loop: "{{ tag_data | dict2items }}" loop: "{{ tag_data | dict2items }}"
vars: vars:
@ -137,7 +137,8 @@ Registering variables with a loop
You can register the output of a loop as a variable. For example:: You can register the output of a loop as a variable. For example::
- shell: "echo {{ item }}" - name: Register loop output as a variable
ansible.builtin.shell: "echo {{ item }}"
loop: loop:
- "one" - "one"
- "two" - "two"
@ -185,14 +186,15 @@ When you use ``register`` with a loop, the data structure placed in the variable
Subsequent loops over the registered variable to inspect the results may look like:: Subsequent loops over the registered variable to inspect the results may look like::
- name: Fail if return code is not 0 - name: Fail if return code is not 0
fail: ansible.builtin.fail:
msg: "The command ({{ item.cmd }}) did not have a 0 return code" msg: "The command ({{ item.cmd }}) did not have a 0 return code"
when: item.rc != 0 when: item.rc != 0
loop: "{{ echo.results }}" loop: "{{ echo.results }}"
During iteration, the result of the current item will be placed in the variable:: During iteration, the result of the current item will be placed in the variable::
- shell: echo "{{ item }}" - name: Place the result of the current item in the variable
ansible.builtin.shell: echo "{{ item }}"
loop: loop:
- one - one
- two - two
@ -209,8 +211,8 @@ Iterating over nested lists
You can use Jinja2 expressions to iterate over complex lists. For example, a loop can combine nested lists:: You can use Jinja2 expressions to iterate over complex lists. For example, a loop can combine nested lists::
- name: give users access to multiple databases - name: Give users access to multiple databases
mysql_user: community.mysql.mysql_user:
name: "{{ item[0] }}" name: "{{ item[0] }}"
priv: "{{ item[1] }}.*:ALL" priv: "{{ item[1] }}.*:ALL"
append_privs: yes append_privs: yes
@ -227,7 +229,8 @@ Retrying a task until a condition is met
You can use the ``until`` keyword to retry a task until a certain condition is met. Here's an example:: You can use the ``until`` keyword to retry a task until a certain condition is met. Here's an example::
- shell: /usr/bin/foo - name: Retry a task until a certain condition is met
ansible.builtin.shell: /usr/bin/foo
register: result register: result
until: result.stdout.find("all systems go") != -1 until: result.stdout.find("all systems go") != -1
retries: 5 retries: 5
@ -246,25 +249,25 @@ Looping over inventory
To loop over your inventory, or just a subset of it, you can use a regular ``loop`` with the ``ansible_play_batch`` or ``groups`` variables:: To loop over your inventory, or just a subset of it, you can use a regular ``loop`` with the ``ansible_play_batch`` or ``groups`` variables::
# show all the hosts in the inventory - name: Show all the hosts in the inventory
- debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
loop: "{{ groups['all'] }}" loop: "{{ groups['all'] }}"
# show all the hosts in the current play - name: Show all the hosts in the current play
- debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
loop: "{{ ansible_play_batch }}" loop: "{{ ansible_play_batch }}"
There is also a specific lookup plugin ``inventory_hostnames`` that can be used like this:: There is also a specific lookup plugin ``inventory_hostnames`` that can be used like this::
# show all the hosts in the inventory - name: Show all the hosts in the inventory
- debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
loop: "{{ query('inventory_hostnames', 'all') }}" loop: "{{ query('inventory_hostnames', 'all') }}"
# show all the hosts matching the pattern, ie all but the group www - name: Show all the hosts matching the pattern, ie all but the group www
- debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
loop: "{{ query('inventory_hostnames', 'all:!www') }}" loop: "{{ query('inventory_hostnames', 'all:!www') }}"
@ -300,7 +303,7 @@ Limiting loop output with ``label``
When looping over complex data structures, the console output of your task can be enormous. To limit the displayed output, use the ``label`` directive with ``loop_control``:: When looping over complex data structures, the console output of your task can be enormous. To limit the displayed output, use the ``label`` directive with ``loop_control``::
- name: create servers - name: Create servers
digital_ocean: digital_ocean:
name: "{{ item.name }}" name: "{{ item.name }}"
state: present state: present
@ -326,8 +329,8 @@ Pausing within a loop
To control the time (in seconds) between the execution of each item in a task loop, use the ``pause`` directive with ``loop_control``:: To control the time (in seconds) between the execution of each item in a task loop, use the ``pause`` directive with ``loop_control``::
# main.yml # main.yml
- name: create servers, pause 3s before creating next - name: Create servers, pause 3s before creating next
digital_ocean: community.digitalocean.digital_ocean:
name: "{{ item }}" name: "{{ item }}"
state: present state: present
loop: loop:
@ -342,8 +345,8 @@ Tracking progress through a loop with ``index_var``
To keep track of where you are in a loop, use the ``index_var`` directive with ``loop_control``. This directive specifies a variable name to contain the current loop index:: To keep track of where you are in a loop, use the ``index_var`` directive with ``loop_control``. This directive specifies a variable name to contain the current loop index::
- name: count our fruit - name: Count our fruit
debug: ansible.builtin.debug:
msg: "{{ item }} with index {{ my_idx }}" msg: "{{ item }} with index {{ my_idx }}"
loop: loop:
- apple - apple
@ -371,7 +374,8 @@ You can specify the name of the variable for each loop using ``loop_var`` with `
loop_var: outer_item loop_var: outer_item
# inner.yml # inner.yml
- debug: - name: Print outer and inner items
ansible.builtin.debug:
msg: "outer item={{ outer_item }} inner item={{ item }}" msg: "outer item={{ outer_item }} inner item={{ item }}"
loop: loop:
- a - a

View file

@ -10,14 +10,14 @@ with_list
.. code-block:: yaml+jinja .. code-block:: yaml+jinja
- name: with_list - name: with_list
debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
with_list: with_list:
- one - one
- two - two
- name: with_list -> loop - name: with_list -> loop
debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
loop: loop:
- one - one
@ -31,12 +31,12 @@ with_items
.. code-block:: yaml+jinja .. code-block:: yaml+jinja
- name: with_items - name: with_items
debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
with_items: "{{ items }}" with_items: "{{ items }}"
- name: with_items -> loop - name: with_items -> loop
debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
loop: "{{ items|flatten(levels=1) }}" loop: "{{ items|flatten(levels=1) }}"
@ -48,12 +48,12 @@ with_indexed_items
.. code-block:: yaml+jinja .. code-block:: yaml+jinja
- name: with_indexed_items - name: with_indexed_items
debug: ansible.builtin.debug:
msg: "{{ item.0 }} - {{ item.1 }}" msg: "{{ item.0 }} - {{ item.1 }}"
with_indexed_items: "{{ items }}" with_indexed_items: "{{ items }}"
- name: with_indexed_items -> loop - name: with_indexed_items -> loop
debug: ansible.builtin.debug:
msg: "{{ index }} - {{ item }}" msg: "{{ index }} - {{ item }}"
loop: "{{ items|flatten(levels=1) }}" loop: "{{ items|flatten(levels=1) }}"
loop_control: loop_control:
@ -67,12 +67,12 @@ with_flattened
.. code-block:: yaml+jinja .. code-block:: yaml+jinja
- name: with_flattened - name: with_flattened
debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
with_flattened: "{{ items }}" with_flattened: "{{ items }}"
- name: with_flattened -> loop - name: with_flattened -> loop
debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
loop: "{{ items|flatten }}" loop: "{{ items|flatten }}"
@ -84,14 +84,14 @@ with_together
.. code-block:: yaml+jinja .. code-block:: yaml+jinja
- name: with_together - name: with_together
debug: ansible.builtin.debug:
msg: "{{ item.0 }} - {{ item.1 }}" msg: "{{ item.0 }} - {{ item.1 }}"
with_together: with_together:
- "{{ list_one }}" - "{{ list_one }}"
- "{{ list_two }}" - "{{ list_two }}"
- name: with_together -> loop - name: with_together -> loop
debug: ansible.builtin.debug:
msg: "{{ item.0 }} - {{ item.1 }}" msg: "{{ item.0 }} - {{ item.1 }}"
loop: "{{ list_one|zip(list_two)|list }}" loop: "{{ list_one|zip(list_two)|list }}"
@ -100,7 +100,7 @@ Another example with complex data
.. code-block:: yaml+jinja .. code-block:: yaml+jinja
- name: with_together -> loop - name: with_together -> loop
debug: ansible.builtin.debug:
msg: "{{ item.0 }} - {{ item.1 }} - {{ item.2 }}" msg: "{{ item.0 }} - {{ item.1 }} - {{ item.2 }}"
loop: "{{ data[0]|zip(*data[1:])|list }}" loop: "{{ data[0]|zip(*data[1:])|list }}"
vars: vars:
@ -117,17 +117,17 @@ with_dict
.. code-block:: yaml+jinja .. code-block:: yaml+jinja
- name: with_dict - name: with_dict
debug: ansible.builtin.debug:
msg: "{{ item.key }} - {{ item.value }}" msg: "{{ item.key }} - {{ item.value }}"
with_dict: "{{ dictionary }}" with_dict: "{{ dictionary }}"
- name: with_dict -> loop (option 1) - name: with_dict -> loop (option 1)
debug: ansible.builtin.debug:
msg: "{{ item.key }} - {{ item.value }}" msg: "{{ item.key }} - {{ item.value }}"
loop: "{{ dictionary|dict2items }}" loop: "{{ dictionary|dict2items }}"
- name: with_dict -> loop (option 2) - name: with_dict -> loop (option 2)
debug: ansible.builtin.debug:
msg: "{{ item.0 }} - {{ item.1 }}" msg: "{{ item.0 }} - {{ item.1 }}"
loop: "{{ dictionary|dictsort }}" loop: "{{ dictionary|dictsort }}"
@ -139,12 +139,12 @@ with_sequence
.. code-block:: yaml+jinja .. code-block:: yaml+jinja
- name: with_sequence - name: with_sequence
debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
with_sequence: start=0 end=4 stride=2 format=testuser%02x with_sequence: start=0 end=4 stride=2 format=testuser%02x
- name: with_sequence -> loop - name: with_sequence -> loop
debug: ansible.builtin.debug:
msg: "{{ 'testuser%02x' | format(item) }}" msg: "{{ 'testuser%02x' | format(item) }}"
# range is exclusive of the end point # range is exclusive of the end point
loop: "{{ range(0, 4 + 1, 2)|list }}" loop: "{{ range(0, 4 + 1, 2)|list }}"
@ -157,14 +157,14 @@ with_subelements
.. code-block:: yaml+jinja .. code-block:: yaml+jinja
- name: with_subelements - name: with_subelements
debug: ansible.builtin.debug:
msg: "{{ item.0.name }} - {{ item.1 }}" msg: "{{ item.0.name }} - {{ item.1 }}"
with_subelements: with_subelements:
- "{{ users }}" - "{{ users }}"
- mysql.hosts - mysql.hosts
- name: with_subelements -> loop - name: with_subelements -> loop
debug: ansible.builtin.debug:
msg: "{{ item.0.name }} - {{ item.1 }}" msg: "{{ item.0.name }} - {{ item.1 }}"
loop: "{{ users|subelements('mysql.hosts') }}" loop: "{{ users|subelements('mysql.hosts') }}"
@ -176,14 +176,14 @@ with_nested/with_cartesian
.. code-block:: yaml+jinja .. code-block:: yaml+jinja
- name: with_nested - name: with_nested
debug: ansible.builtin.debug:
msg: "{{ item.0 }} - {{ item.1 }}" msg: "{{ item.0 }} - {{ item.1 }}"
with_nested: with_nested:
- "{{ list_one }}" - "{{ list_one }}"
- "{{ list_two }}" - "{{ list_two }}"
- name: with_nested -> loop - name: with_nested -> loop
debug: ansible.builtin.debug:
msg: "{{ item.0 }} - {{ item.1 }}" msg: "{{ item.0 }} - {{ item.1 }}"
loop: "{{ list_one|product(list_two)|list }}" loop: "{{ list_one|product(list_two)|list }}"
@ -195,11 +195,11 @@ with_random_choice
.. code-block:: yaml+jinja .. code-block:: yaml+jinja
- name: with_random_choice - name: with_random_choice
debug: ansible.builtin.debug:
msg: "{{ item }}" msg: "{{ item }}"
with_random_choice: "{{ my_list }}" with_random_choice: "{{ my_list }}"
- name: with_random_choice -> loop (No loop is needed here) - name: with_random_choice -> loop (No loop is needed here)
debug: ansible.builtin.debug:
msg: "{{ my_list|random }}" msg: "{{ my_list|random }}"
tags: random tags: random