2019-04-05 23:49:20 +02:00
.. _playbooks_blocks:
2019-12-12 19:35:17 +01:00
***** *
2015-07-17 19:53:13 +02:00
Blocks
2019-12-12 19:35:17 +01:00
***** *
2015-07-17 19:53:13 +02:00
2019-12-12 19:35:17 +01:00
Blocks create logical groups of tasks. Blocks also offer ways to handle task errors, similar to exception handling in many programming languages.
2015-07-17 19:53:13 +02:00
2019-12-12 19:35:17 +01:00
.. contents ::
:local:
Grouping tasks with blocks
==========================
All tasks in a block inherit directives applied at the block level. Most of what you can apply to a single task (with the exception of loops) can be applied at the block level, so blocks make it much easier to set data or directives common to the tasks. The directive does not affect the block itself, it is only inherited by the tasks enclosed by a block. For example, a `when` statement is applied to the tasks within a block, not to the block itself.
2015-07-17 19:53:13 +02:00
2015-08-05 01:09:06 +02:00
.. code-block :: YAML
2017-08-02 22:36:17 +02:00
:emphasize-lines: 3
2018-10-18 22:24:52 +02:00
:caption: Block example with named tasks inside the block
2015-07-17 19:53:13 +02:00
2018-02-02 19:20:03 +01:00
tasks:
2018-10-18 22:24:52 +02:00
- name: Install, configure, and start Apache
2018-02-02 19:20:03 +01:00
block:
2020-09-17 16:20:22 +02:00
- name: Install httpd and memcached
ansible.builtin.yum:
2019-09-03 17:09:47 +02:00
name:
- httpd
- memcached
state: present
2020-09-17 16:20:22 +02:00
- name: Apply the foo config template
ansible.builtin.template:
2019-09-03 17:09:47 +02:00
src: templates/src.j2
dest: /etc/foo.conf
2020-09-17 16:20:22 +02:00
- name: Start service bar and enable it
ansible.builtin.service:
2019-09-03 17:09:47 +02:00
name: bar
state: started
enabled: True
2018-09-06 17:26:58 +02:00
when: ansible_facts['distribution'] == 'CentOS'
2018-02-02 19:20:03 +01:00
become: true
become_user: root
2019-04-05 23:49:20 +02:00
ignore_errors: yes
2015-08-05 01:09:06 +02:00
2019-12-12 19:35:17 +01:00
In the example above, the 'when' condition will be evaluated before Ansible runs each of the three tasks in the block. All three tasks also inherit the privilege escalation directives, running as the root user. Finally, `` ignore_errors: yes `` ensures that Ansible continues to execute the playbook even if some of the tasks fail.
2015-07-17 19:53:13 +02:00
2020-07-20 16:48:53 +02:00
Names for blocks have been available since Ansible 2.3. We recommend using names in all tasks, within blocks or elsewhere, for better visibility into the tasks being executed when you run the playbook.
2015-07-17 19:53:13 +02:00
.. _block_error_handling:
2019-12-12 19:35:17 +01:00
Handling errors with blocks
===========================
2015-07-17 19:53:13 +02:00
2019-12-12 19:35:17 +01:00
You can control how Ansible responds to task errors using blocks with `` rescue `` and `` always `` sections.
Rescue blocks specify tasks to run when an earlier task in a block fails. This approach is similar to exception handling in many programming languages. Ansible only runs rescue blocks after a task returns a 'failed' state. Bad task definitions and unreachable hosts will not trigger the rescue block.
2015-08-05 01:09:06 +02:00
2018-08-28 19:40:12 +02:00
.. _block_rescue:
2015-08-05 01:09:06 +02:00
.. code-block :: YAML
2021-01-14 20:40:31 +01:00
:emphasize-lines: 3,14
2015-08-05 01:09:06 +02:00
:caption: Block error handling example
2015-07-17 19:53:13 +02:00
2018-02-02 19:20:03 +01:00
tasks:
2018-08-28 19:40:12 +02:00
- name: Handle the error
2018-02-02 19:20:03 +01:00
block:
2020-09-17 16:20:22 +02:00
- name: Print a message
ansible.builtin.debug:
2018-02-02 19:20:03 +01:00
msg: 'I execute normally'
2020-09-17 16:20:22 +02:00
- name: Force a failure
ansible.builtin.command: /bin/false
- name: Never print this
ansible.builtin.debug:
2018-08-28 19:40:12 +02:00
msg: 'I never execute, due to the above task failing, :-('
2018-02-02 19:20:03 +01:00
rescue:
2020-09-17 16:20:22 +02:00
- name: Print when errors
ansible.builtin.debug:
2018-08-28 19:40:12 +02:00
msg: 'I caught an error, can do stuff here to fix it, :-)'
2019-12-12 19:35:17 +01:00
You can also add an `` always `` section to a block. Tasks in the `` always `` section run no matter what the task status of the previous block is.
2018-08-28 19:40:12 +02:00
.. _block_always:
.. code-block :: YAML
2021-01-14 20:40:31 +01:00
:emphasize-lines: 2,13
2018-08-28 19:40:12 +02:00
:caption: Block with always section
- name: Always do X
block:
2020-09-17 16:20:22 +02:00
- name: Print a message
ansible.builtin.debug:
2018-08-28 19:40:12 +02:00
msg: 'I execute normally'
2020-09-17 16:20:22 +02:00
- name: Force a failure
ansible.builtin.command: /bin/false
- name: Never print this
ansible.builtin.debug:
2018-08-28 19:40:12 +02:00
msg: 'I never execute :-('
2018-02-02 19:20:03 +01:00
always:
2020-09-17 16:20:22 +02:00
- name: Always do this
ansible.builtin.debug:
2018-08-28 19:40:12 +02:00
msg: "This always executes, :-)"
2015-07-17 19:53:13 +02:00
2019-12-12 19:35:17 +01:00
Together, these elements offer complex error handling.
2015-07-17 19:53:13 +02:00
2018-08-28 19:40:12 +02:00
.. code-block :: YAML
2021-01-14 20:40:31 +01:00
:emphasize-lines: 2,13,24
2018-08-28 19:40:12 +02:00
:caption: Block with all sections
- name: Attempt and graceful roll back demo
block:
2020-09-17 16:20:22 +02:00
- name: Print a message
ansible.builtin.debug:
2018-08-28 19:40:12 +02:00
msg: 'I execute normally'
2020-09-17 16:20:22 +02:00
- name: Force a failure
ansible.builtin.command: /bin/false
- name: Never print this
ansible.builtin.debug:
2018-08-28 19:40:12 +02:00
msg: 'I never execute, due to the above task failing, :-('
rescue:
2020-09-17 16:20:22 +02:00
- name: Print when errors
ansible.builtin.debug:
2018-08-28 19:40:12 +02:00
msg: 'I caught an error'
2020-09-17 16:20:22 +02:00
- name: Force a failure in middle of recovery! >:-)
ansible.builtin.command: /bin/false
- name: Never print this
ansible.builtin.debug:
2018-08-28 19:40:12 +02:00
msg: 'I also never execute :-('
always:
2020-09-17 16:20:22 +02:00
- name: Always do this
ansible.builtin.debug:
2018-08-28 19:40:12 +02:00
msg: "This always executes"
2019-12-12 19:35:17 +01:00
The tasks in the `` block `` execute normally. If any tasks in the block return `` failed `` , the `` rescue `` section executes tasks to recover from the error. The `` always `` section runs regardless of the results of the `` block `` and `` rescue `` sections.
2018-08-28 19:40:12 +02:00
2020-09-17 16:20:22 +02:00
If an error occurs in the block and the rescue task succeeds, Ansible reverts the failed status of the original task for the run and continues to run the play as if the original task had succeeded. The rescued task is considered successful, and does not trigger `` max_fail_percentage `` or `` any_errors_fatal `` configurations. However, Ansible still reports a failure in the playbook statistics.
2015-07-17 19:53:13 +02:00
2019-12-12 19:35:17 +01:00
You can use blocks with `` flush_handlers `` in a rescue task to ensure that all handlers run even if an error occurs:
2016-04-18 23:18:20 +02:00
.. code-block :: YAML
2021-01-14 20:40:31 +01:00
:emphasize-lines: 3,12
2016-04-18 23:18:20 +02:00
:caption: Block run handlers in error handling
tasks:
2018-06-14 08:14:11 +02:00
- name: Attempt and graceful roll back demo
2017-08-02 22:36:17 +02:00
block:
2020-09-17 16:20:22 +02:00
- name: Print a message
ansible.builtin.debug:
2018-02-02 19:20:03 +01:00
msg: 'I execute normally'
2019-05-14 16:02:41 +02:00
changed_when: yes
2017-08-02 22:36:17 +02:00
notify: run me even after an error
2020-09-17 16:20:22 +02:00
- name: Force a failure
ansible.builtin.command: /bin/false
2017-08-02 22:36:17 +02:00
rescue:
2020-09-17 16:20:22 +02:00
- name: Make sure all handlers run
2017-08-02 22:36:17 +02:00
meta: flush_handlers
2018-02-02 19:20:03 +01:00
handlers:
2020-09-17 16:20:22 +02:00
- name: Run me even after an error
ansible.builtin.debug:
2018-06-14 08:14:11 +02:00
msg: 'This handler runs even on error'
2015-07-17 19:53:13 +02:00
2018-07-30 20:05:16 +02:00
.. versionadded :: 2.1
2019-12-12 19:35:17 +01:00
Ansible provides a couple of variables for tasks in the `` rescue `` portion of a block:
2018-07-30 20:05:16 +02:00
ansible_failed_task
The task that returned 'failed' and triggered the rescue. For example, to get the name use `` ansible_failed_task.name `` .
ansible_failed_result
The captured return result of the failed task that triggered the rescue. This would equate to having used this var in the `` register `` keyword.
2015-07-17 19:53:13 +02:00
.. seealso ::
2019-06-26 23:07:27 +02:00
:ref: `playbooks_intro`
2015-07-17 19:53:13 +02:00
An introduction to playbooks
2019-06-26 23:07:27 +02:00
:ref: `playbooks_reuse_roles`
2015-07-17 19:53:13 +02:00
Playbook organization by roles
2018-07-21 15:48:47 +02:00
`User Mailing List <https://groups.google.com/group/ansible-devel> `_
2015-07-17 19:53:13 +02:00
Have a question? Stop by the google group!
2021-06-01 09:48:09 +02:00
`irc.libera.chat <https://libera.chat/> `_
2015-07-17 19:53:13 +02:00
#ansible IRC chat channel