diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ansible/config/ansible_builtin_runtime.yml | 7 | ||||
-rw-r--r-- | lib/ansible/executor/task_queue_manager.py | 30 |
2 files changed, 29 insertions, 8 deletions
diff --git a/lib/ansible/config/ansible_builtin_runtime.yml b/lib/ansible/config/ansible_builtin_runtime.yml index b412518ab1..e7d35fb3d8 100644 --- a/lib/ansible/config/ansible_builtin_runtime.yml +++ b/lib/ansible/config/ansible_builtin_runtime.yml @@ -8290,6 +8290,13 @@ plugin_routing: redirect: ansible.posix.timer foreman: redirect: theforeman.foreman.foreman + # 'collections' integration test entries, do not remove + formerly_core_callback: + redirect: testns.testcoll.usercallback + formerly_core_removed_callback: + redirect: testns.testcoll.removedcallback + formerly_core_missing_callback: + redirect: bogusns.boguscoll.boguscallback doc_fragments: a10: redirect: community.network.a10 diff --git a/lib/ansible/executor/task_queue_manager.py b/lib/ansible/executor/task_queue_manager.py index cd6c396860..e7277c9183 100644 --- a/lib/ansible/executor/task_queue_manager.py +++ b/lib/ansible/executor/task_queue_manager.py @@ -138,6 +138,9 @@ class TaskQueueManager: else: raise AnsibleError("callback must be an instance of CallbackBase or the name of a callback plugin") + loaded_callbacks = set() + + # first, load callbacks in the core distribution and configured callback paths for callback_plugin in callback_loader.all(class_only=True): callback_type = getattr(callback_plugin, 'CALLBACK_TYPE', '') callback_needs_whitelist = getattr(callback_plugin, 'CALLBACK_NEEDS_WHITELIST', False) @@ -150,23 +153,34 @@ class TaskQueueManager: elif callback_name == 'tree' and self._run_tree: # special case for ansible cli option pass + # eg, ad-hoc doesn't allow non-default callbacks elif not self._run_additional_callbacks or (callback_needs_whitelist and ( C.DEFAULT_CALLBACK_WHITELIST is None or callback_name not in C.DEFAULT_CALLBACK_WHITELIST)): # 2.x plugins shipped with ansible should require whitelisting, older or non shipped should load automatically continue callback_obj = callback_plugin() + loaded_callbacks.add(callback_name) # mark as loaded so we skip in second pass callback_obj.set_options() self._callback_plugins.append(callback_obj) - for callback_plugin_name in (c for c in C.DEFAULT_CALLBACK_WHITELIST if AnsibleCollectionRef.is_valid_fqcr(c)): - # TODO: need to extend/duplicate the stdout callback check here (and possible move this ahead of the old way - callback_obj = callback_loader.get(callback_plugin_name) - if callback_obj: - callback_obj.set_options() - self._callback_plugins.append(callback_obj) - else: - display.warning("Skipping '%s', unable to load or use as a callback" % callback_plugin_name) + # eg, ad-hoc doesn't allow non-default callbacks + if self._run_additional_callbacks: + # Second pass over everything in the whitelist we haven't already loaded, try to explicitly load. This will catch + # collection-hosted callbacks, as well as formerly-core callbacks that have been redirected to collections. + for callback_plugin_name in (c for c in C.DEFAULT_CALLBACK_WHITELIST if c not in loaded_callbacks): + # TODO: need to extend/duplicate the stdout callback check here (and possible move this ahead of the old way + callback_obj, plugin_load_context = callback_loader.get_with_context(callback_plugin_name) + if callback_obj: + loaded_as_name = callback_obj._redirected_names[-1] + if loaded_as_name in loaded_callbacks: + display.warning("Skipping callback '%s', already loaded as '%s'." % (callback_plugin_name, loaded_as_name)) + continue + loaded_callbacks.add(loaded_as_name) + callback_obj.set_options() + self._callback_plugins.append(callback_obj) + else: + display.warning("Skipping '%s', unable to load or use as a callback" % callback_plugin_name) self._callbacks_loaded = True |