diff --git a/changelogs/fragments/75216-loop-control-extended-allitems.yml b/changelogs/fragments/75216-loop-control-extended-allitems.yml new file mode 100644 index 00000000000..5c60d503eba --- /dev/null +++ b/changelogs/fragments/75216-loop-control-extended-allitems.yml @@ -0,0 +1,3 @@ +minor_changes: +- Loops - Add new ``loop_control.extended_allitems`` to allow users to disable tracking all loop items for each loop + (https://github.com/ansible/ansible/issues/75216) diff --git a/docs/docsite/rst/user_guide/playbooks_loops.rst b/docs/docsite/rst/user_guide/playbooks_loops.rst index cbb6c175049..eb5483ac449 100644 --- a/docs/docsite/rst/user_guide/playbooks_loops.rst +++ b/docs/docsite/rst/user_guide/playbooks_loops.rst @@ -452,6 +452,16 @@ Variable Description .. note:: When using ``loop_control.extended`` more memory will be utilized on the control node. This is a result of ``ansible_loop.allitems`` containing a reference to the full loop data for every loop. When serializing the results for display in callback plugins within the main ansible process, these references may be dereferenced causing memory usage to increase. +.. versionadded:: 2.14 + +To disable the ``ansible_loop.allitems`` item, to reduce memory consumption, set ``loop_control.extended_allitems: no``. + +:: + + loop_control: + extended: yes + extended_allitems: no + Accessing the name of your loop_var ----------------------------------- .. versionadded:: 2.8 diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index 6284e9aabe9..47b3ad323ef 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -283,6 +283,7 @@ class TaskExecutor: index_var = templar.template(self._task.loop_control.index_var) loop_pause = templar.template(self._task.loop_control.pause) extended = templar.template(self._task.loop_control.extended) + extended_allitems = templar.template(self._task.loop_control.extended_allitems) # This may be 'None',so it is templated below after we ensure a value and an item is assigned label = self._task.loop_control.label @@ -310,7 +311,6 @@ class TaskExecutor: if extended: task_vars['ansible_loop'] = { - 'allitems': items, 'index': item_index + 1, 'index0': item_index, 'first': item_index == 0, @@ -319,6 +319,8 @@ class TaskExecutor: 'revindex': items_len - item_index, 'revindex0': items_len - item_index - 1, } + if extended_allitems: + task_vars['ansible_loop']['allitems'] = items try: task_vars['ansible_loop']['nextitem'] = items[item_index + 1] except IndexError: diff --git a/lib/ansible/playbook/loop_control.py b/lib/ansible/playbook/loop_control.py index d840644fc81..2e38f7ea548 100644 --- a/lib/ansible/playbook/loop_control.py +++ b/lib/ansible/playbook/loop_control.py @@ -30,6 +30,7 @@ class LoopControl(FieldAttributeBase): _label = FieldAttribute(isa='str') _pause = FieldAttribute(isa='float', default=0) _extended = FieldAttribute(isa='bool') + _extended_allitems = FieldAttribute(isa='bool', default=True) def __init__(self): super(LoopControl, self).__init__() diff --git a/test/integration/targets/loop_control/extended.yml b/test/integration/targets/loop_control/extended.yml index 6ad9933a30e..3467d32fe3d 100644 --- a/test/integration/targets/loop_control/extended.yml +++ b/test/integration/targets/loop_control/extended.yml @@ -10,3 +10,14 @@ - third loop_control: extended: yes + + - debug: + var: ansible_loop + loop: + - first + - second + - third + loop_control: + extended: yes + extended_allitems: no + failed_when: ansible_loop.allitems is defined