# ansible\_host and delegate\_to behavior

**URL:** <https://forum.ansible.com/t/ansible-host-and-delegate-to-behavior/26337>\
**Category:** Ansible Project\
**Created:** [December 20, 2017, 10:55am UTC](https://forum.ansible.com/t/ansible-host-and-delegate-to-behavior/26337 "2017-12-20T10:55:21Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![gaudenz](https://avatars.discourse-cdn.com/v4/letter/g/4af34b/32.png) [@gaudenz](https://forum.ansible.com/u/gaudenz)\
**Post date:** [December 20, 2017, 10:55am UTC](https://forum.ansible.com/t/ansible-host-and-delegate-to-behavior/26337/1 "2017-12-20T10:55:21Z")

</div>

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.

host: ‘{{ (ansible\_host == “localhost”) | ternary(inventory\_hostname, ansible\_host) }}’  
port: 22  
state: started  
delay: 30  
timeout: 300  
delegate\_to: localhost  
check\_mode: False

`

I found these github issues wich might be related:

> <https://github.com/ansible/ansible/issues/30630>
>
> \##### ISSUE TYPE
> - Bug Report
> 
> \##### COMPONENT NAME
> core
> 
> \##### ANSIBLE V…ERSION
> \`\`\`
> ansible 2.3.2.0
> config file = /etc/ansible/ansible.cfg
> configured module search path = Default w/o overrides
> python version = 2.7.13 (default, Sep 5 2017, 08:53:59) \[GCC 7.1.1 20170622 (Red Hat 7.1.1-3)\]
> 
> \`\`\`
> 
> \##### OS / ENVIRONMENT
> Fedora release 26 (Twenty Six)
> 
> \##### SUMMARY
> The value for ansible\_host isn't properly set when delegate\_to is used and the inventory defines ansible\_host value for the host.
> 
> \##### STEPS TO REPRODUCE
> 
> I am using the following site.yml playbook:
> \`\`\`
> \---
> \- hosts: clients
> tasks:
> - name: test
> delegate\_to: server.example.com
> debug:
> var: ansible\_host
> \`\`\`
> 
> With the following inventory file:
> \`\`\`
> \[clients\]
> client.example.com
> 
> \[servers\]
> server.example.com
> \`\`\`
> The output is the following:
> \`\`\`
> TASK \[test\] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
> ok: \[client.example.com -\> server.example.com\] =\> {
> "ansible\_host": "server.example.com"
> }
> \`\`\`
> Now if I modify the inventory and add a ansible\_host value to the client machine:
> \`\`\`
> \[clients\]
> client.example.com ansible\_host=192.168.100.10
> 
> \[servers\]
> server.example.com
> \`\`\`
> The output changes to:
> \`\`\`
> TASK \[test\] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
> ok: \[client.example.com -\> server.example.com\] =\> {
> "ansible\_host": "192.168.100.10"
> }
> \`\`\`
> 
> We can see that in the first run, ansible\_host was pointing to the delegate\_to host, and in the 2nd run it is using the value for the inventory host instead. This behavior seems inconsistent.
> 
> \##### EXPECTED RESULTS
> I would expect the output to always show the value ansible\_host: server.example.com, as the doc 
> http://docs.ansible.com/ansible/latest/playbooks\_delegation.html states that "The ansible\_host variable (ansible\_ssh\_host in 1.x or specific to ssh/paramiko plugins) reflects the host a task is delegated to."

> <https://github.com/ansible/ansible/issues/14958>
>
> \##### Issue Type:
> 
> 
> \- Bug Report
> \##### Ansible Version:
> 
> \`\`\`
> ansible 2.0.1.0
> c…onfig file = /home/lars/src/tripleo-quickstart/ansible.cfg
> configured module search path = /usr/lib/python2.7/site-packages/tripleo-quickstart/playbooks/library:/home/lars/env/ansible-stable/usr/local/share/tripleo-quickstart/playbooks/library:playbooks/library
> 
> \`\`\`
> \##### Ansible Configuration:
> 
> 
> \##### Environment:
> 
> 
> \##### Summary:
> 
> When using \`delegate\_to: localhost\` on a task, if \`ansible\_host\` is set explicitly then that value is used in the delegated task, but if \`ansible\_host\` is \_not\_ set explicitly it will be \`localhost\`. This should always reflect the value for the original host, and thus should be \_unset\_ if there is no explicit value.
> \##### Steps To Reproduce:
> 
> \`\`\`
> \- hosts: remotehost
> tasks:
> - delegate\_to: localhost
> debug:
> var: ansible\_host
> 
> \`\`\`
> 
> Run the above with:
> 
> \`\`\`
> ansible-playbook -i remotehost, playbook.yml
> \`\`\`
> \##### Expected Results:
> 
> I expected \`ansible\_host\` to be undefined.
> \##### Actual Results:
> 
> \`\`\`
> TASK \[debug\] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
> Monday 14 March 2016 09:42:07 -0400 (0:00:00.078) 0:00:01.906 \*\*\*\*\*\*\*\*\*\* 
> ok: \[madhatter -\> localhost\] =\> {
> "ansible\_host": "localhost"
> }
> \`\`\`

Regards,  
Gaudenz

---

<div class="post-metadata">

**Author:** ![jborean](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jborean/32/1525_2.png) [@jborean](https://forum.ansible.com/u/jborean)\
**Post date:** [December 20, 2017, 11:14am UTC](https://forum.ansible.com/t/ansible-host-and-delegate-to-behavior/26337/2 "2017-12-20T11:14:50Z")

</div>

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](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

Jordan

---

<div class="post-metadata">

**Author:** ![gaudenz](https://avatars.discourse-cdn.com/v4/letter/g/4af34b/32.png) [@gaudenz](https://forum.ansible.com/u/gaudenz)\
**Post date:** [December 20, 2017, 12:54pm UTC](https://forum.ansible.com/t/ansible-host-and-delegate-to-behavior/26337/3 "2017-12-20T12:54:07Z")

</div>

> 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](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](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.

Regards;  
Gaudenz
