Much requested feature -- allows relative imports of content within roles or relative to any task or handler include (../templates for template ../files for copy)
This commit is contained in:
parent
95f30f0def
commit
892484812e
4 changed files with 102 additions and 9 deletions
|
@ -56,9 +56,14 @@ class Play(object):
|
|||
self.vars_prompt = ds.get('vars_prompt', {})
|
||||
self.playbook = playbook
|
||||
self.vars = self._get_vars()
|
||||
self.vars_files = ds.get('vars_files', [])
|
||||
self.basedir = basedir
|
||||
self.roles = ds.get('roles', None)
|
||||
|
||||
ds = self._load_roles(self.roles, ds)
|
||||
self.vars_files = ds.get('vars_files', [])
|
||||
|
||||
self._update_vars_files_for_host(None)
|
||||
|
||||
self._ds = ds = utils.template(basedir, ds, self.vars)
|
||||
|
||||
hosts = ds.get('hosts')
|
||||
|
@ -82,12 +87,11 @@ class Play(object):
|
|||
self.serial = int(ds.get('serial', 0))
|
||||
self.remote_port = self.remote_port
|
||||
self.any_errors_fatal = ds.get('any_errors_fatal', False)
|
||||
self.roles = ds.get('roles', None)
|
||||
|
||||
|
||||
load_vars = {}
|
||||
if self.playbook.inventory.basedir() is not None:
|
||||
load_vars['inventory_dir'] = self.playbook.inventory.basedir();
|
||||
|
||||
self._tasks = self._load_tasks(self._ds.get('tasks', []), load_vars)
|
||||
self._handlers = self._load_tasks(self._ds.get('handlers', []), load_vars)
|
||||
|
||||
|
@ -100,10 +104,65 @@ class Play(object):
|
|||
|
||||
if self.sudo_user != 'root':
|
||||
self.sudo = True
|
||||
|
||||
|
||||
# *************************************************
|
||||
|
||||
def _load_tasks(self, tasks, vars={}, additional_conditions=[]):
|
||||
def _load_roles(self, roles, ds):
|
||||
|
||||
|
||||
# a role is a name that auto-includes the following if they exist
|
||||
# <rolename>/tasks/main.yml
|
||||
# <rolename>/handlers/main.yml
|
||||
# <rolename>/vars/main.yml
|
||||
# and it auto-extends tasks/handlers/vars_files as appropriate if found
|
||||
|
||||
if roles is None:
|
||||
return ds
|
||||
if type(roles) != list:
|
||||
raise errors.AnsibleError("value of 'roles:' must be a list")
|
||||
|
||||
new_tasks = []
|
||||
new_handlers = []
|
||||
new_vars_files = []
|
||||
for orig_path in roles:
|
||||
path = utils.path_dwim(self.basedir, orig_path)
|
||||
if not os.path.isdir(path):
|
||||
path2 = utils.path_dwim(self.basedir, os.path.join(self.basedir, 'roles', orig_path))
|
||||
if not os.path.isdir(path2):
|
||||
raise errors.AnsibleError("cannot find role in %s or %s" % (path, path2))
|
||||
path = path2
|
||||
task = utils.path_dwim(self.basedir, os.path.join(path, 'tasks', 'main.yml'))
|
||||
handler = utils.path_dwim(self.basedir, os.path.join(path, 'handlers', 'main.yml'))
|
||||
vars_file = utils.path_dwim(self.basedir, os.path.join(path, 'vars', 'main.yml'))
|
||||
if os.path.isfile(task):
|
||||
new_tasks.append(dict(include=task))
|
||||
if os.path.isfile(handler):
|
||||
new_handlers.append(dict(include=handler))
|
||||
if os.path.isfile(vars_file):
|
||||
new_vars_files.append(vars_file)
|
||||
|
||||
tasks = ds.get('tasks', None)
|
||||
handlers = ds.get('handlers', None)
|
||||
vars_files = ds.get('vars_files', None)
|
||||
if type(tasks) != list:
|
||||
tasks = []
|
||||
if type(handlers) != list:
|
||||
handlers = []
|
||||
if type(vars_files) != list:
|
||||
vars_files = []
|
||||
tasks.extend(new_tasks)
|
||||
handlers.extend(new_handlers)
|
||||
vars_files.extend(new_vars_files)
|
||||
ds['tasks'] = tasks
|
||||
ds['handlers'] = handlers
|
||||
ds['vars_files'] = vars_files
|
||||
|
||||
return ds
|
||||
|
||||
# *************************************************
|
||||
|
||||
def _load_tasks(self, tasks, vars={}, additional_conditions=[], original_file=None):
|
||||
''' handle task and handler include statements '''
|
||||
|
||||
results = []
|
||||
|
@ -116,6 +175,9 @@ class Play(object):
|
|||
raise errors.AnsibleError("expecting dict; got: %s" % x)
|
||||
task_vars = self.vars.copy()
|
||||
task_vars.update(vars)
|
||||
if original_file:
|
||||
task_vars['_original_file'] = original_file
|
||||
|
||||
if 'include' in x:
|
||||
tokens = shlex.split(x['include'])
|
||||
items = ['']
|
||||
|
@ -147,7 +209,7 @@ class Play(object):
|
|||
mv[k] = utils.template(self.basedir, v, mv)
|
||||
include_file = utils.template(self.basedir, tokens[0], mv)
|
||||
data = utils.parse_yaml_from_file(utils.path_dwim(self.basedir, include_file))
|
||||
results += self._load_tasks(data, mv, included_additional_conditions)
|
||||
results += self._load_tasks(data, mv, included_additional_conditions, original_file=include_file)
|
||||
elif type(x) == dict:
|
||||
results.append(Task(self,x,module_vars=task_vars, additional_conditions=additional_conditions))
|
||||
else:
|
||||
|
|
|
@ -56,6 +56,8 @@ class ActionModule(object):
|
|||
for fn in inject.get('first_available_file'):
|
||||
fn = utils.template(self.runner.basedir, fn, inject)
|
||||
fn = utils.path_dwim(self.runner.basedir, fn)
|
||||
if not os.path.exists(fn) and '_original_file' in inject:
|
||||
fn = utils.path_dwim_relative(inject['_original_file'], 'files', fn, self.runner.basedir, check=False)
|
||||
if os.path.exists(fn):
|
||||
source = fn
|
||||
found = True
|
||||
|
@ -76,7 +78,11 @@ class ActionModule(object):
|
|||
source = tmp_content
|
||||
else:
|
||||
source = utils.template(self.runner.basedir, source, inject)
|
||||
source = utils.path_dwim(self.runner.basedir, source)
|
||||
if '_original_file' in inject:
|
||||
source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir)
|
||||
else:
|
||||
source = utils.path_dwim(self.runner.basedir, source)
|
||||
|
||||
|
||||
local_md5 = utils.md5(source)
|
||||
if local_md5 is None:
|
||||
|
|
|
@ -53,10 +53,13 @@ class ActionModule(object):
|
|||
# look up the files and use the first one we find as src
|
||||
|
||||
if 'first_available_file' in inject:
|
||||
|
||||
found = False
|
||||
for fn in self.runner.module_vars.get('first_available_file'):
|
||||
fnt = utils.template(self.runner.basedir, fn, inject)
|
||||
fnd = utils.path_dwim(self.runner.basedir, fnt)
|
||||
if not os.path.exists(fnd) and '_original_file' in inject:
|
||||
fnd = utils.path_dwim_relative(inject['_original_file'], 'templates', fnd, self.runner.basedir, check=False)
|
||||
if os.path.exists(fnd):
|
||||
source = fnt
|
||||
found = True
|
||||
|
@ -66,6 +69,12 @@ class ActionModule(object):
|
|||
return ReturnData(conn=conn, comm_ok=False, result=result)
|
||||
else:
|
||||
source = utils.template(self.runner.basedir, source, inject)
|
||||
|
||||
if '_original_file' in inject:
|
||||
source = utils.path_dwim_relative(inject['_original_file'], 'templates', source, self.runner.basedir)
|
||||
else:
|
||||
source = utils.path_dwim(self.runner.basedir, source)
|
||||
|
||||
|
||||
if dest.endswith("/"):
|
||||
base = os.path.basename(source)
|
||||
|
|
|
@ -195,11 +195,27 @@ def path_dwim(basedir, given):
|
|||
'''
|
||||
|
||||
if given.startswith("/"):
|
||||
return given
|
||||
return os.path.abspath(given)
|
||||
elif given.startswith("~"):
|
||||
return os.path.expanduser(given)
|
||||
return os.path.abspath(os.path.expanduser(given))
|
||||
else:
|
||||
return os.path.join(basedir, given)
|
||||
return os.path.abspath(os.path.join(basedir, given))
|
||||
|
||||
def path_dwim_relative(original, dirname, source, playbook_base, check=True):
|
||||
''' find one file in a directory one level up in a dir named dirname relative to current '''
|
||||
# (used by roles code)
|
||||
|
||||
basedir = os.path.dirname(original)
|
||||
template2 = os.path.join(basedir, '..', dirname, source)
|
||||
source2 = path_dwim(basedir, template2)
|
||||
if os.path.exists(source2):
|
||||
return source2
|
||||
obvious_local_path = path_dwim(playbook_base, source)
|
||||
if os.path.exists(obvious_local_path):
|
||||
return obvious_local_path
|
||||
if check:
|
||||
raise errors.AnsibleError("input file not found at %s or %s" % (source2, obvious_local_path))
|
||||
return source2 # which does not exist
|
||||
|
||||
def json_loads(data):
|
||||
''' parse a JSON string and return a data structure '''
|
||||
|
|
Loading…
Reference in a new issue