Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use Jinja2 `map` filter in an Ansible play to get values from an array of objects?

Tags:

ansible

jinja2

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.

like image 831
amacleod Avatar asked Dec 22 '16 15:12

amacleod


People also ask

Which filter is used to provide default values to variables Ansible?

So if you want to define a default value for a variable you should set it in role/defaults/main. yml . Ansible will use that value only if the variable is not defined somewhere else. Using the Jina2 filters is it possible to do something like {{ variable | default(other_variable) }} ?

What is map in Ansible?

the map is actually a Jinja2 filter and more information can be found per the Jinja2 official documentation: map() Applies a filter on a sequence of objects or looks up an attribute. This is useful when dealing with lists of objects but you are really only interested in a certain value of it.

How can I manipulate data in Jinja2 using Ansible?

You can use the Ansible-specific filters documented here to manipulate your data, or use any of the standard filters shipped with Jinja2 - see the list of built-in filters in the official Jinja2 template documentation. You can also use Python methods to transform data.

What are the use cases of Ansible map function or filter?

In this article, we are going to see the various use cases of Ansible Map Function or Filter. As Ansible Official documentation claims, All Jinja2 Filters can be used within Ansible. It helps us to filter and iterate complex datasets and a list of objects.

What are jinaj2 filters in Ansible?

The Jinaj2 filters are a very powerful feature and could help us in various tasks for the manipulation with the data. You are welcome to find more filters in the ansible documentation.

How to combine two lists into one in Ansible?

use just “+” operator to combine two lists into one, like: "{{ ansible_interfaces + ["VETH-1", "VETH-2"] }}" check here for more advanced example: Advanced list operations in Ansible; Ansible filters and lists operators. Ansible provides a rich set of filters, which you can apply to your variables. Recently, I needed to filter and map a ...


1 Answers

map filter it 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 maps to get required result.
Don't forget to put | list at the end to make your map readable.

like image 137
Konstantin Suvorov Avatar answered Sep 28 '22 03:09

Konstantin Suvorov