diff --git a/changelogs/fragments/config_load_by_name.yml b/changelogs/fragments/config_load_by_name.yml new file mode 100644 index 00000000000..8174bbb311d --- /dev/null +++ b/changelogs/fragments/config_load_by_name.yml @@ -0,0 +1,2 @@ +bugfixes: + - plugin loader will now load config data for plugin by name instead of by file to avoid issues with the same file being loaded under different names (fqcn + short name). diff --git a/lib/ansible/plugins/loader.py b/lib/ansible/plugins/loader.py index c47a313a0c0..ffb500ffacf 100644 --- a/lib/ansible/plugins/loader.py +++ b/lib/ansible/plugins/loader.py @@ -391,7 +391,7 @@ class PluginLoader: type_name = get_plugin_class(self.class_name) # if type name != 'module_doc_fragment': - if type_name in C.CONFIGURABLE_PLUGINS: + if type_name in C.CONFIGURABLE_PLUGINS and not C.config.get_configuration_definition(type_name, name): dstring = AnsibleLoader(getattr(module, 'DOCUMENTATION', ''), file_name=path).get_single_data() if dstring: add_fragments(dstring, path, fragment_loader=fragment_loader, is_module=(type_name == 'module')) @@ -819,10 +819,12 @@ class PluginLoader: if path not in self._module_cache: self._module_cache[path] = self._load_module_source(name, path) - self._load_config_defs(name, self._module_cache[path], path) found_in_cache = False + self._load_config_defs(name, self._module_cache[path], path) + obj = getattr(self._module_cache[path], self.class_name) + if self.base_class: # The import path is hardcoded and should be the right place, # so we are not expecting an ImportError. @@ -949,15 +951,18 @@ class PluginLoader: else: full_name = basename module = self._load_module_source(full_name, path) - self._load_config_defs(basename, module, path) except Exception as e: display.warning("Skipping plugin (%s) as it seems to be invalid: %s" % (path, to_text(e))) continue self._module_cache[path] = module found_in_cache = False + else: + module = self._module_cache[path] + + self._load_config_defs(basename, module, path) try: - obj = getattr(self._module_cache[path], self.class_name) + obj = getattr(module, self.class_name) except AttributeError as e: display.warning("Skipping plugin (%s) as it seems to be invalid: %s" % (path, to_text(e))) continue diff --git a/test/integration/targets/plugin_loader/runme.sh b/test/integration/targets/plugin_loader/runme.sh index 8ce7803a78f..e30f62419b3 100755 --- a/test/integration/targets/plugin_loader/runme.sh +++ b/test/integration/targets/plugin_loader/runme.sh @@ -31,3 +31,6 @@ do exit 1 fi done + +# test config loading +ansible-playbook use_coll_name.yml -i ../../inventory -e 'ansible_connection=ansible.builtin.ssh' "$@" diff --git a/test/integration/targets/plugin_loader/use_coll_name.yml b/test/integration/targets/plugin_loader/use_coll_name.yml new file mode 100644 index 00000000000..66507ced2c1 --- /dev/null +++ b/test/integration/targets/plugin_loader/use_coll_name.yml @@ -0,0 +1,7 @@ +- name: ensure configuration is loaded when we use FQCN and have already loaded using 'short namne' (which is case will all builtin connection plugins) + hosts: all + gather_facts: false + tasks: + - name: relies on extra var being passed in with connection and fqcn + ping: + ignore_unreachable: True