I recently added a table of host names mapped to IP addresses to my environment, because I needed this anyway to configure my DHCP server. I thought it was a nice idea to use this table as the Source of Truth™ for my playbooks. I introduced a variable expression for ansible_host which would look up the IP address in this table. This seemed to work nicely … until I started using delegate_to.
Here’s a test:
inventory.yml
all:
hosts:
zeus:
# ansible_host: 192.168.1.20
ansible_ssh_user: martin
ananas:
# ansible_host: 192.168.1.167
ansible_ssh_user: p464v2
vars:
ip_addrs:
zeus: 192.168.1.20
ananas: 192.168.1.167
ansible_host: "{{ ip_addrs[inventory_hostname] }}"
delegate-test.yml
- name: Test delegate_to with computed ansible_host
hosts: zeus,ananas
gather_facts: true
become: false
tasks:
- name: Print host and user
debug:
msg: "Host: {{ ansible_host }}, User: {{ ansible_ssh_user }}"
- name: Print host and user with delegate_to
debug:
msg: "Host: {{ ansible_host }}, User: {{ ansible_ssh_user }}"
delegate_to: ananas
when: inventory_hostname == 'zeus'
- name: Check connectivity
ping:
- name: Check connectivity with delegate_to
ping:
delegate_to: ananas
when: inventory_hostname == 'zeus'
The output of this playbook is:
> ansible-playbook -i inventory.yml delegate-test.yml
PLAY [Test delegate] ********************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************
ok: [zeus]
ok: [ananas]
TASK [Print host and user] **************************************************************************************************
ok: [zeus] => {
"msg": "Host: 192.168.1.20, User: martin"
}
ok: [ananas] => {
"msg": "Host: 192.168.1.167, User: p464v2"
}
TASK [Print host and user with delegate_to] *********************************************************************************
ok: [zeus -> ananas({{ ip_addrs[inventory_hostname] }})] => {
"msg": "Host: 192.168.1.20, User: martin"
}
skipping: [ananas]
TASK [Check connectivity] ***************************************************************************************************
ok: [zeus]
ok: [ananas]
TASK [Check connectivity with delegate_to] **********************************************************************************
skipping: [ananas]
fatal: [zeus -> ananas]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Received disconnect from 192.168.1.20 port 22:2: Too many authentication failures\r\nDisconnected from 192.168.1.20 port 22", "unreachable": true}
PLAY RECAP ******************************************************************************************************************
ananas : ok=3 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
zeus : ok=4 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
In the last task with delegate_to, ansible is using the IP address of host zeus when connecting to ananas.
If I uncomment the constant expressions for ansible_host in the inventory.yml file, the playbook succeeds.
Is this a bug? Or is it generally not supported to use a variable for ansible_host?