2019-04-05 23:49:20 +02:00
.. _playbooks_blocks:
2015-07-17 19:53:13 +02:00
Blocks
======
2018-08-22 21:07:24 +02:00
Blocks allow for logical grouping of tasks and in play error handling. Most of what you can apply to a single task (with the exception of loops) can be applied at the block level, which also makes it much easier to set data or directives common to the tasks. This does not mean the directive affects the block itself, but is inherited by the tasks enclosed by a block. i.e. a `when` will be applied to the tasks, not 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:
2018-10-18 22:24:52 +02:00
- name: install httpd and memcached
yum:
name: "{{ item }}"
2018-10-31 15:36:35 +01:00
state: present
2018-10-18 22:24:52 +02:00
loop:
- httpd
- memcached
- name: apply the foo config template
template:
src: templates/src.j2
dest: /etc/foo.conf
- name: start service bar and enable it
service:
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
2016-10-21 14:30:11 +02:00
In the example above, each of the 3 tasks will be executed after appending the `when` condition from the block
2016-02-03 20:33:25 +01:00
and evaluating it in the task's context. Also they inherit the privilege escalation directives enabling "become to root"
2019-04-05 23:49:20 +02:00
for all the enclosed tasks. Finally, `` ignore_errors: yes `` will continue executing the playbook even if some of the tasks fail.
2015-07-17 19:53:13 +02:00
2018-10-18 22:24:52 +02:00
Names for tasks within 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-04-05 23:49:20 +02:00
Blocks error handling
`` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ``
2015-07-17 19:53:13 +02:00
2015-08-05 01:09:06 +02:00
Blocks also introduce the ability to handle errors in a way similar to exceptions in most programming languages.
2019-04-05 23:49:20 +02:00
Blocks only deal with 'failed' status of a task. A bad task definition or an unreachable host are not 'rescuable' errors.
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
2018-08-28 19:40:12 +02:00
:emphasize-lines: 3,10
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:
- debug:
msg: 'I execute normally'
2018-08-28 19:40:12 +02:00
- name: i force a failure
command: /bin/false
2018-02-02 19:20:03 +01:00
- 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:
- debug:
2018-08-28 19:40:12 +02:00
msg: 'I caught an error, can do stuff here to fix it, :-)'
This will 'revert' the failed status of the task for the run and the play will continue as if it had succeeded.
There is also an `` always `` section, that will run no matter what the task status is.
.. _block_always:
.. code-block :: YAML
:emphasize-lines: 2,9
:caption: Block with always section
- name: Always do X
block:
- debug:
msg: 'I execute normally'
- name: i force a failure
command: /bin/false
2018-02-02 19:20:03 +01:00
- debug:
2018-08-28 19:40:12 +02:00
msg: 'I never execute :-('
2018-02-02 19:20:03 +01:00
always:
- debug:
2018-08-28 19:40:12 +02:00
msg: "This always executes, :-)"
2015-07-17 19:53:13 +02:00
2018-08-28 19:40:12 +02:00
They can be added all together to do complex error handling.
2015-07-17 19:53:13 +02:00
2018-08-28 19:40:12 +02:00
.. code-block :: YAML
:emphasize-lines: 2,9,16
:caption: Block with all sections
- name: Attempt and graceful roll back demo
block:
- debug:
msg: 'I execute normally'
- name: i force a failure
command: /bin/false
- debug:
msg: 'I never execute, due to the above task failing, :-('
rescue:
- debug:
msg: 'I caught an error'
- name: i force a failure in middle of recovery! >:-)
command: /bin/false
- debug:
msg: 'I also never execute :-('
always:
- debug:
msg: "This always executes"
The tasks in the `` block `` would execute normally, if there is any error the `` rescue `` section would get executed
with whatever you need to do to recover from the previous error.
The `` always `` section runs no matter what previous error did or did not occur in the `` block `` and `` rescue `` sections.
It should be noted that the play continues if a `` rescue `` section completes successfully as it 'erases' the error status (but not the reporting),
this means it won't trigger `` max_fail_percentage `` nor `` any_errors_fatal `` configurations but will appear in the playbook statistics.
2015-07-17 19:53:13 +02:00
2016-04-18 23:18:20 +02:00
Another example is how to run handlers after an error occurred :
.. code-block :: YAML
2018-02-02 19:20:03 +01:00
:emphasize-lines: 6,10
2016-04-18 23:18:20 +02:00
:caption: Block run handlers in error handling
2018-02-02 19:20:03 +01:00
2016-04-18 23:18:20 +02:00
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:
2018-02-02 19:20:03 +01:00
- debug:
msg: 'I execute normally'
2017-08-02 22:36:17 +02:00
notify: run me even after an error
- command: /bin/false
rescue:
- name: make sure all handlers run
meta: flush_handlers
2018-02-02 19:20:03 +01:00
handlers:
2017-08-02 22:36:17 +02:00
- name: run me even after an error
2018-02-02 19:20:03 +01:00
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
Ansible also provides a couple of variables for tasks in the `` rescue `` portion of a block:
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 ::
:doc: `playbooks`
An introduction to playbooks
2017-06-06 23:39:48 +02:00
:doc: `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!
`irc.freenode.net <http://irc.freenode.net> `_
#ansible IRC chat channel