Example #1
0
    def load_callbacks(self):
        '''
        Loads all available callbacks, with the exception of those which
        utilize the CALLBACK_TYPE option. When CALLBACK_TYPE is set to 'stdout',
        only one such callback plugin will be loaded.
        '''

        if self._callbacks_loaded:
            return

        stdout_callback_loaded = False
        if self._stdout_callback is None:
            self._stdout_callback = C.DEFAULT_STDOUT_CALLBACK

        if isinstance(self._stdout_callback, CallbackBase):
            stdout_callback_loaded = True
        elif isinstance(self._stdout_callback, string_types):
            if self._stdout_callback not in callback_loader:
                raise AnsibleError("Invalid callback for stdout specified: %s" % self._stdout_callback)
            else:
                self._stdout_callback = callback_loader.get(self._stdout_callback)
                try:
                    self._stdout_callback.set_options()
                except AttributeError:
                    display.deprecated("%s stdout callback, does not support setting 'options', it will work for now, "
                                       " but this will be required in the future and should be updated,"
                                       " see the 2.4 porting guide for details." % self._stdout_callback._load_name, version="2.9")
                stdout_callback_loaded = True
        else:
            raise AnsibleError("callback must be an instance of CallbackBase or the name of a callback plugin")

        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)
            (callback_name, _) = os.path.splitext(os.path.basename(callback_plugin._original_path))
            if callback_type == 'stdout':
                # we only allow one callback of type 'stdout' to be loaded,
                if callback_name != self._stdout_callback or stdout_callback_loaded:
                    continue
                stdout_callback_loaded = True
            elif callback_name == 'tree' and self._run_tree:
                # special case for ansible cli option
                pass
            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()
            try:
                callback_obj.set_options()
            except AttributeError:
                    display.deprecated("%s callback, does not support setting 'options', it will work for now, "
                                       " but this will be required in the future and should be updated, "
                                       " see the 2.4 porting guide for details." % callback_obj._load_name, version="2.9")
            self._callback_plugins.append(callback_obj)

        self._callbacks_loaded = True
    def load_callbacks(self):
        '''
        Loads all available callbacks, with the exception of those which
        utilize the CALLBACK_TYPE option. When CALLBACK_TYPE is set to 'stdout',
        only one such callback plugin will be loaded.
        '''

        if self._callbacks_loaded:
            return

        stdout_callback_loaded = False
        if self._stdout_callback is None:
            self._stdout_callback = C.DEFAULT_STDOUT_CALLBACK

        if isinstance(self._stdout_callback, CallbackBase):
            stdout_callback_loaded = True
        elif isinstance(self._stdout_callback, string_types):
            if self._stdout_callback not in callback_loader:
                raise AnsibleError("Invalid callback for stdout specified: %s" % self._stdout_callback)
            else:
                self._stdout_callback = callback_loader.get(self._stdout_callback)
                try:
                    self._stdout_callback.set_options()
                except AttributeError:
                    display.deprecated("%s stdout callback, does not support setting 'options', it will work for now, "
                                       " but this will be required in the future and should be updated,"
                                       " see the 2.4 porting guide for details." % self._stdout_callback._load_name, version="2.9")
                stdout_callback_loaded = True
        else:
            raise AnsibleError("callback must be an instance of CallbackBase or the name of a callback plugin")

        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)
            (callback_name, _) = os.path.splitext(os.path.basename(callback_plugin._original_path))
            if callback_type == 'stdout':
                # we only allow one callback of type 'stdout' to be loaded,
                if callback_name != self._stdout_callback or stdout_callback_loaded:
                    continue
                stdout_callback_loaded = True
            elif callback_name == 'tree' and self._run_tree:
                # special case for ansible cli option
                pass
            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()
            try:
                callback_obj.set_options()
            except AttributeError:
                    display.deprecated("%s callback, does not support setting 'options', it will work for now, "
                                       " but this will be required in the future and should be updated, "
                                       " see the 2.4 porting guide for details." % self.callback_obj._load_name, version="2.9")
            self._callback_plugins.append(callback_obj)

        self._callbacks_loaded = True
Example #3
0
    def load_callbacks(self):
        '''
        Loads all available callbacks, with the exception of those which
        utilize the CALLBACK_TYPE option. When CALLBACK_TYPE is set to 'stdout',
        only one such callback plugin will be loaded.
        '''

        if self._callbacks_loaded:
            return

        stdout_callback_loaded = False
        if self._stdout_callback is None:
            self._stdout_callback = C.DEFAULT_STDOUT_CALLBACK

        if isinstance(self._stdout_callback, CallbackBase):
            stdout_callback_loaded = True
        elif isinstance(self._stdout_callback, string_types):
            if self._stdout_callback not in callback_loader:
                raise AnsibleError(
                    "Invalid callback for stdout specified: %s" %
                    self._stdout_callback)
            else:
                self._stdout_callback = callback_loader.get(
                    self._stdout_callback)
                stdout_callback_loaded = True
        else:
            raise AnsibleError(
                "callback must be an instance of CallbackBase or the name of a callback plugin"
            )

        for callback_plugin in callback_loader.all(class_only=True):
            if hasattr(callback_plugin, 'CALLBACK_VERSION'
                       ) and callback_plugin.CALLBACK_VERSION >= 2.0:
                # we only allow one callback of type 'stdout' to be loaded, so check
                # the name of the current plugin and type to see if we need to skip
                # loading this callback plugin
                callback_type = getattr(callback_plugin, 'CALLBACK_TYPE', None)
                callback_needs_whitelist = getattr(callback_plugin,
                                                   'CALLBACK_NEEDS_WHITELIST',
                                                   False)
                (callback_name, _) = os.path.splitext(
                    os.path.basename(callback_plugin._original_path))
                if callback_type == 'stdout':
                    if callback_name != self._stdout_callback or stdout_callback_loaded:
                        continue
                    stdout_callback_loaded = True
                elif callback_name == 'tree' and self._run_tree:
                    pass
                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)):
                    continue

            self._callback_plugins.append(callback_plugin())

        self._callbacks_loaded = True
    def load_callbacks(self):
        '''
        Loads all available callbacks, with the exception of those which
        utilize the CALLBACK_TYPE option. When CALLBACK_TYPE is set to 'stdout',
        only one such callback plugin will be loaded.
        '''

        if self._callbacks_loaded:
            return

        stdout_callback_loaded = False
        if self._stdout_callback is None:
            self._stdout_callback = C.DEFAULT_STDOUT_CALLBACK

        if isinstance(self._stdout_callback, CallbackBase):
            stdout_callback_loaded = True
        elif isinstance(self._stdout_callback, string_types):
            if self._stdout_callback not in callback_loader:
                raise AnsibleError("Invalid callback for stdout specified: %s" % self._stdout_callback)
            else:
                self._stdout_callback = callback_loader.get(self._stdout_callback)
                self._stdout_callback.set_options()
                stdout_callback_loaded = True
        else:
            raise AnsibleError("callback must be an instance of CallbackBase or the name of a callback plugin")

        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)
            (callback_name, _) = os.path.splitext(os.path.basename(callback_plugin._original_path))
            if callback_type == 'stdout':
                # we only allow one callback of type 'stdout' to be loaded,
                if callback_name != self._stdout_callback or stdout_callback_loaded:
                    continue
                stdout_callback_loaded = True
            elif callback_name == 'tree' and self._run_tree:
                # special case for ansible cli option
                pass
            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()
            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)
            self._callback_plugins.append(callback_obj)

        self._callbacks_loaded = True
Example #5
0
    def load_callbacks(self):
        '''
        Loads all available callbacks, with the exception of those which
        utilize the CALLBACK_TYPE option. When CALLBACK_TYPE is set to 'stdout',
        only one such callback plugin will be loaded.
        '''

        if self._callbacks_loaded:
            return

        stdout_callback_loaded = False
        if self._stdout_callback is None:
            self._stdout_callback = C.DEFAULT_STDOUT_CALLBACK

        if isinstance(self._stdout_callback, CallbackBase):
            stdout_callback_loaded = True
        elif isinstance(self._stdout_callback, string_types):
            if self._stdout_callback not in callback_loader:
                raise AnsibleError(
                    "Invalid callback for stdout specified: %s" %
                    self._stdout_callback)
            else:
                self._stdout_callback = callback_loader.get(
                    self._stdout_callback)
                self._stdout_callback.set_options()
                stdout_callback_loaded = True
        else:
            raise AnsibleError(
                "callback must be an instance of CallbackBase or the name of a callback plugin"
            )

        # get all configured loadable callbacks (adjacent, builtin)
        callback_list = list(callback_loader.all(class_only=True))

        # add whitelisted callbacks that refer to collections, which might not appear in normal listing
        for c in C.DEFAULT_CALLBACK_WHITELIST:
            # load all, as collection ones might be using short/redirected names and not a fqcn
            plugin = callback_loader.get(c, class_only=True)

            # TODO: check if this skip is redundant, loader should handle bad file/plugin cases already
            if plugin:
                # avoids incorrect and dupes possible due to collections
                if plugin not in callback_list:
                    callback_list.append(plugin)
            else:
                display.warning(
                    "Skipping callback plugin '%s', unable to load" % c)

        # for each callback in the list see if we should add it to 'active callbacks' used in the play
        for callback_plugin in callback_list:

            callback_type = getattr(callback_plugin, 'CALLBACK_TYPE', '')
            callback_needs_whitelist = getattr(callback_plugin,
                                               'CALLBACK_NEEDS_WHITELIST',
                                               False)

            # try to get collection world name first
            cnames = getattr(callback_plugin, '_redirected_names', [])
            if cnames:
                # store the name the plugin was loaded as, as that's what we'll need to compare to the configured callback list later
                callback_name = cnames[0]
            else:
                # fallback to 'old loader name'
                (callback_name, _) = os.path.splitext(
                    os.path.basename(callback_plugin._original_path))

            display.vvvvv("Attempting to use '%s' callback." % (callback_name))
            if callback_type == 'stdout':
                # we only allow one callback of type 'stdout' to be loaded,
                if callback_name != self._stdout_callback or stdout_callback_loaded:
                    display.vv(
                        "Skipping callback '%s', as we already have a stdout callback."
                        % (callback_name))
                    continue
                stdout_callback_loaded = True
            elif callback_name == 'tree' and self._run_tree:
                # TODO: remove special case for tree, which is an adhoc cli option --tree
                pass
            elif not self._run_additional_callbacks or (
                    callback_needs_whitelist and
                (
                    # only run if not adhoc, or adhoc was specifically configured to run + check enabled list
                    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

            try:
                callback_obj = callback_plugin()
                # avoid bad plugin not returning an object, only needed cause we do class_only load and bypass loader checks,
                # really a bug in the plugin itself which we ignore as callback errors are not supposed to be fatal.
                if callback_obj:
                    # skip initializing if we already did the work for the same plugin (even with diff names)
                    if callback_obj not in self._callback_plugins:
                        callback_obj.set_options()
                        self._callback_plugins.append(callback_obj)
                    else:
                        display.vv(
                            "Skipping callback '%s', already loaded as '%s'." %
                            (callback_plugin, callback_name))
                else:
                    display.warning(
                        "Skipping callback '%s', as it does not create a valid plugin instance."
                        % callback_name)
                    continue
            except Exception as e:
                display.warning(
                    "Skipping callback '%s', unable to load due to: %s" %
                    (callback_name, to_native(e)))
                continue

        self._callbacks_loaded = True
    def load_callbacks(self):
        '''
        Loads all available callbacks, with the exception of those which
        utilize the CALLBACK_TYPE option. When CALLBACK_TYPE is set to 'stdout',
        only one such callback plugin will be loaded.
        '''

        if self._callbacks_loaded:
            return

        stdout_callback_loaded = False
        if self._stdout_callback is None:
            self._stdout_callback = C.DEFAULT_STDOUT_CALLBACK

        if isinstance(self._stdout_callback, CallbackBase):
            stdout_callback_loaded = True
        elif isinstance(self._stdout_callback, string_types):
            if self._stdout_callback not in callback_loader:
                raise AnsibleError(
                    "Invalid callback for stdout specified: %s" %
                    self._stdout_callback)
            else:
                self._stdout_callback = callback_loader.get(
                    self._stdout_callback)
                self._stdout_callback.set_options()
                stdout_callback_loaded = True
        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)
            (callback_name, _) = os.path.splitext(
                os.path.basename(callback_plugin._original_path))
            if callback_type == 'stdout':
                # we only allow one callback of type 'stdout' to be loaded,
                if callback_name != self._stdout_callback or stdout_callback_loaded:
                    continue
                stdout_callback_loaded = True
            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)

        # 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