# Dynamically set /etc/hosts using ansible\_interfaces

**URL:** <https://forum.ansible.com/t/dynamically-set-etc-hosts-using-ansible-interfaces/20386>\
**Category:** Ansible Project\
**Created:** [January 29, 2016, 3:33pm UTC](https://forum.ansible.com/t/dynamically-set-etc-hosts-using-ansible-interfaces/20386 "2016-01-29T15:33:53Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dayton\_Jones](https://avatars.discourse-cdn.com/v4/letter/d/22d042/32.png) [@Dayton\_Jones](https://forum.ansible.com/u/Dayton_Jones)\
**Post date:** [January 29, 2016, 3:33pm UTC](https://forum.ansible.com/t/dynamically-set-etc-hosts-using-ansible-interfaces/20386/1 "2016-01-29T15:33:53Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [January 29, 2016, 5:23pm UTC](https://forum.ansible.com/t/dynamically-set-etc-hosts-using-ansible-interfaces/20386/2 "2016-01-29T17:23:47Z")

</div>

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'] }} ...

---

<div class="post-metadata">

**Author:** ![Dayton\_Jones](https://avatars.discourse-cdn.com/v4/letter/d/22d042/32.png) [@Dayton\_Jones](https://forum.ansible.com/u/Dayton_Jones)\
**Post date:** [January 29, 2016, 5:36pm UTC](https://forum.ansible.com/t/dynamically-set-etc-hosts-using-ansible-interfaces/20386/3 "2016-01-29T17:36:47Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [January 29, 2016, 8:17pm UTC](https://forum.ansible.com/t/dynamically-set-etc-hosts-using-ansible-interfaces/20386/4 "2016-01-29T20:17:37Z")

</div>

cannot have . inside

hostvars[inventory\_hostname]['ansible\_' + interface]['ipv4.address']

---

<div class="post-metadata">

**Author:** ![Dayton\_Jones](https://avatars.discourse-cdn.com/v4/letter/d/22d042/32.png) [@Dayton\_Jones](https://forum.ansible.com/u/Dayton_Jones)\
**Post date:** [January 29, 2016, 8:30pm UTC](https://forum.ansible.com/t/dynamically-set-etc-hosts-using-ansible-interfaces/20386/5 "2016-01-29T20:30:59Z")

</div>

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…

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [January 29, 2016, 9:40pm UTC](https://forum.ansible.com/t/dynamically-set-etc-hosts-using-ansible-interfaces/20386/6 "2016-01-29T21:40:16Z")

</div>

missed a dot ['ipv4.address'] =\> ['ipv4']['address']

---

<div class="post-metadata">

**Author:** ![Dayton\_Jones](https://avatars.discourse-cdn.com/v4/letter/d/22d042/32.png) [@Dayton\_Jones](https://forum.ansible.com/u/Dayton_Jones)\
**Post date:** [January 29, 2016, 9:49pm UTC](https://forum.ansible.com/t/dynamically-set-etc-hosts-using-ansible-interfaces/20386/7 "2016-01-29T21:49:35Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Dayton\_Jones](https://avatars.discourse-cdn.com/v4/letter/d/22d042/32.png) [@Dayton\_Jones](https://forum.ansible.com/u/Dayton_Jones)\
**Post date:** [February 1, 2016, 2:47pm UTC](https://forum.ansible.com/t/dynamically-set-etc-hosts-using-ansible-interfaces/20386/8 "2016-02-01T14:47:58Z")

</div>

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](http://hostname.mydomain.com) hostname  
2.3.4.5 [hostname-alt.otherdomain.com](http://hostname-alt.otherdomain.com) hostname-alt

This of course assumes that DNS has been properly set beforehand…

---

<div class="post-metadata">

**Author:** ![Giovanni\_Tommasini](https://avatars.discourse-cdn.com/v4/letter/g/da6949/32.png) [@Giovanni\_Tommasini](https://forum.ansible.com/u/Giovanni_Tommasini)\
**Post date:** [February 14, 2018, 9:51am UTC](https://forum.ansible.com/t/dynamically-set-etc-hosts-using-ansible-interfaces/20386/9 "2018-02-14T09:51:49Z")

</div>

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](http://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](http://hostname.domain.com)  
1.2.3.4 hostname [hostname.domain.com](http://hostname.domain.com)

thanks
