# How to properly iterate over an array and set\_fact when the array can be variable length?

**URL:** <https://forum.ansible.com/t/how-to-properly-iterate-over-an-array-and-set-fact-when-the-array-can-be-variable-length/27155>\
**Category:** Ansible Project\
**Tags:** aws\
**Created:** [March 29, 2018, 8:05pm UTC](https://forum.ansible.com/t/how-to-properly-iterate-over-an-array-and-set-fact-when-the-array-can-be-variable-length/27155 "2018-03-29T20:05:10Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dayton\_Jones](https://avatars.discourse-cdn.com/v4/letter/d/22d042/32.png) [@Dayton\_Jones](https://forum.ansible.com/u/Dayton_Jones)\
**Post date:** [March 29, 2018, 8:05pm UTC](https://forum.ansible.com/t/how-to-properly-iterate-over-an-array-and-set-fact-when-the-array-can-be-variable-length/27155/1 "2018-03-29T20:05:10Z")

</div>

I’m trying to use the efs module to create EFS volumes dynamically in AWS/EC2 by getting the list of subnets/security groups for a VPC. My problem is some VPCs have 2 subnets, some have 3, etc - so the tasks below fail.

I’m struggling on how to get the count of subnets and looping over it to set the “efs\_targets” fact properly to send to the efs module

`

- name: Gather subnet facts  
ec2\_vpc\_subnet\_facts:  
profile: “{{ aws\_account\_name }}”  
region: “{{ region }}”  
filters:  
vpc-id: “{{ vpc\_id }}”  
“tag:Public”: “True”  
register: subnet\_facts

- name: Generate EFS Targets  
ec2\_group\_facts:  
region: “{{ region }}”  
profile: “{{ aws\_account\_name }}”  
filters:  
group-name:

- group1

- group2  
vpc-id: “{{ vpc\_id }}”  
register: sgfacts

- set\_fact:  
efs\_security\_groups: ‘[“{{ sgfacts.security\_groups.0.group\_id }}”, “{{ sgfacts.security\_groups.1.group\_id }}”]’

- set\_fact:  
#This works only if there are 3 subnets  
efs\_targets:

- subnet\_id: “{{ subnet\_facts.subnets.0.id }}”  
security\_groups: “{{ efs\_security\_groups }}”

- subnet\_id: “{{ subnet\_facts.subnets.1.id }}”  
security\_groups: “{{ efs\_security\_groups }}”

- subnet\_id: “{{ subnet\_facts.subnets.2.id }}”  
security\_groups: “{{ efs\_security\_groups }}”

`

I tried permutations of:

`

- set\_fact:  
efs\_targets: "{% for i in range(0,(subnet\_facts.subnets)| length) %}
- subnet\_id: {{ subnet\_facts.subnets.i.id }}  
security\_groups: {{ efs\_security\_groups }}  
{% endfor %}"

`

But it fails with ‘list object’ has no attribute ‘i’

---

<div class="post-metadata">

**Author:** ![Kai\_Stian\_Olstad](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@Kai\_Stian\_Olstad](https://forum.ansible.com/u/Kai_Stian_Olstad)\
**Post date:** [March 30, 2018, 10:08am UTC](https://forum.ansible.com/t/how-to-properly-iterate-over-an-array-and-set-fact-when-the-array-can-be-variable-length/27155/2 "2018-03-30T10:08:22Z")

</div>

When you write it like that it means literately i not the variable i, you need to enclose the variable in square brackets.

&nbsp;&nbsp;{{ subnet\_facts.subnets[i].id }}

---

<div class="post-metadata">

**Author:** ![Dayton\_Jones](https://avatars.discourse-cdn.com/v4/letter/d/22d042/32.png) [@Dayton\_Jones](https://forum.ansible.com/u/Dayton_Jones)\
**Post date:** [March 30, 2018, 1:55pm UTC](https://forum.ansible.com/t/how-to-properly-iterate-over-an-array-and-set-fact-when-the-array-can-be-variable-length/27155/3 "2018-03-30T13:55:25Z")

</div>

Ah…it’s always the little things that get me. Thanks for for that, but there is still something missing/wrong…

Doesn’t work:

`

- set\_fact:

efs\_targets: '{% for i in range(0,(subnet\_facts.subnets)| length) %}

- subnet\_id: {{ subnet\_facts.subnets[i].id }}  
security\_groups: {{ efs\_security\_groups }}{% endfor %}’
- debug:  
var: efs\_targets

TASK [set\_fact] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [111.00.222.14] =\> {  
“ansible\_facts”: {},  
“changed”: false  
}

TASK [debug] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [111.00.222.14] =\> {  
“efs\_targets”: “VARIABLE IS NOT DEFINED!”  
}

`

But this does (but only when there are 3 subnets, of course) so I know subnet\_facts is being generated correctly…

`

- set\_fact:  
efs\_targets:

- subnet\_id: “{{ subnet\_facts.subnets.0.id }}”  
security\_groups: “{{ efs\_security\_groups }}”

- subnet\_id: “{{ subnet\_facts.subnets.1.id }}”  
security\_groups: “{{ efs\_security\_groups }}”

- subnet\_id: “{{ subnet\_facts.subnets.2.id }}”  
security\_groups: “{{ efs\_security\_groups }}”

- debug:  
var: efs\_targets

TASK [set\_fact] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [111.00.222.14] =\> {  
“ansible\_facts”: {  
“efs\_targets”: [  
{  
“security\_groups”: [  
“sg-VwysuqEM”,  
“sg-xXUBURyp”  
],  
“subnet\_id”: “subnet-bETYLaZY”  
},  
{  
“security\_groups”: [  
“sg-VwysuqEM”,  
“sg-xXUBURyp”  
],  
“subnet\_id”: “subnet-werigAdE”  
},  
{  
“security\_groups”: [  
“sg-VwysuqEM”,  
“sg-xXUBURyp”  
],  
“subnet\_id”: “subnet-qXeWEbEq”  
}  
]  
},  
“changed”: false  
}

TASK [debug] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [111.00.222.14] =\> {  
“efs\_targets”: [  
{  
“security\_groups”: [  
“sg-VwysuqEM”,  
“sg-xXUBURyp”  
],  
“subnet\_id”: “subnet-bETYLaZY”  
},  
{  
“security\_groups”: [  
“sg-VwysuqEM”,  
“sg-xXUBURyp”  
],  
“subnet\_id”: “subnet-werigAdE”  
},  
{  
“security\_groups”: [  
“sg-VwysuqEM”,  
“sg-xXUBURyp”  
],  
“subnet\_id”: “subnet-qXeWEbEq”  
}  
]  
}

`

---

<div class="post-metadata">

**Author:** ![Dayton\_Jones](https://avatars.discourse-cdn.com/v4/letter/d/22d042/32.png) [@Dayton\_Jones](https://forum.ansible.com/u/Dayton_Jones)\
**Post date:** [March 30, 2018, 8:05pm UTC](https://forum.ansible.com/t/how-to-properly-iterate-over-an-array-and-set-fact-when-the-array-can-be-variable-length/27155/4 "2018-03-30T20:05:21Z")

</div>

Ok… sorted this out in a different way after much trial and error (and an upgrade from ansible 2.4 to 2.5):

`

- set\_fact:  
my\_security\_groups:  
‘{{ sgfacts.security\_groups | map(attribute=“group\_id”) | list }}’

- set\_fact:  
my\_subnets:  
‘{{ subnet\_facts.subnets | map(attribute=“id”) | list }}’

- name: Create loop fact  
set\_fact:  
loop\_item:  
subnet\_id: “{{ item }}”  
security\_groups: “{{ my\_security\_groups }}”  
loop: “{{ my\_subnets }}”  
register: loop\_list

- name: Create EFS target list  
set\_fact:  
efs\_targets: “{{ loop\_list.results | map(attribute=‘ansible\_facts.loop\_item’) | list }}”  
`
