2 min read · Dec 5, 2018
--
Most people think that ansible_default_ipv4
is some magical way to guess what IP address is the ‘main’ IP foraserver.
It is not.
It is the IP address which resides on interface where the default route points to. If you do ip route
command you can see something like that:
ip route
default via 192.168.1.1 dev wlp58s0 proto dhcp metric 600
wlp58s0
is ‘ansible_default_ipv4
’ just because it’s in ‘default
’ route.
If your server have no default route (f.e. it has full view, or it’s running in an isolated environment with no internet access at all), ansible_default_ipv4
is empty even if you can access to it through a specific route (and more importantly server have a specific route to get to you).
I learned it in a hard way when my playbooks failed badly with battle-proven roles, some which was heavily relied on ansible_default_ipv4
.
There is no easy solution for this problem, as you really need to think “what is the ‘main IP’ for my server” but there is a little hack which will cover about 99% of all cases (“no default ip” is already a 1% of all cases, so you are covering 99.99% of all possible situations with this):
ansible_default_ipv4.address|default(ansible_all_ipv4_addresses[0])
We use default_ipv4.address
if it’s available and falling to ‘fist available IP’ if it’s not. ansible_all_ipv4_addresses
contains all server IP addresses except for localhost.
This is example of facts for server with no default IPv4 address:
...
"ansible_default_ipv4": {},
"ansible_default_ipv6": {},
...
"ansible_all_ipv4_addresses": [
"10.160.0.158"
],
"ansible_all_ipv6_addresses": [
"fe80::f816:3eff:fea7:67be"
],
...
As you can see, we have only one private address there, so we’ll use it. If there is no ANY ip addresses, there is nothing to do.
If you have more than one IP address to choose from, I recommend to use ipaddr
jinja filter to match ip against a given ip net.