I’m trying to dynamically set /etc/hosts based on the ipv4 address assigned to all the interfaces on a host… my template reads as such
127.0.0.1 localhost.localdomain localhost
{% for item in ansible_interfaces if item != ‘lo’ %}
{{ ‘ansible_’ + item + ‘.ipv4.address’ }} {{ lookup(‘dig’, ‘ansible_’ + item + ‘.ipv4.address’ + ‘/PTR’) }}
{% endfor %}
which results in :
127.0.0.1 localhost.localdomain localhost
ansible_eth1.ipv4.address NXDOMAIN
ansible_eth0.ipv4.address NXDOMAIN
I’ve tried several iterations, but I’m struggling to find the proper syntax to get the file to write as expected… is this possible? Any suggestions greatly appreciated.
Brian_Coca
(Brian Coca)
January 29, 2016, 5:23pm
2
You seem to expect that the resulting string of {{ 'ansible_' + item +
'.ipv4.address' }} will then be 'retemplated', that won't happen
Also, don't use 'item' as that is reserved for ansible loops, the
following is the say to 'dynamically' access host facts:
{% for interface in ansible_interfaces if item != 'lo' %}
{{ hostvars[inventory_hostname]['ansible_' + interface+ '.ipv4.address'] }} ...
Changing to this format results in:
FAILED! => {“changed”: false, “failed”: true, “msg”: “AnsibleUndefinedVariable: ‘dict object’ has no attribute u’ansible_eth1.ipv4.address’”}
yet if I check ansible_eth1 I see:
{u’macaddress’: u’00:21:f6:f2:c1:21’, u’pciid’: u’vif-0’, u’module’: u’xen_netfront’, u’mtu’: 1500, u’device’: u’eth1’, u’promisc’: False, u’ipv4’: {u’broadcast’: u’10.224.103.255’, u’netmask’: u’255.255.248.0’, u’network’: u’10.224.96.0’, u’address’: u’10.224.97.202’}, u’active’: True, u’type’: u’ether’}
So the current template looks like this:
{% for interface in ansible_interfaces if interface != ‘lo’ %}
{{ hostvars[inventory_hostname][‘ansible_’ + interface + ‘.ipv4.address’] }} {{ lookup(‘dig’, hostvars[inventory_hostname][‘ansible_’ + interface + ‘.ipv4.address’] + ‘/PTR’) }}
{% endfor %}
I can’t see anything wrong here, and the address is there and available…any other thoughts?
Brian_Coca
(Brian Coca)
January 29, 2016, 8:17pm
4
cannot have . inside
hostvars[inventory_hostname]['ansible_' + interface]['ipv4.address']
Ah…that makes sense, but unfortunately it still doesn’t work for me…
template:
{% for interface in ansible_interfaces if interface != ‘lo’ %}
{{ hostvars[inventory_hostname][‘ansible_’ + interface][‘ipv4.address’] }} {{ lookup(‘dig’, hostvars[inventory_hostname][‘ansible_’ + interface][‘ipv4.address’] + ‘/PTR’) }}
{% endfor %}
results of ansible-playbook run:
FAILED! => {“changed”: false, “failed”: true, “msg”: “AnsibleUndefinedVariable: ‘dict object’ has no attribute ‘ipv4.address’”}
Thanks for the quick replies…
Brian_Coca
(Brian Coca)
January 29, 2016, 9:40pm
6
missed a dot ['ipv4.address'] => ['ipv4']['address']
Ah…perfect…thanks! Yes, that works - although it does have a trailing ‘.’ at the end of the line and blank lines between the entries, which I’ll have to figure out how to strip.
Thanks again
Final solution:
{% for interface in ansible_interfaces if interface != ‘lo’ %}{{ hostvars[inventory_hostname][‘ansible_’ + interface][‘ipv4’][‘address’] }} {{ lookup(‘dig’, hostvars[inventory_hostname][‘ansible_’ + interface][‘ipv4’][‘address’] + ‘/PTR’).rstrip(‘.’) }} {{ lookup(‘dig’, hostvars[inventory_hostname][‘ansible_’ + interface][‘ipv4’][‘address’] + ‘/PTR’).split(‘.’)[0] }}
{% endfor %}
results in :
1.2.3.4 hostname.mydomain.com hostname
2.3.4.5 hostname-alt.otherdomain.com hostname-alt
This of course assumes that DNS has been properly set beforehand…
Thanks Dayton for you final solution.
If I use it, I notice that the privat IP wasn’t set correctly; like this:
192.168.1.1
1.2.3.4 hostname hostname.domain.com
So I use this solution
{% for interface in ansible_interfaces if interface != ‘lo’ %}
{{ hostvars[inventory_hostname][‘ansible_’ + interface][‘ipv4’][‘address’] }} {{ inventory_hostname_short }} {{ inventory_hostname }}
{% endfor %}
and now it’s ok for me
192.168.1.1 hostname hostname.domain.com
1.2.3.4 hostname hostname.domain.com
thanks