I’m using the following task to check if a host is reachable (after a reboot):
`
name: Wait for host to come back
wait_for:
host: ‘{{ ansible_host }}’
port: 22
state: started
delay: 30
timeout: 300
delegate_to: localhost
check_mode: False
`
This works fine for hosts that have ansible_host explicitly set, but for hosts that don’t set ansible_host it’s set to “localhost”. As far as I understand ansible_host is the correct variable to use in this situation. As it should contain the hostname or IP address where the host is reachable.
To clarify the issue, use the following example inventory:
`
host-a
host-b ansible_host=10.1.2.3
`
In this case, in the above task ansible_host is set to localhost for host-a but to 10.1.2.3 for host-b. This leads to wrong behavior as it would check port 22 on localhost for host-a. I could not find any variable that would contain the equivalent of ansible_host in a task without delegate_to for host-a.
Is this behavior expected or a bug in Ansible? Is there a variable I could use instead to get the connection target in case the task would be run without delegate_to? I’m currently using the following workaround, but this is really ugly and breaks if the Ansible behavior changes at some point in the future:
`
name: Wait for host to come back
wait_for:
ansible_host with delegate_to is weird. It’s set to localhost if it was not set explicitly before.
delegate_to is a tricky one and I’ve come across a few pitfalls. One thing to note is that delegate_to is meant to replace the connection vars for the host specified, in this case I would have expected ansible_host to be localhost in every instance.
What I would suggest is infinitely easier which is to use the wait_for_connection task like so;
`
name: wait for connection to come online
wait_for_connection:
delay: 30
timeout: 300
check_mode: False
`
The wait_for_connection plugin http://docs.ansible.com/ansible/latest/wait_for_connection_module.html was adding in Ansible 2.3 and is designed to get Ansible to continue to try and connect to the current host and run the ping module and wait until it succeeds. It’s better than wait_for as it not only checks if the port is online but also that Ansible can connect to the host before continuing.
delegate_to is a tricky one and I’ve come across a few pitfalls. One thing to note is that delegate_to is meant to replace the connection vars for the host specified, in this case I would have expected ansible_host to be localhost in every instance.
It would still be nice to have a way to access the “original value” of ansible_host then. And the behavior when setting ansible_host from the inventory is still questionable. This is what https://github.com/ansible/ansible/issues/30630 is about.
What I would suggest is infinitely easier which is to use the wait_for_connection task like so;
`
name: wait for connection to come online
wait_for_connection:
delay: 30
timeout: 300
check_mode: False
`
The wait_for_connection plugin http://docs.ansible.com/ansible/latest/wait_for_connection_module.html was adding in Ansible 2.3 and is designed to get Ansible to continue to try and connect to the current host and run the ping module and wait until it succeeds. It’s better than wait_for as it not only checks if the port is online but also that Ansible can connect to the host before continuing.
Thanks for the tip. I didn’t know about wait_for_connection. This is definitely a better match for my particular case.