Esempio n. 1
0
    def _find_plugin(self,
                     name,
                     mod_type='',
                     ignore_deprecated=False,
                     check_aliases=False,
                     collection_list=None):
        ''' Find a plugin named name '''

        global _PLUGIN_FILTERS
        if name in _PLUGIN_FILTERS[self.package]:
            return None

        if mod_type:
            suffix = mod_type
        elif self.class_name:
            # Ansible plugins that run in the controller process (most plugins)
            suffix = '.py'
        else:
            # Only Ansible Modules.  Ansible modules can be any executable so
            # they can have any suffix
            suffix = ''

        # HACK: need this right now so we can still load shipped PS module_utils
        if (is_collection_ref(name)
                or collection_list) and not name.startswith('Ansible'):
            if '.' in name or not collection_list:
                candidates = [name]
            else:
                candidates = [
                    '{0}.{1}'.format(c, name) for c in collection_list
                ]
            # TODO: keep actual errors, not just assembled messages
            errors = []
            for candidate_name in candidates:
                try:
                    # HACK: refactor this properly
                    if candidate_name.startswith('ansible.legacy'):
                        # just pass the raw name to the old lookup function to check in all the usual locations
                        p = self._find_plugin_legacy(
                            name.replace('ansible.legacy.', '', 1),
                            ignore_deprecated, check_aliases, suffix)
                    else:
                        p = self._find_fq_plugin(candidate_name, suffix)
                    if p:
                        return p
                except Exception as ex:
                    errors.append(to_native(ex))

            if errors:
                display.debug(
                    msg='plugin lookup for {0} failed; errors: {1}'.format(
                        name, '; '.join(errors)))

            return None

        # if we got here, there's no collection list and it's not an FQ name, so do legacy lookup

        return self._find_plugin_legacy(name, ignore_deprecated, check_aliases,
                                        suffix)
Esempio n. 2
0
def validate_collection_name(name):
    """
    Validates the collection name as an input from the user or a requirements file fit the requirements.

    :param name: The input name with optional range specifier split by ':'.
    :return: The input value, required for argparse validation.
    """
    collection, dummy, dummy = name.partition(':')
    if is_collection_ref('ansible_collections.{0}'.format(collection)):
        return name

    raise AnsibleError("Invalid collection name '%s', name must be in the format <namespace>.<collection>." % name)
Esempio n. 3
0
    def _validate_collection_name(name):
        if is_collection_ref('ansible_collections.{0}'.format(name)):
            return name

        raise AnsibleError("Invalid collection name, must be in the format <namespace>.<collection>")
Esempio n. 4
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"
            )

        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 is_collection_ref(c)):
            callback_obj = callback_loader.get(callback_plugin_name)
            self._callback_plugins.append(callback_obj)

        self._callbacks_loaded = True
Esempio n. 5
0
    def _load_role_path(self, role_name):
        '''
        the 'role', as specified in the ds (or as a bare string), can either
        be a simple name or a full path. If it is a full path, we use the
        basename as the role name, otherwise we take the name as-given and
        append it to the default role path
        '''

        # create a templar class to template the dependency names, in
        # case they contain variables
        if self._variable_manager is not None:
            all_vars = self._variable_manager.get_vars(play=self._play)
        else:
            all_vars = dict()

        templar = Templar(loader=self._loader, variables=all_vars)
        role_name = templar.template(role_name)

        role_tuple = None

        # try to load as a collection-based role first
        if self._collection_list or is_collection_ref(role_name):
            role_tuple = get_collection_role_path(role_name,
                                                  self._collection_list)

        if role_tuple:
            # we found it, stash collection data and return the name/path tuple
            self._role_collection = role_tuple[2]
            return role_tuple[0:2]

        # FUTURE: refactor this to be callable from internal so we can properly order ansible.legacy searches with the collections keyword
        if self._collection_list and 'ansible.legacy' not in self._collection_list:
            raise AnsibleError("the role '%s' was not found in %s" %
                               (role_name, ":".join(self._collection_list)),
                               obj=self._ds)

        # we always start the search for roles in the base directory of the playbook
        role_search_paths = [
            os.path.join(self._loader.get_basedir(), u'roles'),
        ]

        # also search in the configured roles path
        if C.DEFAULT_ROLES_PATH:
            role_search_paths.extend(C.DEFAULT_ROLES_PATH)

        # next, append the roles basedir, if it was set, so we can
        # search relative to that directory for dependent roles
        if self._role_basedir:
            role_search_paths.append(self._role_basedir)

        # finally as a last resort we look in the current basedir as set
        # in the loader (which should be the playbook dir itself) but without
        # the roles/ dir appended
        role_search_paths.append(self._loader.get_basedir())

        # now iterate through the possible paths and return the first one we find
        for path in role_search_paths:
            path = templar.template(path)
            role_path = unfrackpath(os.path.join(path, role_name))
            if self._loader.path_exists(role_path):
                return (role_name, role_path)

        # if not found elsewhere try to extract path from name
        role_path = unfrackpath(role_name)
        if self._loader.path_exists(role_path):
            role_name = os.path.basename(role_name)
            return (role_name, role_path)

        raise AnsibleError("the role '%s' was not found in %s" %
                           (role_name, ":".join(role_search_paths)),
                           obj=self._ds)