When running a task with run_once, if the first node is skipped, the entire task is skipped, rather than running on the first host that is not skipped.
This behavior is not what is intuitively understood, this behavior is not mentioned in the docs, and this behavior is almost certainly not what most of people want it to do. There are discussions of this in multiple github issues, the most detailed of which is at https://github.com/ansible/ansible/issues/19966, but there are also at least https://github.com/ansible/ansible/issues/11496, https://github.com/ansible/ansible/issues/13226, and https://github.com/ansible/ansible/issues/23594.
I was told by @bcoco to take this here, rather than discuss it in the existing github issues.
Below is an untested simple example of a scenario that would skip the run_once task, when it should (according to the docs, and common sense) run on one of either host2 or host3.
Inventory
`
[all]
host1
host2
host3
`
Playbook
`
- name: Test Play
hosts: all
tasks: - include: outer-task.yml
`
outer-task.yml
`
- name: Outer task
include: inner-task.yml
when: inventory_hostname != ‘host1’
`
inner-task.yml
`
- name: Inner task
command: do_something
run_once: True
`
This issue is exacerbated by the fact that the inner task may have no idea why the first host is skipped (IE: we’re including a reusable task that may get run many times in different ways). In those cases, there is no way to work around the issue with a simple when: inventory_hostname == something
, since we don’t know what to check against.
In https://github.com/ansible/ansible/issues/19966, @bcoco proposes a scenario where one would rely on the existing behavior, but in my opinion and that of the other commenters on that ticket, that use case is an incredibly bad practice, as it relies on the specific order of the inventory file. I can think of no sane reason to want the current behavior. If the user is doing crazy things like this, they should just stay on the old broken versions forever, as any update is likely to break their fragile buggy code.