user7802257
user7802257

Reputation:

Using Block in Handler - Ansible

I am writing a handler for an Ansible role to stop and start docker. The stop is written as follows in handlers/main.yml

- name: stop docker
  block:

    - name: stop docker (Debian based)
      block:

        - name: stop service docker on debian, if running
          systemd: name=docker state=stopped

        - name: stop service docker.socket on debian, if running
          systemd: name=docker.socket state=stopped

      when: ansible_pkg_mgr == "apt"
  
    - name: stop docker (CentOS based)
      block:

        - name: stop service docker on CentOS, if running
          service:
            name: docker
            state: stopped

        - name: stop service docker.socket on CentOS, if running
          service:
            name: docker
            state: stopped

      when: ansible_pkg_mgr == "yum"

Then in my tasks/main file, I'm calling stop docker

---
- name: test
  command: echo "Stopping docker" 

  notify:
    - stop docker

The error I'm receiving is ERROR! Unexpected Exception, this is probably a bug: 'Block' object has no attribute 'notified_hosts'

If I run this as a task in a playbook it works.

Is there a way to use block in an Ansible handler?

Upvotes: 8

Views: 8758

Answers (3)

Catalan Jarvis
Catalan Jarvis

Reputation: 33

I've faced a similar situation that I've resolved with the "listen" param in every single task within the block in handlers file.

- name: "restart server - Block"
  block:
    - name: "Ensure the webserver service is running with daemon-reloaded"
      systemd:
        name: webserver.service
        enabled: true
        state: restarted
        daemon_reload: true
      listen: "Restart Server"

    - name: "Wait until webserver is up and running"
      uri:
        url: 'http://localhost:8080'
        return_content: true
        validate_certs: false
        status_code: [200, 403]
      register: uri_output
      until: uri_output.status in [200, 403]
      retries: 12
      delay: 20  # seconds
    listen: "Restart Server"

and in the tasks file adding the notify param:

- name: "Install systemd webserver service"
  ansible.builtin.template:
    src: webserver_service.j2
    dest: /etc/systemd/system/webserver.service
    mode: 0644
  notify: "Restart Server"

The trick works because you can have repeated listen params but having different task names. To be more conscious about the tasks are related you can have them in a block, but it's not necessary.

I've taken this idea from: https://github.com/ansible/ansible/issues/77461#issuecomment-1088274545

Upvotes: 2

U880D
U880D

Reputation: 12064

According your error message it seems that Ansible do not provide block functionality for handlers.

Instead you could use an other approach

handlers:
  - name: Stop Docker
    include_tasks: tasks/stop_docker.yaml

and put the logic into a separate task file.

Further Information

Upvotes: 10

jehon
jehon

Reputation: 1648

For me, neither block and import_tasks did work (see https://docs.ansible.com/ansible/latest/user_guide/playbooks_blocks.html).

- name: do something else in somewhere else:
  include_tasks: roles/jh_load_services/tasks/main.yml

If that can help

Upvotes: 4

Related Questions