Ansible Pause – Fix Ansible Pause Not Working with When Conditionals

ansible

example play:

- name: WTF
  debug:
    msg: THIS WORKS "{{ inventory_hostname }} UPGRADE VAR IS "{{ upgrade }}"
  when: upgrade and inventory_hostname is regex("switch.*a")

- name: Wait for routes to be removed
  pause:
    prompt: "Wait 30 seconds or so for routes to be removed, push enter when ready"
  when: upgrade and inventory_hostname is regex("switch.*a")

the debug works fine however the pause task never runs. The when conditionals are the same. If i run this against a single host with --limit myhost it works fine however running it against a group of hosts and the pause task works for the first host but not the rest

wait_for is no good to me as i specifically need to wait for the user to press return

any idea of how i can do this?

Best Answer

pause is an action plugin does an uncommon thing: it bypasses the host loop. Which has an effect the same as forcing run_once: true that is to say run once even if multiple hosts are targeted. (The implementation is in strategy plugin code.)

This is what "bypass_host_loop full" attribute means in the plugin docs, which you can read on the cli by running ansible-doc pause

Code that does this implies the author never wanted to deal with multiple hosts. Which makes sense for a screen input plugin, would be a nightmare to deal with repeated interleaving hosts.

    - name: Wait for routes to be removed
      wait_for:
        timeout: 30
      # no point in uploading code just to sleep to remote hosts
      # although that could work if the remote host has Python
      delegate_to: localhost

wait_for is an alternative which can be used as a "sleep for this number of seconds" timer. However, user input is no longer an option.

Note that the play time elapsed might not be number of hosts times timeout seconds. Because the host loop can run multiple hosts in parallel.

Another alternative could be a task that checks for the thing to happen, perhaps polling for it. Assuming no specialized module exists that synchronously waits, could be done with an until: loop. On a task that queries if "routes are removed": set delay: task keyword to the minimum feasible seconds, and until: to an expression that checks if the task returned a success.

Scripting the confirmation that a thing happened, even if it takes some time after the task returns, can be good for automation. A play could keep going and do the next things on the list. Although at key points a persons input might be a good idea, depending on the work flows.