Using Blocks
1. Defining Blocks
Blocks in Ansible are used to group tasks together and apply common attributes or conditions to all tasks within the block.
| Attribute | Description | Example |
|---|---|---|
| block | Defines the beginning of a block of tasks | block: |
| rescue | Defines a set of tasks to run if any task in the block fails | rescue: |
| always | Defines a set of tasks to run regardless of success or failure in the block | always: |
Example: Basic Block Definition
- name: Run tasks in a block
block:
- name: Task 1
command: echo "Task 1"
- name: Task 2
command: echo "Task 2"
rescue:
- name: Handle failure
command: echo "Rescue task"
always:
- name: Always run
command: echo "Always task"
2. Grouping Tasks
Blocks in Ansible allow you to group tasks together and apply common attributes or conditions to all tasks within the block. This is useful for organizing playbooks and applying settings like when, loop, or rescue to a set of tasks.
| Attribute | Description | Usage Example |
|---|---|---|
| block | Defines a group of tasks to be executed together. | |
| rescue | Defines a set of tasks to run if any task in the block fails. | |
| always | Defines a set of tasks to run regardless of whether the block succeeded or failed. | |
Example: Using Blocks with Loop and Rescue
- name: Loop through files and handle errors
block:
- name: Create directory if it doesn't exist
file:
path: /tmp/testdir
state: directory
- name: Create files in loop
file:
path: "/tmp/testdir/{{ item }}"
state: touch
loop:
- file1.txt
- file2.txt
- file3.txt
rescue:
- name: Log error if any task failed
debug:
msg: "An error occurred while creating files"
always:
- name: Clean up directory
file:
path: /tmp/testdir
state: absent
3. Implementing Error Handling
| Action | Description | Example |
|---|---|---|
| ignore_errors | Continue execution even if a task fails | |
| failed_when | Custom condition to mark a task as failed | |
| rescue | Tasks to run if a block fails | |
| always | Tasks to run regardless of success or failure | |
Example: Using rescue and always blocks
- name: Deploy application with error handling
hosts: web_servers
tasks:
- name: Start deployment
command: /usr/bin/deploy.sh
register: deploy_result
- name: Validate deployment
command: /usr/bin/validate.sh
when: deploy_result.rc == 0
failed_when: "'FAILED' in output"
- name: Rollback if needed
command: /usr/bin/rollback.sh
rescue:
- debug: msg="Rollback initiated"
- name: Cleanup resources
command: /usr/bin/cleanup.sh
always:
- debug: msg="Cleanup completed"
rescue and always blocks are part of the block structure and execute conditionally based on task success or failure.
Error Handling Best Practices
- Use
ignore_errorssparingly and document why - Implement custom failure conditions with
failed_when - Use
rescuefor rollback or recovery operations - Utilize
alwaysfor cleanup or final status reporting
4. Setting Block Variables
| Variable | Value | Description |
|---|---|---|
| block_var | value |
Defines a variable within the block scope |
| block_var_with_default | default_value |
Variable with a default value if not set |
Example: Setting Block Variables
- name: Set block variables
hosts: all
vars:
block_var: "example_value"
block_var_with_default: "default"
tasks:
- name: Use block variables
debug:
msg: "{{ block_var }} and {{ block_var_with_default }}"
5. Applying Block Conditions
| Condition Type | Description | Usage Example |
|---|---|---|
| when | Applies a condition to a block of tasks | |
| loop | Iterates over a list or set of items within a block | |
| rescue | Executes a block only if the main block fails | |
| always | Executes a block regardless of success or failure | |
Example: Using when with block conditions
- name: Conditional block execution
hosts: all
tasks:
- name: Set variable based on OS
set_fact:
os_type: "{{ ansible_facts['os_family'] }}"
when: ansible_facts is defined
- name: Execute tasks only on Linux
debug:
msg: "Running on Linux"
when: os_type == 'Linux'
when condition can be used at any level in Ansible, including inside blocks to control task execution based on variable or fact values.
6. Using Block Tags
| Tag | Description | Usage |
|---|---|---|
| block | Defines a block that can be overridden by roles or other playbooks | block: followed by a list of tasks |
| rescue | Defines a set of tasks to run if the main block fails | rescue: followed by a list of tasks |
| always | Defines a set of tasks to run regardless of success or failure | always: followed by a list of tasks |
Example: Using block tags in a playbook
- name: Example using block tags
hosts: all
tasks:
- name: Main block
block:
- shell: echo "Running main task"
- debug: msg="Main task completed"
rescue:
- debug: msg="Rescue block executed due to failure"
always:
- debug: msg="Always block executed"
rescue and always blocks are optional and can be omitted if not needed.
7. Setting Block Delegation
Block delegation in Ansible allows you to control how blocks are executed, particularly useful for conditional execution and error handling. You can configure delegation using the delegate_to and delegate_facts keywords.
| Parameter | Description | Values |
|---|---|---|
| delegate_to | Specifies the host to run the block on | hostname, localhost, or inventory_hostname |
| delegate_facts | Controls whether facts are delegated to the target host | true, false |
Example: Delegating a block to localhost
- name: Run a block on localhost
hosts: all
tasks:
- name: Execute commands on localhost
delegate_to: localhost
delegate_facts: true
command: whoami
delegate_to, ensure that the target host is reachable and has appropriate permissions to execute the tasks.
8. Executing Rescue Tasks
| Property | Description | Example |
|---|---|---|
| rescue | Defines a block of tasks to run if any task in the always or main block fails. |
|
| always | Defines a block of tasks to run regardless of success or failure in the main or rescue blocks. | |
Example: Rescue task execution flow
- name: Example with rescue and always
hosts: localhost
tasks:
- name: Fail task to trigger rescue
command: /bin/false
- name: Rescue block
rescue:
- debug:
msg: "This runs only if main fails"
- name: Always block
always:
- debug:
msg: "This runs regardless"
9. Ensuring Cleanup
Example: Using block with cleanup
- name: Ensure cleanup after task
hosts: all
tasks:
- name: Create temporary file
copy:
content: "temp data"
dest: "/tmp/tempfile.txt"
- name: Use block with cleanup
block:
- name: Do some work
command: echo "working"
- name: Fail task
command: false
rescue:
- name: Cleanup temp file
file:
path: "/tmp/tempfile.txt"
state: absent
| Property | Description | Values |
|---|---|---|
| block | Group of tasks to execute together | list of task objects |
| rescue | Tasks to run if any task in block fails | list of task objects |
| always | Tasks to run regardless of block success/failure | list of task objects |
rescue block runs only if a task in the block fails. The always block runs regardless of success or failure.
Block Execution Flow
- Execute tasks in
block - If any task fails, execute tasks in
rescue - Execute tasks in
always(regardless of outcome)
10. Nesting Blocks
Blocks can be nested inside other blocks to organize complex logic and reuse templates. This is particularly useful for managing conditional workflows or repeating structures.
| Block Type | Description | Usage Example |
|---|---|---|
| block | Defines a reusable block of tasks that can be included in other blocks or playbooks. | |
| rescue | Defines a set of tasks to run if any task in the main block fails. | |
| always | Defines a set of tasks to run regardless of whether the main block or rescue block succeeded. | |
Example: Nested Block Usage
- name: Example of nested blocks
block:
- name: Main task inside block
debug:
msg: "Running main tasks"
- name: Another task in the same block
debug:
msg: "Another task in the main block"
rescue:
- name: Handle failure in nested block
debug:
msg: "Rescuing from error in nested block"
always:
- name: Always run in nested block
debug:
msg: "Always running after nested block"
11. Using any_errors_fatal
The any_errors_fatal directive in Ansible controls how the playbook behaves when a task fails. When set to true, it causes the playbook to stop executing immediately upon encountering any failure, regardless of whether the task is part of a loop or conditional block.
| Directive | Values | Description |
|---|---|---|
| any_errors_fatal | true | false |
If set to true, stops playbook execution on any task failure. |
Example: Using any_errors_fatal at playbook level
---
- name: Example Playbook with any_errors_fatal
hosts: all
any_errors_fatal: true
tasks:
- name: Task that might fail
command: /bin/false
- name: This task will not run if previous fails
debug:
msg: "This is skipped"
any_errors_fatal to true affects the entire playbook and overrides any ignore_errors settings on individual tasks.