ansible / proposals

Repository for sharing and tracking progress on enhancement proposals for Ansible.
Creative Commons Zero v1.0 Universal
93 stars 19 forks source link

Run `always`/`rescue` tasks when cancelling a task in a `block` with SIGINT/SIGTERM #120

Open kustodian opened 6 years ago

kustodian commented 6 years ago

Proposal: Run always/rescue tasks when cancelling a task in a block with SIGINT/SIGTERM

Author: Strahinja Kustudic @kustodian

Date: 2018/06/15

Motivation

Ansible has blocks and they allow us to have tasks which will be executed in case of failure which should be stated in the rescue section and tasks which should be run all the time which is stated in the always sections. This is very useful if you need to do some clean up, or some post tasks in case of failure, or always.

Problems

The problem is that if you cancel a task in a block which has a rescue/always sections by sending SIGINT/SIGTERM to the ansible-playbook process, Ansible just stops the execution and exits, it doesn't run the tasks in rescue/always sections.

For example we have the following playbook which runs some stress tests which looks like this:

---
- hosts: hosts_to_burn
  vars:
    duration: 24
    data_size: 120
    dirs:
      - /tmp
  tasks:
    - block:
        - name: Install sysbench
          yum:
            name: sysbench
            state: latest

        - script: files/burn.sh '{{ duration }}' '{{ data_size }}' {{ dirs | join(',') }}
          async: 0
          poll: 10
      always:
        - name: Remove sysbench by undoing the transaction
          shell: "yum -y history undo $(yum history list sysbench | grep -m 1 Install | tr -d ' ' | cut -d '|' -f 1)"
          args:
            warn: no

        - name: Remove benchmark dirs
          file:
            name: '{{ item }}'
            state: absent
          with_items: '{{ dirs }}'

So what I expect from this playbook when press CTRL+C is that it executes the always tasks so my hosts are clean from the sysbench package and files create by it.

Solution proposal

Make ansible-playbook treat SIGHUP/SIGTERM signals special and when cancelling a task with one of those signals execute the always/rescue sections, then stop the execution, so that possible clean up tasks can execute regularly.

One other important reason why always/rescue should execute is because if I want them to execute when the tasks fail, why I wouldn't want to execute them in case I cancelled the task? Also if for some reason we want to cancel tasks in those sections, you can always press CTRL+C again.

bcoca commented 6 years ago

They are supposed to handle task 'failed' state, in an interruption, the task won't get a state assigned. That said, I would not be against this feature as long as it had a toggle for it.

jnm27 commented 1 year ago

I support this. One Ctrl+C to start a clean cancel (which runs always/rescue), and if they run Ctrl+C again during the clean cancel, it forcefully exits. A PLAY RECAP at the end showing all the hosts (that have not finished yet) "failed" would be nice to complement this.