Merge pull request #1645 from dhozac/use-plugin-system-for-modules
Use plugin system for modules
This commit is contained in:
commit
75620220b6
6 changed files with 40 additions and 34 deletions
|
@ -68,7 +68,7 @@ class Inventory(object):
|
||||||
host_list = [ h for h in host_list if h and h.strip() ]
|
host_list = [ h for h in host_list if h and h.strip() ]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
utils.plugins.push_basedir(self.basedir())
|
utils.plugins.vars_loader.add_directory(self.basedir())
|
||||||
|
|
||||||
if type(host_list) == list:
|
if type(host_list) == list:
|
||||||
all = Group('all')
|
all = Group('all')
|
||||||
|
|
|
@ -44,7 +44,7 @@ class PlayBook(object):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
playbook = None,
|
playbook = None,
|
||||||
host_list = C.DEFAULT_HOST_LIST,
|
host_list = C.DEFAULT_HOST_LIST,
|
||||||
module_path = C.DEFAULT_MODULE_PATH,
|
module_path = None,
|
||||||
forks = C.DEFAULT_FORKS,
|
forks = C.DEFAULT_FORKS,
|
||||||
timeout = C.DEFAULT_TIMEOUT,
|
timeout = C.DEFAULT_TIMEOUT,
|
||||||
remote_user = C.DEFAULT_REMOTE_USER,
|
remote_user = C.DEFAULT_REMOTE_USER,
|
||||||
|
@ -110,17 +110,11 @@ class PlayBook(object):
|
||||||
self.inventory = ansible.inventory.Inventory(host_list)
|
self.inventory = ansible.inventory.Inventory(host_list)
|
||||||
self.inventory.subset(subset)
|
self.inventory.subset(subset)
|
||||||
|
|
||||||
self.modules_list = utils.get_available_modules(self.module_path)
|
|
||||||
|
|
||||||
if not self.inventory._is_script:
|
if not self.inventory._is_script:
|
||||||
self.global_vars.update(self.inventory.get_group_variables('all'))
|
self.global_vars.update(self.inventory.get_group_variables('all'))
|
||||||
|
|
||||||
self.basedir = os.path.dirname(playbook)
|
self.basedir = os.path.dirname(playbook)
|
||||||
(self.playbook, self.play_basedirs) = self._load_playbook_from_file(playbook)
|
(self.playbook, self.play_basedirs) = self._load_playbook_from_file(playbook)
|
||||||
self.module_path = self.module_path + os.pathsep + os.path.join(self.basedir, "library")
|
|
||||||
|
|
||||||
for i in self.play_basedirs:
|
|
||||||
utils.plugins.push_basedir(i)
|
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
|
@ -137,6 +131,7 @@ class PlayBook(object):
|
||||||
raise errors.AnsibleError("parse error: playbooks must be formatted as a YAML list")
|
raise errors.AnsibleError("parse error: playbooks must be formatted as a YAML list")
|
||||||
|
|
||||||
basedir = os.path.dirname(path)
|
basedir = os.path.dirname(path)
|
||||||
|
utils.plugins.push_basedir(basedir)
|
||||||
for play in playbook_data:
|
for play in playbook_data:
|
||||||
if type(play) != dict:
|
if type(play) != dict:
|
||||||
raise errors.AnsibleError("parse error: each play in a playbook must a YAML dictionary (hash), recieved: %s" % play)
|
raise errors.AnsibleError("parse error: each play in a playbook must a YAML dictionary (hash), recieved: %s" % play)
|
||||||
|
|
|
@ -44,7 +44,7 @@ class Task(object):
|
||||||
for x in ds.keys():
|
for x in ds.keys():
|
||||||
|
|
||||||
# code to allow for saying "modulename: args" versus "action: modulename args"
|
# code to allow for saying "modulename: args" versus "action: modulename args"
|
||||||
if x in play.playbook.modules_list:
|
if x in utils.plugins.module_finder:
|
||||||
ds['action'] = x + " " + ds[x]
|
ds['action'] = x + " " + ds[x]
|
||||||
ds.pop(x)
|
ds.pop(x)
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ class Runner(object):
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
host_list=C.DEFAULT_HOST_LIST, # ex: /etc/ansible/hosts, legacy usage
|
host_list=C.DEFAULT_HOST_LIST, # ex: /etc/ansible/hosts, legacy usage
|
||||||
module_path=C.DEFAULT_MODULE_PATH, # ex: /usr/share/ansible
|
module_path=None, # ex: /usr/share/ansible
|
||||||
module_name=C.DEFAULT_MODULE_NAME, # ex: copy
|
module_name=C.DEFAULT_MODULE_NAME, # ex: copy
|
||||||
module_args=C.DEFAULT_MODULE_ARGS, # ex: "src=/tmp/a dest=/tmp/b"
|
module_args=C.DEFAULT_MODULE_ARGS, # ex: "src=/tmp/a dest=/tmp/b"
|
||||||
forks=C.DEFAULT_FORKS, # parallelism level
|
forks=C.DEFAULT_FORKS, # parallelism level
|
||||||
|
@ -128,7 +128,6 @@ class Runner(object):
|
||||||
self.sudo_user = sudo_user
|
self.sudo_user = sudo_user
|
||||||
self.connector = connection.Connection(self)
|
self.connector = connection.Connection(self)
|
||||||
self.conditional = conditional
|
self.conditional = conditional
|
||||||
self.module_path = module_path
|
|
||||||
self.module_name = module_name
|
self.module_name = module_name
|
||||||
self.forks = int(forks)
|
self.forks = int(forks)
|
||||||
self.pattern = pattern
|
self.pattern = pattern
|
||||||
|
@ -151,6 +150,12 @@ class Runner(object):
|
||||||
if self.transport == 'local':
|
if self.transport == 'local':
|
||||||
self.remote_user = pwd.getpwuid(os.geteuid())[0]
|
self.remote_user = pwd.getpwuid(os.geteuid())[0]
|
||||||
|
|
||||||
|
if module_path is not None:
|
||||||
|
for i in module_path.split(os.pathsep):
|
||||||
|
utils.plugins.module_finder.add_directory(i)
|
||||||
|
|
||||||
|
utils.plugins.push_basedir(self.basedir)
|
||||||
|
|
||||||
# ensure we are using unique tmp paths
|
# ensure we are using unique tmp paths
|
||||||
random.seed()
|
random.seed()
|
||||||
|
|
||||||
|
@ -511,12 +516,9 @@ class Runner(object):
|
||||||
raise errors.AnsibleFileNotFound("%s is not a module" % module_name)
|
raise errors.AnsibleFileNotFound("%s is not a module" % module_name)
|
||||||
|
|
||||||
# Search module path(s) for named module.
|
# Search module path(s) for named module.
|
||||||
for module_path in self.module_path.split(os.pathsep):
|
in_path = utils.plugins.module_finder.find_plugin(module_name)
|
||||||
in_path = os.path.expanduser(os.path.join(module_path, module_name))
|
if in_path is None:
|
||||||
if os.path.exists(in_path):
|
raise errors.AnsibleFileNotFound("module %s not found in %s" % (module_name, utils.plugins.module_finder.print_paths()))
|
||||||
break
|
|
||||||
else:
|
|
||||||
raise errors.AnsibleFileNotFound("module %s not found in %s" % (module_name, self.module_path))
|
|
||||||
|
|
||||||
out_path = os.path.join(tmp, module_name)
|
out_path = os.path.join(tmp, module_name)
|
||||||
|
|
||||||
|
|
|
@ -463,20 +463,6 @@ def filter_leading_non_json_lines(buf):
|
||||||
filtered_lines.write(line + '\n')
|
filtered_lines.write(line + '\n')
|
||||||
return filtered_lines.getvalue()
|
return filtered_lines.getvalue()
|
||||||
|
|
||||||
def get_available_modules(dirname=None):
|
|
||||||
"""
|
|
||||||
returns a list of modules available based on current directory
|
|
||||||
looks in DEFAULT_MODULE_PATH, all subfolders named library and
|
|
||||||
-M option"""
|
|
||||||
modules_list = set()
|
|
||||||
if dirname is None:
|
|
||||||
dirname = C.DEFAULT_MODULE_PATH
|
|
||||||
for path in dirname.split(os.pathsep):
|
|
||||||
if os.path.exists(path):
|
|
||||||
modules_list.update(os.listdir(path))
|
|
||||||
modules_list = list(modules_list)
|
|
||||||
return modules_list
|
|
||||||
|
|
||||||
def boolean(value):
|
def boolean(value):
|
||||||
val = str(value)
|
val = str(value)
|
||||||
if val.lower() in [ "true", "t", "y", "1", "yes" ]:
|
if val.lower() in [ "true", "t", "y", "1", "yes" ]:
|
||||||
|
|
|
@ -42,25 +42,47 @@ class PluginLoader(object):
|
||||||
self.subdir = subdir
|
self.subdir = subdir
|
||||||
self.aliases = aliases
|
self.aliases = aliases
|
||||||
self._module_cache = {}
|
self._module_cache = {}
|
||||||
|
self._extra_dirs = []
|
||||||
|
|
||||||
def _get_package_path(self):
|
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'):
|
if not hasattr(self, 'package_path'):
|
||||||
m = __import__(self.package)
|
m = __import__(self.package)
|
||||||
parts = self.package.split('.')[1:]
|
parts = self.package.split('.')[1:]
|
||||||
self.package_path = os.path.join(os.path.dirname(m.__file__), *parts)
|
self.package_path = os.path.join(os.path.dirname(m.__file__), *parts)
|
||||||
return self.package_path
|
return [self.package_path]
|
||||||
|
|
||||||
def _get_paths(self):
|
def _get_paths(self):
|
||||||
"""Return a list of paths to search for plugins in
|
"""Return a list of paths to search for plugins in
|
||||||
|
|
||||||
The list is searched in order."""
|
The list is searched in order."""
|
||||||
return [os.path.join(basedir, self.subdir) for basedir in _basedirs] + self.config.split(os.pathsep) + [self._get_package_path()]
|
return self._extra_dirs + \
|
||||||
|
[os.path.join(basedir, self.subdir) for basedir in _basedirs] + \
|
||||||
|
self.config.split(os.pathsep) + \
|
||||||
|
self._get_package_path()
|
||||||
|
|
||||||
|
def add_directory(self, directory):
|
||||||
|
"""Adds an additional directory to the search path"""
|
||||||
|
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):
|
def find_plugin(self, name):
|
||||||
"""Find a plugin named name"""
|
"""Find a plugin named name"""
|
||||||
|
suffix = ".py"
|
||||||
|
if not self.class_name:
|
||||||
|
suffix = ""
|
||||||
for i in self._get_paths():
|
for i in self._get_paths():
|
||||||
path = os.path.join(i, "%s.py" % name)
|
path = os.path.join(i, "%s%s" % (name, suffix))
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
return path
|
return path
|
||||||
return None
|
return None
|
||||||
|
@ -93,6 +115,7 @@ class PluginLoader(object):
|
||||||
action_loader = PluginLoader('ActionModule', 'ansible.runner.action_plugins', C.DEFAULT_ACTION_PLUGIN_PATH, 'action_plugins')
|
action_loader = PluginLoader('ActionModule', 'ansible.runner.action_plugins', C.DEFAULT_ACTION_PLUGIN_PATH, 'action_plugins')
|
||||||
callback_loader = PluginLoader('CallbackModule', 'ansible.callback_plugins', C.DEFAULT_CALLBACK_PLUGIN_PATH, 'callback_plugins')
|
callback_loader = PluginLoader('CallbackModule', 'ansible.callback_plugins', C.DEFAULT_CALLBACK_PLUGIN_PATH, 'callback_plugins')
|
||||||
connection_loader = PluginLoader('Connection', 'ansible.runner.connection_plugins', C.DEFAULT_CONNECTION_PLUGIN_PATH, 'connection_plugins', aliases={'paramiko': 'paramiko_ssh'})
|
connection_loader = PluginLoader('Connection', 'ansible.runner.connection_plugins', C.DEFAULT_CONNECTION_PLUGIN_PATH, 'connection_plugins', aliases={'paramiko': 'paramiko_ssh'})
|
||||||
|
module_finder = PluginLoader('', '', C.DEFAULT_MODULE_PATH, 'library')
|
||||||
lookup_loader = PluginLoader('LookupModule', 'ansible.runner.lookup_plugins', C.DEFAULT_LOOKUP_PLUGIN_PATH, 'lookup_plugins')
|
lookup_loader = PluginLoader('LookupModule', 'ansible.runner.lookup_plugins', C.DEFAULT_LOOKUP_PLUGIN_PATH, 'lookup_plugins')
|
||||||
vars_loader = PluginLoader('VarsModule', 'ansible.inventory.vars_plugins', C.DEFAULT_VARS_PLUGIN_PATH, 'vars_plugins')
|
vars_loader = PluginLoader('VarsModule', 'ansible.inventory.vars_plugins', C.DEFAULT_VARS_PLUGIN_PATH, 'vars_plugins')
|
||||||
filter_loader = PluginLoader('FilterModule', 'ansible.runner.filter_plugins', C.DEFAULT_FILTER_PLUGIN_PATH, 'filter_plugins')
|
filter_loader = PluginLoader('FilterModule', 'ansible.runner.filter_plugins', C.DEFAULT_FILTER_PLUGIN_PATH, 'filter_plugins')
|
||||||
|
|
Loading…
Reference in a new issue