Simplify global loop result processing

pull/84173/merge^2
Martin Krizek 1 month ago
parent e14f9fe725
commit a4a8e10d19

@ -26,6 +26,7 @@ from ansible.playbook.conditional import Conditional
from ansible.playbook.task import Task from ansible.playbook.task import Task
from ansible.plugins import get_plugin_class from ansible.plugins import get_plugin_class
from ansible.plugins.loader import become_loader, cliconf_loader, connection_loader, httpapi_loader, netconf_loader, terminal_loader from ansible.plugins.loader import become_loader, cliconf_loader, connection_loader, httpapi_loader, netconf_loader, terminal_loader
from ansible.plugins.test.core import unreachable
from ansible.template import Templar from ansible.template import Templar
from ansible.utils.collection_loader import AnsibleCollectionConfig from ansible.utils.collection_loader import AnsibleCollectionConfig
from ansible.utils.listify import listify_lookup_plugin_terms from ansible.utils.listify import listify_lookup_plugin_terms
@ -126,49 +127,43 @@ class TaskExecutor:
self._loop_eval_error = e self._loop_eval_error = e
if items is not None: if items is not None:
if len(items) > 0: if items:
item_results = self._run_loop(items) res = {'results': self._run_loop(items)}
# set the global changed/failed/skipped result flags based on any item
# create the overall result item warnings = set()
res = dict(results=item_results) deprecations = set()
skipped = True
# loop through the item results and set the global changed/failed/skipped result flags based on any item. changed = failed = unreachable = False
res['skipped'] = True for item in res['results']:
for item in item_results: skipped &= item.get('skipped', False)
if 'changed' in item and item['changed'] and not res.get('changed'): changed |= item.get('changed', False)
res['changed'] = True failed |= (failed_item := item.get('failed', False))
if res['skipped'] and ('skipped' not in item or ('skipped' in item and not item['skipped'])): unreachable |= (unreachable_item := item.get('unreachable', False))
res['skipped'] = False
if 'failed' in item and item['failed']: if failed_item:
item_ignore = item.pop('_ansible_ignore_errors') self._task.ignore_errors |= item.pop('_ansible_ignore_errors')
if not res.get('failed'): if unreachable_item:
res['failed'] = True self._task.ignore_unreachable |= item.pop('_ansible_ignore_unreachable')
res['msg'] = 'One or more items failed'
self._task.ignore_errors = item_ignore warnings.update(item.pop('warnings', []))
elif self._task.ignore_errors and not item_ignore: deprecations.update(item.pop('deprecations', []))
self._task.ignore_errors = item_ignore
if 'unreachable' in item and item['unreachable']: if warnings:
item_ignore_unreachable = item.pop('_ansible_ignore_unreachable') res['warnings'] = list(warnings)
if not res.get('unreachable'): if deprecations:
res['unreachable'] = True res['deprecations'] = list(deprecations)
self._task.ignore_unreachable = item_ignore_unreachable
elif self._task.ignore_unreachable and not item_ignore_unreachable: if skipped:
self._task.ignore_unreachable = item_ignore_unreachable
# ensure to accumulate these
for array in ['warnings', 'deprecations']:
if array in item and item[array]:
if array not in res:
res[array] = []
if not isinstance(item[array], list):
item[array] = [item[array]]
res[array] = res[array] + item[array]
del item[array]
if not res.get('failed', False):
res['msg'] = 'All items completed'
if res['skipped']:
res['msg'] = 'All items skipped' res['msg'] = 'All items skipped'
else:
res['msg'] = 'One or more items failed' if failed else 'All items completed'
res.update(
skipped=skipped,
changed=changed,
failed=failed,
unreachable=unreachable,
)
else: else:
res = dict(changed=False, skipped=True, skipped_reason='No items in the list', results=[]) res = dict(changed=False, skipped=True, skipped_reason='No items in the list', results=[])
else: else:

@ -722,8 +722,8 @@ class Base(FieldAttributeBase):
environment = FieldAttribute(isa='list', extend=True, prepend=True) environment = FieldAttribute(isa='list', extend=True, prepend=True)
no_log = FieldAttribute(isa='bool', default=C.DEFAULT_NO_LOG) no_log = FieldAttribute(isa='bool', default=C.DEFAULT_NO_LOG)
run_once = FieldAttribute(isa='bool') run_once = FieldAttribute(isa='bool')
ignore_errors = FieldAttribute(isa='bool') ignore_errors = FieldAttribute(isa='bool', default=False)
ignore_unreachable = FieldAttribute(isa='bool') ignore_unreachable = FieldAttribute(isa='bool', default=False)
check_mode = FieldAttribute(isa='bool', default=context.cliargs_deferred_get('check')) check_mode = FieldAttribute(isa='bool', default=context.cliargs_deferred_get('check'))
diff = FieldAttribute(isa='bool', default=context.cliargs_deferred_get('diff')) diff = FieldAttribute(isa='bool', default=context.cliargs_deferred_get('diff'))
any_errors_fatal = FieldAttribute(isa='bool', default=C.ANY_ERRORS_FATAL) any_errors_fatal = FieldAttribute(isa='bool', default=C.ANY_ERRORS_FATAL)

Loading…
Cancel
Save