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)
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)
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>")
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
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)