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’
When you write it like that it means literately i not the variable i, you need to enclose the variable in square brackets.
{{ subnet_facts.subnets[i].id }}
Ah…it’s always the little things that get me. Thanks for for that, but there is still something missing/wrong…
Doesn’t work:
`
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”
}
]
}
`
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 }}”
`