New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ansible 2.0.0.2: Nested include + with_items does not work properly #14146

Closed
moorglade opened this Issue Jan 27, 2016 · 31 comments

Comments

Projects
None yet
@moorglade

moorglade commented Jan 27, 2016

Issue Type:

Bug report

Ansible Version:

ansible 2.0.0.2
ansible 2.1.0 (devel 7e39634)

Ansible Configuration:

N/A

Environment:

Ubuntu 15.10

Summary:

Ansible 2.0 added a feature to use include statements together with with_items loops. When nesting include statements, (i.e. file A.yml includes B.yml, which includes C.yml) the item variable is not set properly, i.e. the inner include + with_items loop does not override the item value from the outer loop.

Steps To Reproduce:

main.yml

---
- include: include_outer.yml
  with_items:
    - 1
    - 2
    - 3

include_outer.yml

---
- debug:
    msg: "Outer include: item={{ item }}"

- include: include_inner.yml
  with_items:
    - A
    - B
    - C

include_inner.yml

---
- debug:
    msg: "Inner include: item={{ item }}"
Expected Results:
"msg": "Outer include: item=1"
"msg": "Inner include: item=A"
"msg": "Inner include: item=B"
"msg": "Inner include: item=C"
"msg": "Outer include: item=2"
"msg": "Inner include: item=A"
"msg": "Inner include: item=B"
"msg": "Inner include: item=C"
"msg": "Outer include: item=3"
"msg": "Inner include: item=A"
"msg": "Inner include: item=B"
"msg": "Inner include: item=C"
Actual Results:
"msg": "Outer include: item=1"
"msg": "Inner include: item=1"
"msg": "Inner include: item=1"
"msg": "Inner include: item=1"
"msg": "Outer include: item=2"
"msg": "Inner include: item=2"
"msg": "Inner include: item=2"
"msg": "Inner include: item=2"
"msg": "Outer include: item=3"
"msg": "Inner include: item=3"
"msg": "Inner include: item=3"
"msg": "Inner include: item=3"
@jimi-c

This comment has been minimized.

Show comment
Hide comment
@jimi-c

jimi-c Jan 27, 2016

Member

This is documented in the loops documentation as a limitation (along with suggested work around for different scenarios): http://docs.ansible.com/ansible/playbooks_loops.html#loops-and-includes

If you continue seeing any problems related to this issue, or if you have any further questions, please let us know by stopping by one of the two mailing lists, as appropriate:

Because this project is very active, we're unlikely to see comments made on closed tickets, but the mailing list is a great way to ask questions, or post if you don't think this particular issue is resolved.

Thank you!

Member

jimi-c commented Jan 27, 2016

This is documented in the loops documentation as a limitation (along with suggested work around for different scenarios): http://docs.ansible.com/ansible/playbooks_loops.html#loops-and-includes

If you continue seeing any problems related to this issue, or if you have any further questions, please let us know by stopping by one of the two mailing lists, as appropriate:

Because this project is very active, we're unlikely to see comments made on closed tickets, but the mailing list is a great way to ask questions, or post if you don't think this particular issue is resolved.

Thank you!

@jimi-c jimi-c closed this Jan 27, 2016

@moorglade

This comment has been minimized.

Show comment
Hide comment
@moorglade

moorglade Jan 27, 2016

The documentation states:
"There are a couple of things that you need to keep in mind, a included task that has it’s own with_ loop will overwrite the value of the special item variable."

This is not the issue I have encountered, as far as I understand. Sorry if my description was unclear.

moorglade commented Jan 27, 2016

The documentation states:
"There are a couple of things that you need to keep in mind, a included task that has it’s own with_ loop will overwrite the value of the special item variable."

This is not the issue I have encountered, as far as I understand. Sorry if my description was unclear.

@jimi-c

This comment has been minimized.

Show comment
Hide comment
@jimi-c

jimi-c Jan 27, 2016

Member

This is a bit different, as you have an extra depth of include without looping in the inner-most include. Regardless, if you want to do this, you need to save the item variable from the outside loop, and don't use the variable name item as the param to the inner include.

Member

jimi-c commented Jan 27, 2016

This is a bit different, as you have an extra depth of include without looping in the inner-most include. Regardless, if you want to do this, you need to save the item variable from the outside loop, and don't use the variable name item as the param to the inner include.

@moorglade

This comment has been minimized.

Show comment
Hide comment
@moorglade

moorglade Jan 28, 2016

Still, I think it's a different problem. The item variable does not get overwritten in the inner include, i.e. instead of the three values from the inner loop (A, B, C), I get the outer loop value repeated three times. There is no way I can pass values to the inner loop.

I modified my example to better illustrate the case:

main.yml

- include: include_outer.yml
  with_items:
    - 1
    - 2
    - 3

include_outer.yml

---
- debug:
    msg: "Outer include: item={{ item }}"

- set_fact:
    outer_loop: "{{ item }}"

- include: include_inner.yml
  vars:
    inner_item: "{{ item }}"
    outer_item: "{{ outer_loop }}"
  with_items:
    - A
    - B
    - C

include_inner.yml

---
- debug:
    msg: "Inner include: inner_item={{ inner_item }}, outer_item={{ outer_item }}"

The result:

"msg": "Outer include: item=1"
"msg": "Inner include: inner_item=1, outer_item=1"
"msg": "Inner include: inner_item=1, outer_item=1"
"msg": "Inner include: inner_item=1, outer_item=1"
"msg": "Outer include: item=2"
"msg": "Inner include: inner_item=2, outer_item=2"
"msg": "Inner include: inner_item=2, outer_item=2"
"msg": "Inner include: inner_item=2, outer_item=2"
"msg": "Outer include: item=3"
"msg": "Inner include: inner_item=3, outer_item=3"
"msg": "Inner include: inner_item=3, outer_item=3"
"msg": "Inner include: inner_item=3, outer_item=3"

moorglade commented Jan 28, 2016

Still, I think it's a different problem. The item variable does not get overwritten in the inner include, i.e. instead of the three values from the inner loop (A, B, C), I get the outer loop value repeated three times. There is no way I can pass values to the inner loop.

I modified my example to better illustrate the case:

main.yml

- include: include_outer.yml
  with_items:
    - 1
    - 2
    - 3

include_outer.yml

---
- debug:
    msg: "Outer include: item={{ item }}"

- set_fact:
    outer_loop: "{{ item }}"

- include: include_inner.yml
  vars:
    inner_item: "{{ item }}"
    outer_item: "{{ outer_loop }}"
  with_items:
    - A
    - B
    - C

include_inner.yml

---
- debug:
    msg: "Inner include: inner_item={{ inner_item }}, outer_item={{ outer_item }}"

The result:

"msg": "Outer include: item=1"
"msg": "Inner include: inner_item=1, outer_item=1"
"msg": "Inner include: inner_item=1, outer_item=1"
"msg": "Inner include: inner_item=1, outer_item=1"
"msg": "Outer include: item=2"
"msg": "Inner include: inner_item=2, outer_item=2"
"msg": "Inner include: inner_item=2, outer_item=2"
"msg": "Inner include: inner_item=2, outer_item=2"
"msg": "Outer include: item=3"
"msg": "Inner include: inner_item=3, outer_item=3"
"msg": "Inner include: inner_item=3, outer_item=3"
"msg": "Inner include: inner_item=3, outer_item=3"
@moorglade

This comment has been minimized.

Show comment
Hide comment
@moorglade

moorglade Jan 28, 2016

Another example:

main.yml

---
- set_fact:
    item: "some_item_value"

- include: include_with_items.yml
  vars:
    my_item_value: "{{ item }}"

  with_items:
    - loop_item_value_1
    - loop_item_value_2
    - loop_item_value_3

include_with_items.yml

---
- debug:
    msg: "my_item_value={{ my_item_value }}"

Result:

"msg": "my_item_value=some_item_value"
"msg": "my_item_value=some_item_value"
"msg": "my_item_value=some_item_value"

moorglade commented Jan 28, 2016

Another example:

main.yml

---
- set_fact:
    item: "some_item_value"

- include: include_with_items.yml
  vars:
    my_item_value: "{{ item }}"

  with_items:
    - loop_item_value_1
    - loop_item_value_2
    - loop_item_value_3

include_with_items.yml

---
- debug:
    msg: "my_item_value={{ my_item_value }}"

Result:

"msg": "my_item_value=some_item_value"
"msg": "my_item_value=some_item_value"
"msg": "my_item_value=some_item_value"
@gregsymons

This comment has been minimized.

Show comment
Hide comment
@gregsymons

gregsymons Feb 6, 2016

I've encountered this issue too, and I'm not even referencing the outer item in the nested include: See this gist for a working example with expected and actual output.

Can we get this issue reopened so that someone might actually work on it?

gregsymons commented Feb 6, 2016

I've encountered this issue too, and I'm not even referencing the outer item in the nested include: See this gist for a working example with expected and actual output.

Can we get this issue reopened so that someone might actually work on it?

@asorbini

This comment has been minimized.

Show comment
Hide comment
@asorbini

asorbini Feb 8, 2016

+1 for reopening the issue. I'm experiencing the same issue as @moorglade and it is not what the Documentation discusses.

asorbini commented Feb 8, 2016

+1 for reopening the issue. I'm experiencing the same issue as @moorglade and it is not what the Documentation discusses.

@stewartm

This comment has been minimized.

Show comment
Hide comment
@stewartm

stewartm Feb 8, 2016

+1 for reopening the issue. Apologies @moorglade, I had not spotted this bug report when I duplicated with my own.

Regardless, if you want to do this, you need to save the item variable from the outside loop, and don't use the variable name item as the param to the inner include.

This does suggest that the issue has been misinterpreted, as in my own example in #14325, like @gregsymons, my inner include loop is referencing a variable outside the parent loop and is not dependent on 'item' from the parent.

The fundamental issue is that contrary to the docs, the 'item' variable will not get overwritten for a nested include passed a loop, where as it will for any other nested task passed a loop.

stewartm commented Feb 8, 2016

+1 for reopening the issue. Apologies @moorglade, I had not spotted this bug report when I duplicated with my own.

Regardless, if you want to do this, you need to save the item variable from the outside loop, and don't use the variable name item as the param to the inner include.

This does suggest that the issue has been misinterpreted, as in my own example in #14325, like @gregsymons, my inner include loop is referencing a variable outside the parent loop and is not dependent on 'item' from the parent.

The fundamental issue is that contrary to the docs, the 'item' variable will not get overwritten for a nested include passed a loop, where as it will for any other nested task passed a loop.

@jimi-c jimi-c reopened this Feb 8, 2016

@jimi-c jimi-c added the bug_report label Feb 8, 2016

@jimi-c jimi-c added this to the stable-2.0 milestone Feb 8, 2016

@cvle

This comment has been minimized.

Show comment
Hide comment
@cvle

cvle Mar 15, 2016

I just ran into this with ansible 2.0.1.0 :-(

cvle commented Mar 15, 2016

I just ran into this with ansible 2.0.1.0 :-(

@rcarrillocruz

This comment has been minimized.

Show comment
Hide comment
@rcarrillocruz

rcarrillocruz Mar 16, 2016

Contributor

I'm hitting this from devel too :(

Contributor

rcarrillocruz commented Mar 16, 2016

I'm hitting this from devel too :(

@arthurtsang

This comment has been minimized.

Show comment
Hide comment
@arthurtsang

arthurtsang commented Mar 17, 2016

same here.

@amather

This comment has been minimized.

Show comment
Hide comment
@amather

amather Apr 2, 2016

Same here. As a workaround, I've switched to devel with the feature_make_loop_variable_settable_per_task feature applied. Having a loop_var parameter seems to be the cleaner solution anyway.

@jimi-c Is the loop_var feature going to make it into 2.1? At time of this comment the decision was still open.

amather commented Apr 2, 2016

Same here. As a workaround, I've switched to devel with the feature_make_loop_variable_settable_per_task feature applied. Having a loop_var parameter seems to be the cleaner solution anyway.

@jimi-c Is the loop_var feature going to make it into 2.1? At time of this comment the decision was still open.

@nethershaw

This comment has been minimized.

Show comment
Hide comment
@nethershaw

nethershaw Apr 14, 2016

+1 for the loop_var feature from feature_make_loop_variable_settable_per_task. This feature branch is working for me. The topology of a network I'm building with Ansible requires include loops two layers deep; otherwise unrolling those loops gets very, very ugly and unwieldy. With this I can loop at arbitrary depths and still inherit variables properly.

nethershaw commented Apr 14, 2016

+1 for the loop_var feature from feature_make_loop_variable_settable_per_task. This feature branch is working for me. The topology of a network I'm building with Ansible requires include loops two layers deep; otherwise unrolling those loops gets very, very ugly and unwieldy. With this I can loop at arbitrary depths and still inherit variables properly.

@jimi-c

This comment has been minimized.

Show comment
Hide comment
@jimi-c

jimi-c Apr 14, 2016

Member

Yes I plan on having it in 2.1.

Member

jimi-c commented Apr 14, 2016

Yes I plan on having it in 2.1.

@jimi-c

This comment has been minimized.

Show comment
Hide comment
@jimi-c

jimi-c Apr 15, 2016

Member

@amather / @nethershaw after some internal discussions, I've created the branch feature_make_loop_variable_settable_per_task2, which starts implementing something we were going to do in Ansible 2.2. Essentially, we wanted a standardized way to give args to lookup plugins used in loops, so we've introduced the loop_control setting for tasks. Right now, for 2.1, this option will only support the loop_var setting, as follows:

- hosts: localhost
  gather_facts: no
  tasks:
  - command: echo '{{item_foo}}'
    with_items:
    - a
    - b
    - c
    loop_control:
      loop_var: item_foo

We felt it was better to go ahead and implement this now rather than 1 version later, in which case everyone would need to update their playbooks (or deal with deprecation messages).

Give it a try and let me know what you think.

Member

jimi-c commented Apr 15, 2016

@amather / @nethershaw after some internal discussions, I've created the branch feature_make_loop_variable_settable_per_task2, which starts implementing something we were going to do in Ansible 2.2. Essentially, we wanted a standardized way to give args to lookup plugins used in loops, so we've introduced the loop_control setting for tasks. Right now, for 2.1, this option will only support the loop_var setting, as follows:

- hosts: localhost
  gather_facts: no
  tasks:
  - command: echo '{{item_foo}}'
    with_items:
    - a
    - b
    - c
    loop_control:
      loop_var: item_foo

We felt it was better to go ahead and implement this now rather than 1 version later, in which case everyone would need to update their playbooks (or deal with deprecation messages).

Give it a try and let me know what you think.

@nethershaw

This comment has been minimized.

Show comment
Hide comment
@nethershaw

nethershaw Apr 16, 2016

@jimi-c Most excellent. I gave this a spin today on my playbooks that contain nested includes and with_items loops, just as your example, and the loop_control task attribute worked at all levels. It even worked alongside with_dict. Thank you!

nethershaw commented Apr 16, 2016

@jimi-c Most excellent. I gave this a spin today on my playbooks that contain nested includes and with_items loops, just as your example, and the loop_control task attribute worked at all levels. It even worked alongside with_dict. Thank you!

@jimi-c

This comment has been minimized.

Show comment
Hide comment
@jimi-c

jimi-c Apr 19, 2016

Member

The above loop_control/loop_var branch has been merged into devel, however we're holding this issue open as we are interested in why the bug is occurring.

Member

jimi-c commented Apr 19, 2016

The above loop_control/loop_var branch has been merged into devel, however we're holding this issue open as we are interested in why the bug is occurring.

@windowsrefund

This comment has been minimized.

Show comment
Hide comment
@windowsrefund

windowsrefund Apr 19, 2016

Can someone provide an example of this fix working using with_dict:? My experiments are failing as seen here: 6eefc11#commitcomment-17163490

windowsrefund commented Apr 19, 2016

Can someone provide an example of this fix working using with_dict:? My experiments are failing as seen here: 6eefc11#commitcomment-17163490

@nethershaw

This comment has been minimized.

Show comment
Hide comment
@nethershaw

nethershaw Apr 19, 2016

@windowsrefund In this example, an outer loop in a task playbook called loop_vpn.yml includes another playbook called loop_vpn_instance.yml using with_items like so:

# file: loop_vpn.yml
- name: "{{ stack.name }} {{ region }} : configure VPN endpoint cluster nodes"
  include: loop_vpn_instance.yml
  with_items:
    - "{{ region_map_vpn[region]['EIP1'] }}"
    - "{{ region_map_vpn[region]['EIP2'] }}"
  loop_control:
    loop_var: item_instance
  tags:
    - configure

Within the included playbook, this task using with_dict must create several configuration files on the delegated machine using a template populated by the contents of a dictionary called region_map_vpn, which happens to be the same dictionary from which the two items in the outer loop were selected:

# file: loop_vpn_instance.yml
- name: "{{ stack.name }} {{ region }} : {{ item_instance }} : configure VPN connections"
  template:
    src: regionL-regionR.conf.j2
    dest: /etc/ipsec.d/{{ region | replace('-', '') }}-{{ item_region_remote.key | replace('-', '') }}.conf
    owner: root
    group: root
    mode: 0644
  delegate_to: "{{ item_instance }}"
  with_dict: "{{ region_map_vpn }}"
  loop_control:
    loop_var: item_region_remote
  when: region != item_region_remote.key

For context, all of this occurs within a still larger loop that iterates over several Amazon AWS regions within a global stack where region is a key set by the outermost loop. Its purpose is to create a VPC in each region and establish a management network of IPSec tunnels between them.

This example has worked flawlessly in all of my testing.

nethershaw commented Apr 19, 2016

@windowsrefund In this example, an outer loop in a task playbook called loop_vpn.yml includes another playbook called loop_vpn_instance.yml using with_items like so:

# file: loop_vpn.yml
- name: "{{ stack.name }} {{ region }} : configure VPN endpoint cluster nodes"
  include: loop_vpn_instance.yml
  with_items:
    - "{{ region_map_vpn[region]['EIP1'] }}"
    - "{{ region_map_vpn[region]['EIP2'] }}"
  loop_control:
    loop_var: item_instance
  tags:
    - configure

Within the included playbook, this task using with_dict must create several configuration files on the delegated machine using a template populated by the contents of a dictionary called region_map_vpn, which happens to be the same dictionary from which the two items in the outer loop were selected:

# file: loop_vpn_instance.yml
- name: "{{ stack.name }} {{ region }} : {{ item_instance }} : configure VPN connections"
  template:
    src: regionL-regionR.conf.j2
    dest: /etc/ipsec.d/{{ region | replace('-', '') }}-{{ item_region_remote.key | replace('-', '') }}.conf
    owner: root
    group: root
    mode: 0644
  delegate_to: "{{ item_instance }}"
  with_dict: "{{ region_map_vpn }}"
  loop_control:
    loop_var: item_region_remote
  when: region != item_region_remote.key

For context, all of this occurs within a still larger loop that iterates over several Amazon AWS regions within a global stack where region is a key set by the outermost loop. Its purpose is to create a VPC in each region and establish a management network of IPSec tunnels between them.

This example has worked flawlessly in all of my testing.

@jimi-c jimi-c modified the milestones: 2.1.0, stable-2.0 Apr 20, 2016

@windowsrefund

This comment has been minimized.

Show comment
Hide comment
@windowsrefund

windowsrefund Apr 20, 2016

@nethershaw Hello, and thanks for the response. I'm not sure your example relates to the problem I've discovered as it appears your use of the iterators is limited to 2 levels. If you look at the example I've posted above, you'll see I'm actually trying to dig into the data I'm iterating over.

windowsrefund commented Apr 20, 2016

@nethershaw Hello, and thanks for the response. I'm not sure your example relates to the problem I've discovered as it appears your use of the iterators is limited to 2 levels. If you look at the example I've posted above, you'll see I'm actually trying to dig into the data I'm iterating over.

@windowsrefund

This comment has been minimized.

Show comment
Hide comment
@windowsrefund

windowsrefund Apr 20, 2016

I'm actually starting to have some success. Either I'm figuring this out or am completely wrong and will update this thread soon with my findings.

windowsrefund commented Apr 20, 2016

I'm actually starting to have some success. Either I'm figuring this out or am completely wrong and will update this thread soon with my findings.

@rcarrillocruz

This comment has been minimized.

Show comment
Hide comment
@rcarrillocruz

rcarrillocruz Apr 25, 2016

Contributor

@jimi-c so far so good, thanks a bunch for this!

Contributor

rcarrillocruz commented Apr 25, 2016

@jimi-c so far so good, thanks a bunch for this!

rcarrillocruz added a commit to rcarrillocruz/ansible-openstack-cloud-launcher that referenced this issue Apr 25, 2016

Use new loop_control/loop_var constructs from Ansible devel
Ansible now allows you to name the loop var, fixing nested
with_items include issue:

ansible/ansible#14146

Switching to it for making role future proof.
@tkinz27

This comment has been minimized.

Show comment
Hide comment
@tkinz27

tkinz27 May 4, 2016

So I have a bunch of roles that use dynamic task includes to include a set of tasks based on the platform of the remote host. In this case I do not care at all what the outer loop variable is and would prefer to just overwrite the loop variable.

I just started using ansible from devel and noticed that my roles are failing with this error now.

fatal: [10.64.3.116]: FAILED! => {"failed": true, "msg": "the loop variable 'item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else to avoid variable collisions"}

Is it going to be required that loop_var be set even if I'm perfectly ok with the loop_var being overwritten?

[EDITED]
So just found the Note on http://docs.ansible.com/ansible/playbooks_loops.html#loop-control. Could it be possible to add an ansible.cfg option to disable that check?

tkinz27 commented May 4, 2016

So I have a bunch of roles that use dynamic task includes to include a set of tasks based on the platform of the remote host. In this case I do not care at all what the outer loop variable is and would prefer to just overwrite the loop variable.

I just started using ansible from devel and noticed that my roles are failing with this error now.

fatal: [10.64.3.116]: FAILED! => {"failed": true, "msg": "the loop variable 'item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else to avoid variable collisions"}

Is it going to be required that loop_var be set even if I'm perfectly ok with the loop_var being overwritten?

[EDITED]
So just found the Note on http://docs.ansible.com/ansible/playbooks_loops.html#loop-control. Could it be possible to add an ansible.cfg option to disable that check?

@jimi-c

This comment has been minimized.

Show comment
Hide comment
@jimi-c

jimi-c May 12, 2016

Member

@tkinz27 I agree, so I've gone ahead and changed that error to a warning:

TASK [test : include] **********************************************************
task path: /root/testing/14146/roles/test/tasks/include_outer.yml:8
 [WARNING]: The loop variable 'item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else to avoid variable collisions and
unexpected behavior.

Since this overall appears to have resolved the stated issue, we're going to go ahead and close this now. If you have any further questions, please let us know by stopping by one of the two mailing lists, as appropriate:

Because this project is very active, we're unlikely to see comments made on closed tickets, but the mailing list is a great way to ask questions, or post if you don't think this particular issue is resolved.

Thank you!

Member

jimi-c commented May 12, 2016

@tkinz27 I agree, so I've gone ahead and changed that error to a warning:

TASK [test : include] **********************************************************
task path: /root/testing/14146/roles/test/tasks/include_outer.yml:8
 [WARNING]: The loop variable 'item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else to avoid variable collisions and
unexpected behavior.

Since this overall appears to have resolved the stated issue, we're going to go ahead and close this now. If you have any further questions, please let us know by stopping by one of the two mailing lists, as appropriate:

Because this project is very active, we're unlikely to see comments made on closed tickets, but the mailing list is a great way to ask questions, or post if you don't think this particular issue is resolved.

Thank you!

@jimi-c jimi-c closed this May 12, 2016

@bence-takacs

This comment has been minimized.

Show comment
Hide comment
@bence-takacs

bence-takacs Jul 7, 2016

Hi, Guys

The same issue with 'ansible 2.1.0.0'

Inside the internal loop the outer_item seems to be overwritten.
But outside everything is fine

outside.yaml:

---
- include: inside.yaml my_inner_item={{item}}
  with_items: 
    - A
    - B
    - C

inside.yaml:

---
- debug: msg="{{my_inner_item}} with {{ item }} is defined"
  with_items:
    - 1
    - 2
    - 3

- debug: msg="{{my_inner_item}} is defined"

output:

TASK [win-service : debug] *****************************************************
[WARNING]: The loop variable 'item' is already in use. You should set the loop_var value in the loop_control option for the task
to something else to avoid variable collisions and unexpected behavior.

ok: [myhost] => (item=1) => {
"item": 1,
"msg": "1 with 1 is defined"
}
ok: [myhost] => (item=2) => {
"item": 2,
"msg": "2 with 2 is defined"
}
ok: [myhost] => (item=3) => {
"item": 3,
"msg": "3 with 3 is defined"
}

TASK [win-service : debug] *****************************************************

ok: [myhost] => {
"msg": "A is defined"
}

bence-takacs commented Jul 7, 2016

Hi, Guys

The same issue with 'ansible 2.1.0.0'

Inside the internal loop the outer_item seems to be overwritten.
But outside everything is fine

outside.yaml:

---
- include: inside.yaml my_inner_item={{item}}
  with_items: 
    - A
    - B
    - C

inside.yaml:

---
- debug: msg="{{my_inner_item}} with {{ item }} is defined"
  with_items:
    - 1
    - 2
    - 3

- debug: msg="{{my_inner_item}} is defined"

output:

TASK [win-service : debug] *****************************************************
[WARNING]: The loop variable 'item' is already in use. You should set the loop_var value in the loop_control option for the task
to something else to avoid variable collisions and unexpected behavior.

ok: [myhost] => (item=1) => {
"item": 1,
"msg": "1 with 1 is defined"
}
ok: [myhost] => (item=2) => {
"item": 2,
"msg": "2 with 2 is defined"
}
ok: [myhost] => (item=3) => {
"item": 3,
"msg": "3 with 3 is defined"
}

TASK [win-service : debug] *****************************************************

ok: [myhost] => {
"msg": "A is defined"
}

@tjbenator

This comment has been minimized.

Show comment
Hide comment
@tjbenator

tjbenator Sep 6, 2016

@bence-takacs,

You need to use loop control:
http://docs.ansible.com/ansible/playbooks_loops.html#loop-control

outside.yaml:

---
- include: inside.yaml my_inner_item={{outer_item}}
  with_items: 
    - A
    - B
    - C
  loop_control:
    loop_var: outer_item

inside.yaml:

---
- debug: msg="{{my_inner_item}} with {{ item }} is defined"
  with_items:
    - 1
    - 2
    - 3

- debug: msg="{{my_inner_item}} is defined"

tjbenator commented Sep 6, 2016

@bence-takacs,

You need to use loop control:
http://docs.ansible.com/ansible/playbooks_loops.html#loop-control

outside.yaml:

---
- include: inside.yaml my_inner_item={{outer_item}}
  with_items: 
    - A
    - B
    - C
  loop_control:
    loop_var: outer_item

inside.yaml:

---
- debug: msg="{{my_inner_item}} with {{ item }} is defined"
  with_items:
    - 1
    - 2
    - 3

- debug: msg="{{my_inner_item}} is defined"
@MatthewBooth

This comment has been minimized.

Show comment
Hide comment
@MatthewBooth

MatthewBooth Oct 10, 2016

^ That categorically does not work. Sorry. loop_control is totally broken.

MatthewBooth commented Oct 10, 2016

^ That categorically does not work. Sorry. loop_control is totally broken.

@jimi-c

This comment has been minimized.

Show comment
Hide comment
@jimi-c

jimi-c Nov 4, 2016

Member

@MatthewBooth can you please provide an example, or create/reference another issue showing how it's broken?

Member

jimi-c commented Nov 4, 2016

@MatthewBooth can you please provide an example, or create/reference another issue showing how it's broken?

@arnonki

This comment has been minimized.

Show comment
Hide comment
@arnonki

arnonki Mar 23, 2017

Contributor

EDIT:

I`ve tried to look into it and I found out that the issue doesnt happen when I upgrade to 2.2.1.0 the issue doesn't happen

Hello,

There is definitely an issue with the include + loop functionality.
Using Ansible 2.2.0 and the following role:

outer.yml:

- include: inner.yml outer_item="{{ outer_item }}"
  with_items:
    - 1
    - 2
    - 3
  loop_control:
    loop_var: outer_item

inner.yml:

- debug: msg="Outer item={{outer_item}}"

What I get as an output is:


PLAY [Apply customers configuration] *******************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [test_task : include] *****************************************************
 [WARNING]: The loop variable 'outer_item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else
to avoid variable collisions and unexpected behavior.
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost

TASK [test_task : debug] *******************************************************
 [WARNING]: The loop variable 'outer_item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else
to avoid variable collisions and unexpected behavior.
ok: [localhost] => (item=None) => {
    "msg": "Outer item=1", 
    "outer_item": 1
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=2", 
    "outer_item": 2
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=3", 
    "outer_item": 3
}

TASK [test_task : debug] *******************************************************
 [WARNING]: The loop variable 'outer_item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else
to avoid variable collisions and unexpected behavior.
ok: [localhost] => (item=None) => {
    "msg": "Outer item=1", 
    "outer_item": 1
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=2", 
    "outer_item": 2
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=3", 
    "outer_item": 3
}

TASK [test_task : debug] *******************************************************
 [WARNING]: The loop variable 'outer_item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else
to avoid variable collisions and unexpected behavior.
ok: [localhost] => (item=None) => {
    "msg": "Outer item=1", 
    "outer_item": 1
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=2", 
    "outer_item": 2
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=3", 
    "outer_item": 3
}

PLAY RECAP *********************************************************************
localhost                  : ok=7    changed=0    unreachable=0    failed=0   

What is expected is to get is the following output (and behavior)


PLAY [Apply customers configuration] *******************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [test_task : include] *****************************************************
 [WARNING]: The loop variable 'outer_item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else
to avoid variable collisions and unexpected behavior.
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost

TASK [test_task : debug] *******************************************************

ok: [localhost] => (item=None) => {
    "msg": "Outer item=1", 
    "outer_item": 1
}

TASK [test_task : debug] *******************************************************

ok: [localhost] => (item=None) => {
    "msg": "Outer item=2", 
    "outer_item": 2
}

TASK [test_task : debug] *******************************************************

ok: [localhost] => (item=None) => {
    "msg": "Outer item=3", 
    "outer_item": 3
}

PLAY RECAP *********************************************************************
localhost                  : ok=7    changed=0    unreachable=0    failed=0   
```"
Contributor

arnonki commented Mar 23, 2017

EDIT:

I`ve tried to look into it and I found out that the issue doesnt happen when I upgrade to 2.2.1.0 the issue doesn't happen

Hello,

There is definitely an issue with the include + loop functionality.
Using Ansible 2.2.0 and the following role:

outer.yml:

- include: inner.yml outer_item="{{ outer_item }}"
  with_items:
    - 1
    - 2
    - 3
  loop_control:
    loop_var: outer_item

inner.yml:

- debug: msg="Outer item={{outer_item}}"

What I get as an output is:


PLAY [Apply customers configuration] *******************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [test_task : include] *****************************************************
 [WARNING]: The loop variable 'outer_item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else
to avoid variable collisions and unexpected behavior.
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost

TASK [test_task : debug] *******************************************************
 [WARNING]: The loop variable 'outer_item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else
to avoid variable collisions and unexpected behavior.
ok: [localhost] => (item=None) => {
    "msg": "Outer item=1", 
    "outer_item": 1
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=2", 
    "outer_item": 2
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=3", 
    "outer_item": 3
}

TASK [test_task : debug] *******************************************************
 [WARNING]: The loop variable 'outer_item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else
to avoid variable collisions and unexpected behavior.
ok: [localhost] => (item=None) => {
    "msg": "Outer item=1", 
    "outer_item": 1
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=2", 
    "outer_item": 2
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=3", 
    "outer_item": 3
}

TASK [test_task : debug] *******************************************************
 [WARNING]: The loop variable 'outer_item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else
to avoid variable collisions and unexpected behavior.
ok: [localhost] => (item=None) => {
    "msg": "Outer item=1", 
    "outer_item": 1
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=2", 
    "outer_item": 2
}
ok: [localhost] => (item=None) => {
    "msg": "Outer item=3", 
    "outer_item": 3
}

PLAY RECAP *********************************************************************
localhost                  : ok=7    changed=0    unreachable=0    failed=0   

What is expected is to get is the following output (and behavior)


PLAY [Apply customers configuration] *******************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [test_task : include] *****************************************************
 [WARNING]: The loop variable 'outer_item' is already in use. You should set the `loop_var` value in the `loop_control` option for the task to something else
to avoid variable collisions and unexpected behavior.
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost
included: /home/arnonk/playzone/roles/test_task/tasks/inner.yml for localhost

TASK [test_task : debug] *******************************************************

ok: [localhost] => (item=None) => {
    "msg": "Outer item=1", 
    "outer_item": 1
}

TASK [test_task : debug] *******************************************************

ok: [localhost] => (item=None) => {
    "msg": "Outer item=2", 
    "outer_item": 2
}

TASK [test_task : debug] *******************************************************

ok: [localhost] => (item=None) => {
    "msg": "Outer item=3", 
    "outer_item": 3
}

PLAY RECAP *********************************************************************
localhost                  : ok=7    changed=0    unreachable=0    failed=0   
```"
@AndrewChubatiuk

This comment has been minimized.

Show comment
Hide comment
@AndrewChubatiuk

AndrewChubatiuk Apr 4, 2017

Doesn't work as expected in Ansible 2.2.2.0 and older

AndrewChubatiuk commented Apr 4, 2017

Doesn't work as expected in Ansible 2.2.2.0 and older

@ansibot ansibot added bug and removed bug_report labels Mar 7, 2018

@chusiang

This comment has been minimized.

Show comment
Hide comment
@chusiang

chusiang May 13, 2018

The (item=None) is back on Ansible 2.5.2 ! 😂

$ ansible --version
ansible 2.5.2
  config file = /srv/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.14 (default, Dec 14 2017, 15:51:29) [GCC 6.4.0]
$ ansible-playbook playbook_loop.yml

PLAY [Basic loop on playbook] *************************************

TASK [Gathering Facts] ********************************************
ok: [localhost]

TASK [print loop message] *****************************************
ok: [localhost] => (item=None) => {
    "msg": "Hello Loop0"
}
ok: [localhost] => (item=None) => {
    "msg": "Hello Loop1"
}
ok: [localhost] => (item=None) => {
    "msg": "Hello Loop2"
}

PLAY RECAP ********************************************************
localhost    : ok=2    changed=0    unreachable=0    failed=0

chusiang commented May 13, 2018

The (item=None) is back on Ansible 2.5.2 ! 😂

$ ansible --version
ansible 2.5.2
  config file = /srv/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.14 (default, Dec 14 2017, 15:51:29) [GCC 6.4.0]
$ ansible-playbook playbook_loop.yml

PLAY [Basic loop on playbook] *************************************

TASK [Gathering Facts] ********************************************
ok: [localhost]

TASK [print loop message] *****************************************
ok: [localhost] => (item=None) => {
    "msg": "Hello Loop0"
}
ok: [localhost] => (item=None) => {
    "msg": "Hello Loop1"
}
ok: [localhost] => (item=None) => {
    "msg": "Hello Loop2"
}

PLAY RECAP ********************************************************
localhost    : ok=2    changed=0    unreachable=0    failed=0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment