diff --git a/changelogs/fragments/expose-loop-var-name.yml b/changelogs/fragments/expose-loop-var-name.yml new file mode 100644 index 00000000000..802664555bf --- /dev/null +++ b/changelogs/fragments/expose-loop-var-name.yml @@ -0,0 +1,2 @@ +minor_changes: +- loop - expose loop var name as ``ansible_loop_var`` diff --git a/docs/docsite/rst/reference_appendices/special_variables.rst b/docs/docsite/rst/reference_appendices/special_variables.rst index 1b388eac74d..41324834d6c 100644 --- a/docs/docsite/rst/reference_appendices/special_variables.rst +++ b/docs/docsite/rst/reference_appendices/special_variables.rst @@ -28,6 +28,9 @@ ansible_limit ansible_loop A dictionary/map containing extended loop information when enabled via ``loop_control.extended`` +ansible_loop_var + The name of the value provided to ``loop_control.loop_var``. Added in ``2.8`` + ansible_play_batch List of active hosts in the current play run limited by the serial, aka 'batch'. Failed/Unreachable hosts are not considered 'active'. diff --git a/docs/docsite/rst/user_guide/playbooks_loops.rst b/docs/docsite/rst/user_guide/playbooks_loops.rst index ea91d611dc5..8b09330e4cc 100644 --- a/docs/docsite/rst/user_guide/playbooks_loops.rst +++ b/docs/docsite/rst/user_guide/playbooks_loops.rst @@ -400,6 +400,14 @@ Variable Description loop_control: extended: yes +.. versionadded:: 2.8 + +As of Ansible 2.8 you can get the name of the value provided to ``loop_control.loop_var`` using the ``ansible_loop_var`` variable + +For role authors, writing roles that allow loops, instead of dictating the required ``loop_var`` value, you can gather the value via:: + + "{{ lookup('vars', ansible_loop_var) }}" + .. _migrating_to_loop: Migrating from with_X to loop diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index 0786660f2cb..0763909c3c0 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -319,6 +319,8 @@ class TaskExecutor: no_log = False items_len = len(items) for item_index, item in enumerate(items): + task_vars['ansible_loop_var'] = loop_var + task_vars[loop_var] = item if index_var: task_vars[index_var] = item_index @@ -376,6 +378,7 @@ class TaskExecutor: # now update the result with the item info, and append the result # to the list of results res[loop_var] = item + res['ansible_loop_var'] = loop_var if index_var: res[index_var] = item_index if extended: diff --git a/test/integration/targets/assert/assert_quiet.out.quiet.stdout b/test/integration/targets/assert/assert_quiet.out.quiet.stdout index 65b82a6f283..b62aac6cd9f 100644 --- a/test/integration/targets/assert/assert_quiet.out.quiet.stdout +++ b/test/integration/targets/assert/assert_quiet.out.quiet.stdout @@ -6,6 +6,7 @@ ok: [localhost] => (item=item_A) TASK [assert] ****************************************************************** ok: [localhost] => (item=item_A) => { + "ansible_loop_var": "item", "changed": false, "item": "item_A", "msg": "All assertions passed" diff --git a/test/integration/targets/loops/tasks/main.yml b/test/integration/targets/loops/tasks/main.yml index db666873611..85fb5ce4b38 100644 --- a/test/integration/targets/loops/tasks/main.yml +++ b/test/integration/targets/loops/tasks/main.yml @@ -325,3 +325,12 @@ loop_control: extended: true when: item == 'banana' + +- name: Validate the loop_var name + assert: + that: + - ansible_loop_var == 'alvin' + loop: + - 1 + loop_control: + loop_var: alvin