diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index 9c21a6c1675..985379e605b 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -275,6 +275,7 @@ class TaskExecutor: self._task.loop_control.post_validate(templar=templar) + unpack = self._task.loop_control.unpack loop_var = self._task.loop_control.loop_var index_var = self._task.loop_control.index_var loop_pause = self._task.loop_control.pause @@ -296,6 +297,10 @@ class TaskExecutor: for item_index, item in enumerate(items): task_vars['ansible_loop_var'] = loop_var + if unpack is True: + if not isinstance(item, Mapping): + raise AnsibleError('loop_control.unpack can only be used with a mapping/dictionary. Got %r' % item.__class__.__name__) + task_vars.update(item) task_vars[loop_var] = item if index_var: task_vars['ansible_index_var'] = index_var @@ -362,6 +367,7 @@ class TaskExecutor: res['_ansible_item_result'] = True res['_ansible_ignore_errors'] = task_fields.get('ignore_errors') res['_ansible_ignore_unreachable'] = task_fields.get('ignore_unreachable') + res['_ansible_loop_unpack'] = unpack # gets templated here unlike rest of loop_control fields, depends on loop_var above try: diff --git a/lib/ansible/playbook/included_file.py b/lib/ansible/playbook/included_file.py index d2fdb76364d..7b447b375ca 100644 --- a/lib/ansible/playbook/included_file.py +++ b/lib/ansible/playbook/included_file.py @@ -96,6 +96,9 @@ class IncludedFile: if loop_var in include_result: task_vars[loop_var] = special_vars[loop_var] = include_result[loop_var] task_vars['ansible_loop_var'] = special_vars['ansible_loop_var'] = loop_var + if include_result.get('_ansible_loop_unpack', False): + task_vars.update(task_vars[loop_var]) + special_vars.update(task_vars[loop_var]) if index_var and index_var in include_result: task_vars[index_var] = special_vars[index_var] = include_result[index_var] task_vars['ansible_index_var'] = special_vars['ansible_index_var'] = index_var diff --git a/lib/ansible/playbook/loop_control.py b/lib/ansible/playbook/loop_control.py index 8581b1f8b45..dc6c9266345 100644 --- a/lib/ansible/playbook/loop_control.py +++ b/lib/ansible/playbook/loop_control.py @@ -23,6 +23,7 @@ from ansible.playbook.base import FieldAttributeBase class LoopControl(FieldAttributeBase): + unpack = NonInheritableFieldAttribute(isa='bool', default=False, always_post_validate=True) loop_var = NonInheritableFieldAttribute(isa='string', default='item', always_post_validate=True) index_var = NonInheritableFieldAttribute(isa='string', always_post_validate=True) label = NonInheritableFieldAttribute(isa='string')