I am trying to look up the IPv4 address (a single one, which I will assert
on!) for a given name using Ansible and use that as a fact "down the line".
An MWE looks like this:
---
# vim: set autoindent smartindent tabstop=2 shiftwidth=2 softtabstop=2 expandtab filetype=ansible:
- name: Preparations
hosts: localhost
connection: local
vars:
host2lookup: "example.com"
tasks:
- getent:
database: ahostsv4
key: "{{host2lookup}}"
- debug:
var: getent_ahostsv4
- name: Lookup for {{host2lookup}}
debug:
msg: "{{lookup('dig', '{{host2lookup}}./A')}}"
... and fails as follows (relevant excerpt):
localhost failed | msg: An unhandled exception occurred while running the lookup plugin 'dig'. Error was a <class 'ansible.errors.AnsibleError'>, original message: The dig lookup requires the python 'dnspython' library and it is not installed
So I thought to myself I'd install the dnspython
library for the appropriate Python version, making the playbook look as follows:
---
# vim: set autoindent smartindent tabstop=2 shiftwidth=2 softtabstop=2 expandtab filetype=ansible:
- name: Preparing Ansible host
hosts: localhost
connection: local
tasks:
- name: Install dnspython package on Ansible host
block:
- name: Installing python-dnspython package
apt:
pkg:
- python-dnspython
update_cache: yes
install_recommends: no
state: present
when: ansible_python.version.major == 2
- name: Installing python3-dnspython package
apt:
pkg:
- python3-dnspython
update_cache: yes
install_recommends: no
state: present
when: ansible_python.version.major == 3
become: true
- name: Preparations
hosts: localhost
connection: local
vars:
host2lookup: "example.com"
tasks:
- getent:
database: ahostsv4
key: "{{host2lookup}}"
- debug:
var: getent_ahostsv4
- name: Lookup for {{host2lookup}}
debug:
msg: "{{lookup('dig', '{{host2lookup}}./A')}}"
But the ultimate failure remains the same. Either that error is misleading or something else is fishy ...
Executing playbook dbg.yml
- Preparing Ansible host on hosts: localhost -
Gathering Facts...
localhost ok
Installing python-dnspython package...
Installing python3-dnspython package...
localhost ok
- Preparations on hosts: localhost -
Gathering Facts...
localhost ok
getent...
localhost ok
debug...
localhost ok: {
"changed": false,
"getent_ahostsv4": {
"93.184.216.34": [
"RAW"
]
}
}
Lookup for example.com...
localhost failed | msg: An unhandled exception occurred while running the lookup plugin 'dig'. Error was a <class 'ansible.errors.AnsibleError'>, original message: The dig lookup requires the python 'dnspython' library and it is not installed
- Play recap -
localhost : ok=5 changed=0 unreachable=0 failed=1 rescued=0 ignored=0
What other than the appropriate dnspython
package am I missing here?
The dnsutils
package (containing dig
) and its library dependencies is installed. Adding these as prerequisites into the apt:
task therefore makes no difference.
Found another smoking gun, though:
$ python3 -m dnspython
/usr/bin/python3: No module named dnspython
$ sudo -H pip3 install dnspython
Requirement already satisfied: dnspython in /usr/lib/python3/dist-packages
I stand corrected. As per the examples page I should import something like dns.query
(python3 -m dns.query
). And that succeeds.
My ansible.cfg
is this:
$ cat ansible.cfg
[defaults]
nocows = true
command_warnings = false
stdout_callback = unixy
display_skipped_hosts = false
interpreter_python=auto
The whole thing runs on Ubuntu 18.04.
As per request in a comment, I am providing more output. This is still on Ubuntu 18.04. With the (above shown) ansible.cfg
in place, I get the following output:
$ ansible localhost -m setup -a 'filter=ansible_python*'
localhost | SUCCESS => {
"ansible_facts": {
"ansible_python": {
"executable": "/usr/bin/python2",
"has_sslcontext": true,
"type": "CPython",
"version": {
"major": 2,
"micro": 17,
"minor": 7,
"releaselevel": "final",
"serial": 0
},
"version_info": [
2,
7,
17,
"final",
0
]
},
"ansible_python_version": "2.7.17"
},
"changed": false
}
However, ansible-playbook
behaves differently here. Consider the following playbook:
---
- hosts: all
tasks:
- debug:
var: ansible_python
- debug:
var: ansible_python_version
The output becomes:
$ ansible-playbook -i localhost, -c local dbg.yml
Executing playbook dbg.yml
- all on hosts: all -
Gathering Facts...
localhost ok
debug...
localhost ok: {
"ansible_python": {
"executable": "/usr/bin/python3",
"has_sslcontext": true,
"type": "cpython",
"version": {
"major": 3,
"micro": 9,
"minor": 6,
"releaselevel": "final",
"serial": 0
},
"version_info": [
3,
6,
9,
"final",
0
]
},
"changed": false
}
debug...
localhost ok: {
"ansible_python_version": "3.6.9",
"changed": false
}
- Play recap -
localhost : ok=3 changed=0 unreachable=0 failed=0 rescued=0 ignored=0
... comment out the following line from ansible.cfg
:
interpreter_python=auto
... and the output (when rerunning the previous command) becomes:
$ ansible-playbook -i localhost, -c local dbg.yml
Executing playbook dbg.yml
- all on hosts: all -
Gathering Facts...
localhost ok
debug...
localhost ok: {
"ansible_python": {
"executable": "/usr/bin/python",
"has_sslcontext": true,
"type": "CPython",
"version": {
"major": 2,
"micro": 17,
"minor": 7,
"releaselevel": "final",
"serial": 0
},
"version_info": [
2,
7,
17,
"final",
0
]
},
"changed": false
}
debug...
localhost ok: {
"ansible_python_version": "2.7.17",
"changed": false
}
- Play recap -
localhost : ok=3 changed=0 unreachable=0 failed=0 rescued=0 ignored=0
Nothing in the documentation suggests that this should happen.
ansible localhost -m setup | grep ansible_python_version
ansible
command line tool have to do with behavior I see withansible-playbook
? I will amend the question shortly. You'll notice that the two tools behave differently in this exact case. No clue why, but it can be reproduced.-hosts: localhost
, but you used- hosts: all
. This is reallylittle more
.ansible localhost -m setup -a 'filter=ansible_python*'
(other than using a filter instead ofgrep
) lacks the requested information? Your request was for output fromansible
and I pointed out the discrepancy with that ofansible-playbook
based on theinterpreter_python=auto
setting.