Opened 3 years ago
Last modified 3 years ago
#63263 assigned defect
py-ansible-base 2.10.11: Path replacement breaks custom facts — at Initial Version
Reported by: | F30 (Felix Dreissig) | Owned by: | |
---|---|---|---|
Priority: | Normal | Milestone: | |
Component: | ports | Version: | |
Keywords: | Cc: | adfernandes (Andrew Fernandes), steenzout (Pedro Salgado) | |
Port: | py-ansible-base |
Description
Problem:
Local custom facts do not get picked up from "/etc/ansible/facts.d" if Ansible was installed via MacPorts.
To reproduce, place a JSON or INI file into "/etc/ansible/facts.d" on the remote host, e.g. "/etc/ansible/facts.d/demo.fact":
{ "foo": "bar" }
Then, try to read these facts by running something like ansible -m ansible.builtin.setup -a 'filter=ansible_local'
. The output will not contain the custom fact.
Alternatively, try accessing ansible_local['demo']['foo']
from a playbook. That will cause Ansible to crash:
fatal: [<snip>]: FAILED! => msg: |- The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'demo'
Cause:
The py-ansible-base Portfile does a global replacement of all "/etc/ansible" paths to "/opt/local/etc/ansible". This is valid for local paths of the machine running Ansible. However, it does not take into account that the Ansible code also contains paths relevant for remote hosts, which may have nothing to do with MacPorts.
The Ansible docs clearly state a default fact path of "/etc/ansible/facts.d" and (at least for me) it is very unexpected that MacPorts changes that.
This is a fundamental problem and might affect other places besides facts. The following files from the Ansible repository are currently edited by the path replacement:
examples/hosts.yaml examples/scripts/uptime.py lib/ansible/config/base.yml lib/ansible/config/manager.py lib/ansible/inventory/manager.py lib/ansible/module_utils/urls.py lib/ansible/modules/setup.py lib/ansible/plugins/loader.py test/integration/targets/ansible-galaxy/cleanup.yml test/integration/targets/gathering/implicit.yml test/integration/targets/gathering/smart.yml test/integration/targets/gathering_facts/test_gathering_facts.yml test/integration/targets/gathering_facts/test_run_once.yml test/units/cli/galaxy/test_execute_list_collection.py test/units/config/manager/test_find_ini_config_file.py test/units/executor/test_play_iterator.py test/units/playbook/role/test_include_role.py test/units/playbook/role/test_role.py test/units/playbook/test_included_file.py test/units/playbook/test_play.py test/units/vars/test_variable_manager.py
I suppose we can ignore everything under "examples" and "test". This leaves 30 changed lines across 6 files under "lib". Most of these affect the default paths of plugins, collections, roles and similar. These really are relevant for the local machine only.
In fact, the default fact_path
from "lib/ansible/modules/setup.py" is the only remote path I could cursorily identify. Of course, it does not need to stay like that in future versions.
Cause:
The default fact path may get adjusted by setting the ANSIBLE_FACT_PATH
environment variable or adding [defaults]
/fact_path
to an Ansible config file.
However, as stated by the Ansible docs, this only works for implicit fact gathering (i.e. the playbook example from above). Explicit calls to ansible.builtin.setup
(such as the non-playbook example above) will always use the built-in default or the path directly specified from the call.