Ansible Basics 11: Blocks

In Ansible, blocks are a powerful feature that allows users to group tasks logically within a playbook, enabling the execution of multiple tasks as a single unit. This functionality significantly enhances the manageability of complex playbooks by breaking them down into smaller, more manageable parts. Blocks not only create logical groups of tasks but also provide a structured approach to handle errors, similar to exception handling in programming languages.

Purpose of blocks in Ansible playbooks

Blocks serve a dual purpose in Ansible playbooks. Firstly, they help the organization of tasks by grouping them together, making it easier to manage and maintain playbooks, especially those with numerous tasks. This logical grouping enhances the readability and structure of playbooks, contributing to better code maintenance and troubleshooting.

Secondly, blocks offer a robust error-handling mechanism within playbooks. By using blocks with rescue and always sections, users can control how Ansible responds to task errors. The rescue section specifies tasks to run when an earlier task in a block encounters an error, allowing for graceful error recovery. On the other hand, the always section ensures that designated tasks execute regardless of the results of the block and rescue sections.

How to use blocks in Ansible playbooks

Utilizing blocks in Ansible playbooks involves a structured approach to task execution and error handling. When defining a block, tasks are enclosed within it, inheriting directives applied at the block level. Most directives applicable to a single task can be applied at the block level, simplifying the management of common data or directives across tasks.

To effectively use blocks in Ansible playbooks, follow these key steps:

  1. Define a block with a descriptive name to encapsulate related tasks.
  2. Include tasks within the block, ensuring they inherit directives applied at the block level.
  3. Implement error handling by specifying tasks in the rescue section to manage errors gracefully.
  4. Utilize the always section to include tasks that should run irrespective of the block’s outcome.
  5. Ensure that tasks within the block are structured logically and follow best practices for task execution.

Let’s see an example of grouping tasks in a block:

---
- name: Grouping tasks in a playbook/role with block
  hosts: all

  tasks:
    - name: This is NOT in a block
      ansible.builtin.debug:
        msg: This message is NOT in a block

    - name: This is going to be a block
      block:
        - name: First task in a block
          ansible.builtin.debug:
            msg: First task run
        - name: Second task in a block
          ansible.builtin.debug:
            msg: Second task
      when: ansible_facts['distribution'] == 'CentOS'

    - name: Out of the block
      ansible.builtin.debug:
        msg: Not in a block...

In the above example the block will NOT run on the Debian machine. The block consists of two tasks.

---
- name: Handling errors with blocks
  hosts: all

  tasks:
    - name: Rescue block
      block:
        - name: This runs
          ansible.builtin.debug:
            msg: This runs
        - name: This is a failure, Ansible would stop here
          ansible.builtin.command: /bin/false
      rescue:
        - name: Solve the issues
          ansible.builtin.debug:
            msg: This task should solve the error

In the example above the rescue: part will only run in case of failure in the previous tasks in the block. If you want it to run regardless of failure or not, then you have to change the keyword to always: instead of the rescue:.

---
- name: Handling errors and using always in blocks
  hosts: all

  tasks:
    - name: Always
      block:
        - name: This runs
          ansible.builtin.debug:
            msg: This runs
        - name: This is a failure, Ansible would stop here
          ansible.builtin.command: /bin/false
      always:
        - name: This will run always
          ansible.builtin.debug:
            msg: Failure or not this will run

Tasks in the always section will run no matter what the task status of the previous block is.

By following these guidelines, users can use blocks in Ansible playbooks to maintain a seamless task execution, enhance error handling, and improve the overall efficiency and reliability of their automation workflows.

If you want to discuss the topic with other technology-minded people, join my Discord: https://discord.gg/YbSYGsQYES

Now we have an IRC channel as well: irc.libera.chat / #tomsitcafe

Leave a comment