|
|
|
@ -23,34 +23,47 @@ import ansible.constants as C
|
|
|
|
|
from ansible import errors
|
|
|
|
|
|
|
|
|
|
MODULE_CACHE = {}
|
|
|
|
|
PATH_CACHE = {}
|
|
|
|
|
PLUGIN_PATH_CACHE = {}
|
|
|
|
|
_basedirs = []
|
|
|
|
|
|
|
|
|
|
def push_basedir(basedir):
|
|
|
|
|
_basedirs.insert(0, basedir)
|
|
|
|
|
|
|
|
|
|
class PluginLoader(object):
|
|
|
|
|
"""PluginLoader loads plugins from the best source
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
PluginLoader loads plugins from the configured plugin directories.
|
|
|
|
|
|
|
|
|
|
It searches for plugins by iterating through the combined list of
|
|
|
|
|
play basedirs, configured paths, and the installed package directory.
|
|
|
|
|
play basedirs, configured paths, and the python path.
|
|
|
|
|
The first match is used.
|
|
|
|
|
"""
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
def __init__(self, class_name, package, config, subdir, aliases={}):
|
|
|
|
|
"""Create a new PluginLoader"""
|
|
|
|
|
self.class_name = class_name
|
|
|
|
|
self.package = package
|
|
|
|
|
self.config = config
|
|
|
|
|
self.subdir = subdir
|
|
|
|
|
self.aliases = aliases
|
|
|
|
|
|
|
|
|
|
self.class_name = class_name
|
|
|
|
|
self.package = package
|
|
|
|
|
self.config = config
|
|
|
|
|
self.subdir = subdir
|
|
|
|
|
self.aliases = aliases
|
|
|
|
|
|
|
|
|
|
if not class_name in MODULE_CACHE:
|
|
|
|
|
MODULE_CACHE[class_name] = {}
|
|
|
|
|
if not class_name in PATH_CACHE:
|
|
|
|
|
PATH_CACHE[class_name] = None
|
|
|
|
|
if not class_name in PLUGIN_PATH_CACHE:
|
|
|
|
|
PLUGIN_PATH_CACHE[class_name] = {}
|
|
|
|
|
|
|
|
|
|
self._module_cache = MODULE_CACHE[class_name]
|
|
|
|
|
self._paths = PATH_CACHE[class_name]
|
|
|
|
|
self._plugin_path_cache = PLUGIN_PATH_CACHE[class_name]
|
|
|
|
|
|
|
|
|
|
self._module_cache = MODULE_CACHE[class_name]
|
|
|
|
|
self._extra_dirs = []
|
|
|
|
|
|
|
|
|
|
def _get_package_path(self):
|
|
|
|
|
"""Gets the path of a Python package"""
|
|
|
|
|
''' Gets the path of a Python package '''
|
|
|
|
|
|
|
|
|
|
if not self.package:
|
|
|
|
|
return []
|
|
|
|
|
if not hasattr(self, 'package_path'):
|
|
|
|
@ -60,9 +73,11 @@ class PluginLoader(object):
|
|
|
|
|
return [self.package_path]
|
|
|
|
|
|
|
|
|
|
def _get_paths(self):
|
|
|
|
|
"""Return a list of paths to search for plugins in
|
|
|
|
|
''' Return a list of paths to search for plugins in '''
|
|
|
|
|
|
|
|
|
|
if self._paths is not None:
|
|
|
|
|
return self._paths
|
|
|
|
|
|
|
|
|
|
The list is searched in order."""
|
|
|
|
|
ret = []
|
|
|
|
|
ret += self._extra_dirs
|
|
|
|
|
for basedir in _basedirs:
|
|
|
|
@ -71,41 +86,51 @@ class PluginLoader(object):
|
|
|
|
|
ret.append(fullpath)
|
|
|
|
|
ret += self.config.split(os.pathsep)
|
|
|
|
|
ret += self._get_package_path()
|
|
|
|
|
|
|
|
|
|
self._paths = ret
|
|
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_directory(self, directory, with_subdir=False):
|
|
|
|
|
"""Adds an additional directory to the search path"""
|
|
|
|
|
''' Adds an additional directory to the search path '''
|
|
|
|
|
|
|
|
|
|
self._paths = None
|
|
|
|
|
|
|
|
|
|
if directory is not None:
|
|
|
|
|
if with_subdir:
|
|
|
|
|
directory = os.path.join(directory, self.subdir)
|
|
|
|
|
self._extra_dirs.append(directory)
|
|
|
|
|
|
|
|
|
|
def print_paths(self):
|
|
|
|
|
"""Returns a string suitable for printing of the search path"""
|
|
|
|
|
# Uses a list to get the order right
|
|
|
|
|
ret = []
|
|
|
|
|
for i in self._get_paths():
|
|
|
|
|
if i not in ret:
|
|
|
|
|
ret.append(i)
|
|
|
|
|
return os.pathsep.join(ret)
|
|
|
|
|
|
|
|
|
|
def find_plugin(self, name):
|
|
|
|
|
"""Find a plugin named name"""
|
|
|
|
|
''' Find a plugin named name '''
|
|
|
|
|
|
|
|
|
|
if 'name' in self._plugin_path_cache:
|
|
|
|
|
return self._plugin_path_cache[name]
|
|
|
|
|
|
|
|
|
|
suffix = ".py"
|
|
|
|
|
if not self.class_name:
|
|
|
|
|
suffix = ""
|
|
|
|
|
paths = self._get_paths()
|
|
|
|
|
|
|
|
|
|
for i in self._get_paths():
|
|
|
|
|
path = os.path.join(i, "%s%s" % (name, suffix))
|
|
|
|
|
if os.path.exists(path):
|
|
|
|
|
self._plugin_path_cache[name] = path
|
|
|
|
|
return path
|
|
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def has_plugin(self, name):
|
|
|
|
|
"""Checks if a plugin named name exists"""
|
|
|
|
|
''' Checks if a plugin named name exists '''
|
|
|
|
|
|
|
|
|
|
return self.find_plugin(name) is not None
|
|
|
|
|
|
|
|
|
|
__contains__ = has_plugin
|
|
|
|
|
|
|
|
|
|
def get(self, name, *args, **kwargs):
|
|
|
|
|
''' instantiates a plugin of the given name using arguments '''
|
|
|
|
|
|
|
|
|
|
if name in self.aliases:
|
|
|
|
|
name = self.aliases[name]
|
|
|
|
|
path = self.find_plugin(name)
|
|
|
|
@ -116,6 +141,7 @@ class PluginLoader(object):
|
|
|
|
|
return getattr(self._module_cache[path], self.class_name)(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
def all(self, *args, **kwargs):
|
|
|
|
|
''' instantiates all plugins with the same arguments '''
|
|
|
|
|
|
|
|
|
|
for i in self._get_paths():
|
|
|
|
|
for path in glob.glob(os.path.join(i, "*.py")):
|
|
|
|
|