I have a playbook for creating some EC2 instances and then doing some stuff with them. The relevant pieces are approximately like:
- name: create ec2 instances
ec2:
id: '{{ item.name }}'
instance_type: '{{ item.type }}'
register: ec2
with_items: '{{ my_instance_defs }}'
- name: wait for SSH
wait_for:
host: '{{ item.instances[0].private_ip }}'
port: 22
with_items: '{{ ec2.results }}'
This works as intended, but I am not especially happy with the item.instances[0].private_ip
expression, partly because it shows really large objects in the play summary. I would love to have the with_items
part just be an array of IP addresses, rather than an array of objects with arrays of objects inside them. In Python, I would just do something like:
ips = [r['instances'][0]['private_ip'] for r in ec2['results']]
And then I would use with_items: '{{ ips }}'
in the second task.
Is there a way I can do the same thing using a J2 filter in the YAML of the play? Seems like http://docs.ansible.com/ansible/playbooks_filters.html#extracting-values-from-containers might be helpful, but I think that presupposes I have an array of keys/indices/whatever.
map filter is your friend here.
Something like this:
with_items: "{{ ec2.results | map(attribute='instances') | map('first') | map(attribute='private_ip') | list }}"
The code above is not tested.
You may want to try with debug
first and gradually add additional map
filters to get required result.
Don't forget to put | list
at the end to make your map readable.