Implement max_fail_percentage and any_errors_fatal support
Fixes #11997
This commit is contained in:
parent
af41ba929c
commit
50448d68e1
3 changed files with 36 additions and 3 deletions
|
@ -128,15 +128,29 @@ class PlaybookExecutor:
|
||||||
self._tqm.send_callback('v2_playbook_on_play_start', new_play)
|
self._tqm.send_callback('v2_playbook_on_play_start', new_play)
|
||||||
self._tqm.send_callback('v2_playbook_on_no_hosts_matched')
|
self._tqm.send_callback('v2_playbook_on_no_hosts_matched')
|
||||||
break
|
break
|
||||||
|
|
||||||
# restrict the inventory to the hosts in the serialized batch
|
# restrict the inventory to the hosts in the serialized batch
|
||||||
self._inventory.restrict_to_hosts(batch)
|
self._inventory.restrict_to_hosts(batch)
|
||||||
# and run it...
|
# and run it...
|
||||||
result = self._tqm.run(play=play)
|
result = self._tqm.run(play=play)
|
||||||
# if the last result wasn't zero, break out of the serial batch loop
|
|
||||||
if result != 0:
|
# check the number of failures here, to see if they're above the maximum
|
||||||
|
# failure percentage allowed, or if any errors are fatal. If either of those
|
||||||
|
# conditions are met, we break out, otherwise we only break out if the entire
|
||||||
|
# batch failed
|
||||||
|
failed_hosts_count = len(self._tqm._failed_hosts) + len(self._tqm._unreachable_hosts)
|
||||||
|
if new_play.any_errors_fatal and failed_hosts_count > 0:
|
||||||
|
break
|
||||||
|
elif new_play.max_fail_percentage is not None and \
|
||||||
|
int((new_play.max_fail_percentage)/100.0 * len(batch)) > int((len(batch) - failed_hosts_count) / len(batch) * 100.0):
|
||||||
|
break
|
||||||
|
elif len(batch) == failed_hosts_count:
|
||||||
break
|
break
|
||||||
|
|
||||||
# if the last result wasn't zero, break out of the play loop
|
# clear the failed hosts dictionaires in the TQM for the next batch
|
||||||
|
self._tqm.clear_failed_hosts()
|
||||||
|
|
||||||
|
# if the last result wasn't zero, break out of the serial batch loop
|
||||||
if result != 0:
|
if result != 0:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
|
@ -210,6 +210,10 @@ class TaskQueueManager:
|
||||||
main_q.close()
|
main_q.close()
|
||||||
worker_prc.terminate()
|
worker_prc.terminate()
|
||||||
|
|
||||||
|
def clear_failed_hosts(self):
|
||||||
|
self._failed_hosts = dict()
|
||||||
|
self._unreachable_hosts = dict()
|
||||||
|
|
||||||
def get_inventory(self):
|
def get_inventory(self):
|
||||||
return self._inventory
|
return self._inventory
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,13 @@ from ansible.playbook.taggable import Taggable
|
||||||
|
|
||||||
__all__ = ['Task']
|
__all__ = ['Task']
|
||||||
|
|
||||||
|
try:
|
||||||
|
from __main__ import display
|
||||||
|
display = display
|
||||||
|
except ImportError:
|
||||||
|
from ansible.utils.display import Display
|
||||||
|
display = Display()
|
||||||
|
|
||||||
class Task(Base, Conditional, Taggable, Become):
|
class Task(Base, Conditional, Taggable, Become):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -193,6 +200,14 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
|
|
||||||
return super(Task, self).preprocess_data(new_ds)
|
return super(Task, self).preprocess_data(new_ds)
|
||||||
|
|
||||||
|
def _load_any_errors_fatal(self, attr, value):
|
||||||
|
'''
|
||||||
|
Exists only to show a deprecation warning, as this attribute is not valid
|
||||||
|
at the task level.
|
||||||
|
'''
|
||||||
|
display.deprecated("Setting any_errors_fatal on a task is no longer supported. This should be set at the play level only")
|
||||||
|
return None
|
||||||
|
|
||||||
def post_validate(self, templar):
|
def post_validate(self, templar):
|
||||||
'''
|
'''
|
||||||
Override of base class post_validate, to also do final validation on
|
Override of base class post_validate, to also do final validation on
|
||||||
|
|
Loading…
Reference in a new issue