I have a role that encapsulates creation of ec2 instances. It’s sole functionality is to create a specified number of ec2 instances, register them in a group and then wait for the SSH port to be available for those instances so that they can be further provisioned. For availability reasons we create instances in at a minimum of two availability zones.
Most of the configuration of the main play is listed below:
`
-
name: Launch image(s)
local_action:
module: ec2
region: “{{item.ec2_region}}”
zone: “{{item.ec2_zone}}”
instance_type: “{{item.ec2_instance_type}}”
image: “{{item.ec2_image}}”
key_name: “{{item.ec2_keypair}}”
exact_count: “{{item.ec2_exact_count}}”
group: “{{item.ec2_security_groups}}”
instance_tags: “{{item.ec2_tags}}”
count_tag: “{{item.ec2_tags}}”
vpc_subnet_id: “{{item.ec2_vpc_subnet_id}}”
instance_profile_name: “{{item.ec2_instance_profile_name}}”
wait: true
register: ec2 -
name: Add new servers to group for configuration
local_action: add_host hostname={{item.public_dns_name}} groupname={{ec2_groupname}}
with_items: ec2.instances
when: ec2.changed -
name: Wait for the instances to boot by checking the ssh port
local_action: wait_for host={{item.public_dns_name}} port=22 delay=60 timeout=320 state=started
with_items: ec2.instances
when: ec2.changed
`
This works as expected, however this requires the calling playbook to call this role once for each ec2 definition and because we are launching into multiple availability zones there are always at least 2 ec2 definitions. I decided to pass a list of definitions to the task that launches the ec2 instances.
The new launch task looks like (notice the with_items):
`
- name: Launch image(s)
local_action:
module: ec2
region: “{{item.ec2_region}}”
zone: “{{item.ec2_zone}}”
instance_type: “{{item.ec2_instance_type}}”
image: “{{item.ec2_image}}”
key_name: “{{item.ec2_keypair}}”
exact_count: “{{item.ec2_exact_count}}”
group: “{{item.ec2_security_groups}}”
instance_tags: “{{item.ec2_tags}}”
count_tag: “{{item.ec2_tags}}”
vpc_subnet_id: “{{item.ec2_vpc_subnet_id}}”
instance_profile_name: “{{item.ec2_instance_profile_name}}”
wait: true
register: ec2
with_items: ec2_defs
`
The instances launch as expected, but problems arise when I try to use the registered result. The registered result (edited down a bit) looks like:
`
“ec2”: {
“changed”: true,
“msg”: “All items completed”,
“results”: [
{
“changed”: true,
“instance_ids”: [
“i-85170f6a”
],
“instances”: [
{
“ami_launch_index”: “0”,
“architecture”: “x86_64”,
“hypervisor”: “xen”,
“virtualization_type”: “paravirtual”
}
],
“invocation”: {
“module_args”: “”,
“module_name”: “ec2”
},
]
},
{
“changed”: true,
“instance_ids”: [
“i-9c18cf77”
],
“instances”: [
{
“ami_launch_index”: “0”,
“architecture”: “x86_64”,
“hypervisor”: “xen”,
}
],
“invocation”: {
“module_args”: “”,
“module_name”: “ec2”
},
}
]
}
`
I need to be able to iterate through all of the instances list in each of the results and I can’t seem to find a loop construct that will make this happen.
This seems like a fairly common pattern, but perhaps I’m starting in the wrong place or it’s just a known limitation. Any thoughts on a different approach?
Tim