Fix incorrect rc when executing end_host in rescue (#83522)

Fixes #83447
pull/83539/head
Martin Krizek 1 year ago committed by GitHub
parent 6c0f4c8a2d
commit 571e2a9551
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,2 @@
bugfixes:
- "``end_host`` - fix incorrect return code when executing ``end_host`` in the ``rescue`` section (https://github.com/ansible/ansible/issues/83447)"

@ -635,3 +635,19 @@ class PlayIterator:
def clear_notification(self, hostname: str, notification: str) -> None:
self._host_states[hostname].handler_notifications.remove(notification)
def end_host(self, hostname: str) -> None:
"""Used by ``end_host``, ``end_batch`` and ``end_play`` meta tasks to end executing given host."""
state = self.get_active_state(self.get_state_for_host(hostname))
if state.run_state == IteratingStates.RESCUE:
# This is a special case for when ending a host occurs in rescue.
# By definition the meta task responsible for ending the host
# is the last task, so we need to clear the fail state to mark
# the host as rescued.
# The reason we need to do that is because this operation is
# normally done when PlayIterator transitions from rescue to
# always when only then we can say that rescue didn't fail
# but with ending a host via meta task, we don't get to that transition.
self.set_fail_state_for_host(hostname, FailedStates.NONE)
self.set_run_state_for_host(hostname, IteratingStates.COMPLETE)
self._play._removed_hosts.append(hostname)

@ -997,7 +997,7 @@ class StrategyBase:
if _evaluate_conditional(target_host):
for host in self._inventory.get_hosts(iterator._play.hosts):
if host.name not in self._tqm._unreachable_hosts:
iterator.set_run_state_for_host(host.name, IteratingStates.COMPLETE)
iterator.end_host(host.name)
msg = "ending batch"
else:
skipped = True
@ -1006,7 +1006,7 @@ class StrategyBase:
if _evaluate_conditional(target_host):
for host in self._inventory.get_hosts(iterator._play.hosts):
if host.name not in self._tqm._unreachable_hosts:
iterator.set_run_state_for_host(host.name, IteratingStates.COMPLETE)
iterator.end_host(host.name)
# end_play is used in PlaybookExecutor/TQM to indicate that
# the whole play is supposed to be ended as opposed to just a batch
iterator.end_play = True
@ -1016,8 +1016,7 @@ class StrategyBase:
skip_reason += ', continuing play'
elif meta_action == 'end_host':
if _evaluate_conditional(target_host):
iterator.set_run_state_for_host(target_host.name, IteratingStates.COMPLETE)
iterator._play._removed_hosts.append(target_host.name)
iterator.end_host(target_host.name)
msg = "ending play for %s" % target_host.name
else:
skipped = True

@ -76,3 +76,6 @@ done
# test refresh
ansible-playbook -i inventory_refresh.yml refresh.yml "$@"
ansible-playbook -i inventory_refresh.yml refresh_preserve_dynamic.yml "$@"
# test rc when end_host in the rescue section
ANSIBLE_FORCE_HANDLERS=0 ansible-playbook test_end_host_rescue_rc.yml

@ -0,0 +1,7 @@
- hosts: localhost
gather_facts: false
tasks:
- block:
- fail:
rescue:
- meta: end_host
Loading…
Cancel
Save