Reputation: 8758
Given this inventory:
[webservers]
10.0.0.51 private_ip='X.X.X.X'
10.0.0.52 private_ip='Y.Y.Y.Y'
10.0.0.53 private_ip='Z.Z.Z.Z'
How can I get a list of the private ips of the webservers?
webservers_private_ips: "{{ }}" # ['X.X.X.X', 'Y.Y.Y.Y', 'Z.Z.Z.Z']
I know groups['webservers']
will give me this list ['10.0.0.51', '10.0.0.52', '10.0.0.53']
and I can get the private_ip of one with:
{{ hostvars[item]['private_ip'] }}
with_items: groups['webservers']
But I would like to declare a variable in my var file directly and not have a task to register it. It would be nice if something like the following could be done:
webservers_private_ips: "{{ hostvars[item]['private_ip'] }} for item in groups['webservers']"
Upvotes: 15
Views: 12319
Reputation: 121
You can take advantage of the extract filter to get components of a composite data object:
webservers_private_ips: "{{ groups['webservers']|map('extract', hostvars, 'private_ip')|list }}"
The extract filter is used to map from a list of indices to a list of values from a container (hash or array).
Upvotes: 12
Reputation: 9066
As of Ansible 2.2 you can use the json_query
filter.
In your example it looks like:
- debug:
msg: "{{item}}"
loop: "{{hostvars | json_query(query)}}"
vars:
query: "* | [?contains(group_names, `webservers`)].private_ip"
"hostvars" is a hash of hostname (e.g. 10.0.0.51) to its respective variables. Filters cannot be applied to hashes (see this answer), so we need to retrieve a list of hostvar objects with "*". The resulting list of hostvars is filtered for hosts that are in the group "webservers". For all matching hashes, the query returns the value of "private_ip".
Docs: http://docs.ansible.com/ansible/latest/playbooks_filters.html#json-query-filter
Upvotes: 0
Reputation: 18269
It depends on the context.
if you want to loops over private_ip
variable in a task, you can do it like so :
- hosts: all
tasks:
- name: Print private_ips
debug: var={{ hostvars[item]['private_ip'] }}
with_items:
- "{{ groups['webservers'] }}"
Note that this will print the IPs 3 times, since it will run on each server, so depending on what you're trying to achieve, you'll have to set hosts: all
to your frontend server or whatever.
You can also do this in a Jinja2 file if you plan to generate some config file. Again, it all depends on what you're aiming for.
Note that you can access IP information in facts gathered automatically by ansible :
$ ansible someserver -m setup
....
"ansible_eth1": {
"active": true,
"device": "eth1",
"ipv4": {
"address": "192.168.252.6",
"netmask": "255.255.255.255",
"network": "192.168.252.6"
},
"mtu": 1500,
"promisc": false
},
....
which might also be more suitable, depending what you're trying to do.
Good luck.
Upvotes: -2