Closed jr64 closed 1 year ago
Build failed. https://ansible.softwarefactory-project.io/zuul/buildset/59c9cd83fd3b4645b153962cf41083e1
:x: ansible-test-cloud-integration-vmware-rest NODE_FAILURE Node request 200-0006230140 failed in 0s :heavy_check_mark: build-ansible-collection SUCCESS in 10m 49s :heavy_check_mark: ansible-test-splitter SUCCESS in 4m 45s :heavy_check_mark: integration-kubernetes.core-with-turbo-1 SUCCESS in 19m 00s :heavy_check_mark: integration-kubernetes.core-with-turbo-2 SUCCESS in 27m 19s :heavy_check_mark: integration-kubernetes.core-with-turbo-3 SUCCESS in 35m 29s :heavy_check_mark: ansible-galaxy-importer SUCCESS in 5m 08s
@jr64 Could you try https://github.com/ansible-collections/cloud.common/pull/130 to see if that fixes the problem you're having?
@gravesm I can confirm #130 also addresses my issue. Thank you, I'm closing this pull request.
SUMMARY
This pull request fixes a problem in the turbo server where lookup plugins are not loaded correctly if Ansible's collection_finder is not initialized yet.
I encountered this bug when trying to deploy VMs with the
vmware.vmware_rest
collection which usescloud.common
to speed up operations. See ansible-collections/vmware.vmware_rest#421 for a bug report by another uses who experienced the same issue.ISSUE TYPE
COMPONENT NAME
ADDITIONAL INFORMATION
Reproducing the bug:
Environment:
Create a test collection with the following minimal lookup plugin:
Test playbook:
When running, this will fail with the following error message:
Root cause
The problem is in the function
run_as_lookup_plugin
in server.py:https://github.com/ansible-collections/cloud.common/blob/6036c79da7d824918b3872db49ce09adb02ba945/plugins/module_utils/turbo/server.py#L248C1-L250C10
instance
will beNone
if the _AnsibleCollectionFinder is not initialized. I'm not an expert on Ansible internals but from what I have gathered, calling_install()
will install hooks forimportlib.import_module
to be able to load Python code from folders that do not contain a__init__.py
.See: https://github.com/ansible/ansible/blob/a5ccc0124f4677eb55a90a1e2e53b6984b2b140d/lib/ansible/utils/collection_loader/_collection_finder.py#L294C1-L300C57
If AnsibleCollectionFinder hooks are enabled,
import_module
will return the following object (note that the path ends in__synthetic__
instead of__init__.py
):Without the hooks,
import_module
will return a namespace instead because normally, Python 3 treats folders without__init__.py
as namespaces.To understand exactly what happens, we have to dig into the Ansible plugin_loader:
https://github.com/ansible/ansible/blob/a5ccc0124f4677eb55a90a1e2e53b6984b2b140d/lib/ansible/plugins/loader.py#L854C1-L865C99
plugin_loader.lookup_loader.get()
callsget_with_context
which in turn callsfind_plugin_with_context
which calls_resolve_plugin_step
which calls_find_fq_plugin
https://github.com/ansible/ansible/blob/a5ccc0124f4677eb55a90a1e2e53b6984b2b140d/lib/ansible/plugins/loader.py#L535C1-L543C49Here,
sys.modules.get
is called which returns a namespace if the hooks are not installed. The path is then set topkg.__file__
which isNone
for a namespace, causing the loading of the lookup plugin to fail.