Search code examples
ansibleansible-role

Execute handler as idempotent approach


I struggle with the following issue:

- name: Mount installer iso (Debian)
  become: true
  block:
    - name: Create mnt dir
      ansible.builtin.file:
        path: "/mnt/{{ package }}"
        state: directory
        mode: "0755"
    - name: Mount iso file
      ansible.posix.mount:
        path: "/mnt/{{ package }}"
        src: "tmp/{{ package }}.iso"
        fstype: iso9660
        state: ephemeral
      register: linux_iso_mounted

This Task is part of my role for installing a software which is provided via iso. If the mount task was successful but a followup task fails, the iso is still mounted and the task fails next time.

My first suggestion was to use pre_tasks and post_tasks but they are unavailable for roles as far as I know.

So my second approach is to move the cleanup tasks as handlers and trigger the notify with the posix.mount. This should work (not implemented until now) as the handler task get only executed after the finished play (right?).

Is this best practice or are other approaches better for this scenario?


Solution

  • If I understand your requirement correctly, there is a simpler approach - block provides the rescue (that will be executed in case of failure) and always (that will be executed in any case) blocks - you can run your cleanup tasks there.

    Moreover, AFAIK, ansible.posix.mount module should be idempotent, so you probably won't need the cleanup tasks at all.

    Edit: if the failing task is not the mount but the following one, the most straightforward solution would be to move it to the same block, and unmount your ISO volume in rescue block.

    Handlers will not help in this case. They are running on change, not on failure, and trying to override this behavior, while possible in theory (using an unnecessarily complex logic with custom failed_when/changed_when on the potentially failing task and meta: flush_handlers invocations with when), goes against both KISS principle and declarative approach promoted by Ansible. It would basically result in replicating the same try-catch-finally logic that block-rescue-always already has out of the box.