patch ansible-connection collection plugin loading (#59119)
This commit is contained in:
parent
d4dec59cb0
commit
d28f25d118
4 changed files with 17 additions and 7 deletions
2
changelogs/fragments/ac_collection_plugin_load.yml
Normal file
2
changelogs/fragments/ac_collection_plugin_load.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
bugfixes:
|
||||||
|
- fixed collection-based plugin loading in ansible-connection (eg networking plugins)
|
|
@ -26,6 +26,7 @@ from ansible.playbook.conditional import Conditional
|
||||||
from ansible.playbook.task import Task
|
from ansible.playbook.task import Task
|
||||||
from ansible.plugins.loader import become_loader, cliconf_loader, connection_loader, httpapi_loader, netconf_loader, terminal_loader
|
from ansible.plugins.loader import become_loader, cliconf_loader, connection_loader, httpapi_loader, netconf_loader, terminal_loader
|
||||||
from ansible.template import Templar
|
from ansible.template import Templar
|
||||||
|
from ansible.utils.collection_loader import AnsibleCollectionLoader
|
||||||
from ansible.utils.listify import listify_lookup_plugin_terms
|
from ansible.utils.listify import listify_lookup_plugin_terms
|
||||||
from ansible.utils.unsafe_proxy import UnsafeProxy, wrap_var
|
from ansible.utils.unsafe_proxy import UnsafeProxy, wrap_var
|
||||||
from ansible.vars.clean import namespace_facts, clean_facts
|
from ansible.vars.clean import namespace_facts, clean_facts
|
||||||
|
@ -1054,8 +1055,13 @@ def start_connection(play_context, variables):
|
||||||
|
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env.update({
|
env.update({
|
||||||
|
# HACK; most of these paths may change during the controller's lifetime
|
||||||
|
# (eg, due to late dynamic role includes, multi-playbook execution), without a way
|
||||||
|
# to invalidate/update, ansible-connection won't always see the same plugins the controller
|
||||||
|
# can.
|
||||||
'ANSIBLE_BECOME_PLUGINS': become_loader.print_paths(),
|
'ANSIBLE_BECOME_PLUGINS': become_loader.print_paths(),
|
||||||
'ANSIBLE_CLICONF_PLUGINS': cliconf_loader.print_paths(),
|
'ANSIBLE_CLICONF_PLUGINS': cliconf_loader.print_paths(),
|
||||||
|
'ANSIBLE_COLLECTIONS_PATHS': os.pathsep.join(AnsibleCollectionLoader().n_collection_paths),
|
||||||
'ANSIBLE_CONNECTION_PLUGINS': connection_loader.print_paths(),
|
'ANSIBLE_CONNECTION_PLUGINS': connection_loader.print_paths(),
|
||||||
'ANSIBLE_HTTPAPI_PLUGINS': httpapi_loader.print_paths(),
|
'ANSIBLE_HTTPAPI_PLUGINS': httpapi_loader.print_paths(),
|
||||||
'ANSIBLE_NETCONF_PLUGINS': netconf_loader.print_paths(),
|
'ANSIBLE_NETCONF_PLUGINS': netconf_loader.print_paths(),
|
||||||
|
|
|
@ -13,7 +13,8 @@ from types import ModuleType
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.module_utils._text import to_bytes, to_native, to_text
|
from ansible.module_utils._text import to_bytes, to_native, to_text
|
||||||
from ansible.module_utils.six import iteritems, string_types
|
from ansible.module_utils.six import iteritems, string_types, with_metaclass
|
||||||
|
from ansible.utils.singleton import Singleton
|
||||||
|
|
||||||
# HACK: keep Python 2.6 controller tests happy in CI until they're properly split
|
# HACK: keep Python 2.6 controller tests happy in CI until they're properly split
|
||||||
try:
|
try:
|
||||||
|
@ -34,7 +35,7 @@ _collection_qualified_re = re.compile(to_text(r'^(\w+)\.(\w+)\.(\w+)$'))
|
||||||
|
|
||||||
|
|
||||||
# FIXME: exception handling/error logging
|
# FIXME: exception handling/error logging
|
||||||
class AnsibleCollectionLoader(object):
|
class AnsibleCollectionLoader(with_metaclass(Singleton, object)):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._n_configured_paths = C.config.get_config_value('COLLECTIONS_PATHS')
|
self._n_configured_paths = C.config.get_config_value('COLLECTIONS_PATHS')
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ class AnsibleCollectionLoader(object):
|
||||||
sys.modules[pkg_name] = newmod
|
sys.modules[pkg_name] = newmod
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _n_collection_paths(self):
|
def n_collection_paths(self):
|
||||||
return self._n_playbook_paths + self._n_configured_paths
|
return self._n_playbook_paths + self._n_configured_paths
|
||||||
|
|
||||||
def set_playbook_paths(self, b_playbook_paths):
|
def set_playbook_paths(self, b_playbook_paths):
|
||||||
|
@ -145,7 +146,7 @@ class AnsibleCollectionLoader(object):
|
||||||
return newmod
|
return newmod
|
||||||
|
|
||||||
if not parent_pkg: # top-level package, look for NS subpackages on all collection paths
|
if not parent_pkg: # top-level package, look for NS subpackages on all collection paths
|
||||||
package_paths = [self._extend_path_with_ns(p, fullname) for p in self._n_collection_paths]
|
package_paths = [self._extend_path_with_ns(p, fullname) for p in self.n_collection_paths]
|
||||||
else: # subpackage; search in all subpaths (we'll limit later inside a collection)
|
else: # subpackage; search in all subpaths (we'll limit later inside a collection)
|
||||||
package_paths = [self._extend_path_with_ns(p, fullname) for p in parent_pkg.__path__]
|
package_paths = [self._extend_path_with_ns(p, fullname) for p in parent_pkg.__path__]
|
||||||
|
|
||||||
|
@ -309,6 +310,4 @@ def is_collection_ref(candidate_name):
|
||||||
|
|
||||||
|
|
||||||
def set_collection_playbook_paths(b_playbook_paths):
|
def set_collection_playbook_paths(b_playbook_paths):
|
||||||
# set for any/all AnsibleCollectionLoader instance(s) on meta_path
|
AnsibleCollectionLoader().set_playbook_paths(b_playbook_paths)
|
||||||
for loader in (l for l in sys.meta_path if isinstance(l, AnsibleCollectionLoader)):
|
|
||||||
loader.set_playbook_paths(b_playbook_paths)
|
|
||||||
|
|
|
@ -23,6 +23,9 @@ def test_import_from_collection(monkeypatch):
|
||||||
|
|
||||||
from ansible.utils.collection_loader import AnsibleCollectionLoader
|
from ansible.utils.collection_loader import AnsibleCollectionLoader
|
||||||
|
|
||||||
|
# zap the singleton collection loader instance if it exists
|
||||||
|
AnsibleCollectionLoader._Singleton__instance = None
|
||||||
|
|
||||||
for index in [idx for idx, obj in enumerate(sys.meta_path) if isinstance(obj, AnsibleCollectionLoader)]:
|
for index in [idx for idx, obj in enumerate(sys.meta_path) if isinstance(obj, AnsibleCollectionLoader)]:
|
||||||
# replace any existing collection loaders that may exist
|
# replace any existing collection loaders that may exist
|
||||||
# since these were loaded during unit test collection
|
# since these were loaded during unit test collection
|
||||||
|
|
Loading…
Reference in a new issue