Change the way we do with_items to make them happen next to each other in runner, which eliminates the problem of with_items and vars_files sometimes not playing nice with each other.
(Also a fix for the user module error handling when the user is not present at the time of the return. This can only really be caused by multiple ansible executions).pull/4420/head
parent
6c84ec72c6
commit
64c51ade1e
|
@ -104,17 +104,15 @@ class Play(object):
|
||||||
for y in data:
|
for y in data:
|
||||||
items = y.get('with_items',None)
|
items = y.get('with_items',None)
|
||||||
if items is None:
|
if items is None:
|
||||||
items = [ '' ]
|
items = [ ]
|
||||||
elif isinstance(items, basestring):
|
elif isinstance(items, basestring):
|
||||||
items = utils.varLookup(items, task_vars)
|
#items = utils.varLookup(items, task_vars)
|
||||||
for item in items:
|
if type(items) != list:
|
||||||
item = utils.template(item, task_vars)
|
raise errors.AnsibleError("with_items must be a list, got: %s" % items)
|
||||||
if self._has_vars_in(item):
|
# items = [ utils.template(item, task_vars) for item in items]
|
||||||
raise errors.AnsibleError("parse error: unbound variable in with_items: %s" % item)
|
mv = task_vars.copy()
|
||||||
|
mv['items'] = items
|
||||||
mv = task_vars.copy()
|
results.append(Task(self,y,module_vars=mv))
|
||||||
mv['item'] = item
|
|
||||||
results.append(Task(self,y,module_vars=mv))
|
|
||||||
|
|
||||||
for x in results:
|
for x in results:
|
||||||
if self.tags is not None:
|
if self.tags is not None:
|
||||||
|
@ -245,6 +243,8 @@ class Play(object):
|
||||||
if host is not None:
|
if host is not None:
|
||||||
filename3 = utils.template(filename2, self.playbook.SETUP_CACHE[host])
|
filename3 = utils.template(filename2, self.playbook.SETUP_CACHE[host])
|
||||||
filename4 = utils.path_dwim(self.playbook.basedir, filename3)
|
filename4 = utils.path_dwim(self.playbook.basedir, filename3)
|
||||||
|
if self._has_vars_in(filename4):
|
||||||
|
return
|
||||||
new_vars = utils.parse_yaml_from_file(filename4)
|
new_vars = utils.parse_yaml_from_file(filename4)
|
||||||
if new_vars:
|
if new_vars:
|
||||||
if type(new_vars) != dict:
|
if type(new_vars) != dict:
|
||||||
|
|
|
@ -71,13 +71,12 @@ def _executor_hook(job_queue, result_queue):
|
||||||
|
|
||||||
class ReturnData(object):
|
class ReturnData(object):
|
||||||
|
|
||||||
__slots__ = [ 'result', 'comm_ok', 'executed_str', 'host' ]
|
__slots__ = [ 'result', 'comm_ok', 'host' ]
|
||||||
|
|
||||||
def __init__(self, host=None, result=None, comm_ok=True, executed_str=''):
|
def __init__(self, host=None, result=None, comm_ok=True):
|
||||||
self.host = host
|
self.host = host
|
||||||
self.result = result
|
self.result = result
|
||||||
self.comm_ok = comm_ok
|
self.comm_ok = comm_ok
|
||||||
self.executed_str = executed_str
|
|
||||||
|
|
||||||
if type(self.result) in [ str, unicode ]:
|
if type(self.result) in [ str, unicode ]:
|
||||||
self.result = utils.parse_json(self.result)
|
self.result = utils.parse_json(self.result)
|
||||||
|
@ -135,7 +134,7 @@ class Runner(object):
|
||||||
conditional : only execute if this string, evaluated, is True
|
conditional : only execute if this string, evaluated, is True
|
||||||
callbacks : output callback class
|
callbacks : output callback class
|
||||||
sudo : log in as remote user and immediately sudo to root
|
sudo : log in as remote user and immediately sudo to root
|
||||||
module_vars : provides additional variables to a template. FIXME: factor this out
|
module_vars : provides additional variables to a template.
|
||||||
is_playbook : indicates Runner is being used by a playbook. affects behavior in various ways.
|
is_playbook : indicates Runner is being used by a playbook. affects behavior in various ways.
|
||||||
inventory : inventory object, if host_list is not provided
|
inventory : inventory object, if host_list is not provided
|
||||||
"""
|
"""
|
||||||
|
@ -283,6 +282,55 @@ class Runner(object):
|
||||||
def _execute_module(self, conn, tmp, remote_module_path, args,
|
def _execute_module(self, conn, tmp, remote_module_path, args,
|
||||||
async_jid=None, async_module=None, async_limit=None):
|
async_jid=None, async_module=None, async_limit=None):
|
||||||
|
|
||||||
|
items = self.module_vars.get('items', None)
|
||||||
|
if items is None or len(items) == 0:
|
||||||
|
# executing a single item
|
||||||
|
return self._execute_module_internal(
|
||||||
|
conn, tmp, remote_module_path, args,
|
||||||
|
async_jid=async_jid, async_module=async_module, async_limit=async_limit
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# executing using with_items, so make multiple calls
|
||||||
|
# TODO: refactor
|
||||||
|
aggregrate = {}
|
||||||
|
all_comm_ok = True
|
||||||
|
all_changed = False
|
||||||
|
all_failed = False
|
||||||
|
results = []
|
||||||
|
for x in items:
|
||||||
|
self.module_vars['item'] = x
|
||||||
|
result = self._execute_module_internal(
|
||||||
|
conn, tmp, remote_module_path, args,
|
||||||
|
async_jid=async_jid, async_module=async_module, async_limit=async_limit
|
||||||
|
)
|
||||||
|
results.append(result.result)
|
||||||
|
if result.comm_ok == False:
|
||||||
|
all_comm_ok = False
|
||||||
|
break
|
||||||
|
for x in results:
|
||||||
|
if x.get('changed') == True:
|
||||||
|
all_changed = True
|
||||||
|
if (x.get('failed') == True) or (('rc' in x) and (x['rc'] != 0)):
|
||||||
|
all_failed = True
|
||||||
|
break
|
||||||
|
msg = 'All items succeeded'
|
||||||
|
if all_failed:
|
||||||
|
msg = "One or more items failed."
|
||||||
|
rd_result = dict(
|
||||||
|
failed = all_failed,
|
||||||
|
changed = all_changed,
|
||||||
|
results = results,
|
||||||
|
msg = msg
|
||||||
|
)
|
||||||
|
if not all_failed:
|
||||||
|
del rd_result['failed']
|
||||||
|
return ReturnData(host=conn.host, comm_ok=all_comm_ok, result=rd_result)
|
||||||
|
|
||||||
|
# *****************************************************
|
||||||
|
|
||||||
|
def _execute_module_internal(self, conn, tmp, remote_module_path, args,
|
||||||
|
async_jid=None, async_module=None, async_limit=None):
|
||||||
|
|
||||||
''' runs a module that has already been transferred '''
|
''' runs a module that has already been transferred '''
|
||||||
|
|
||||||
inject = self.setup_cache.get(conn.host,{}).copy()
|
inject = self.setup_cache.get(conn.host,{}).copy()
|
||||||
|
@ -304,6 +352,7 @@ class Runner(object):
|
||||||
|
|
||||||
if type(args) == dict:
|
if type(args) == dict:
|
||||||
args = utils.bigjson(args)
|
args = utils.bigjson(args)
|
||||||
|
|
||||||
args = utils.template(args, inject, self.setup_cache)
|
args = utils.template(args, inject, self.setup_cache)
|
||||||
|
|
||||||
module_name_tail = remote_module_path.split("/")[-1]
|
module_name_tail = remote_module_path.split("/")[-1]
|
||||||
|
@ -316,9 +365,7 @@ class Runner(object):
|
||||||
|
|
||||||
res = self._low_level_exec_command(conn, cmd, tmp, sudoable=True)
|
res = self._low_level_exec_command(conn, cmd, tmp, sudoable=True)
|
||||||
|
|
||||||
executed_str = "%s %s" % (module_name_tail, args.strip())
|
return ReturnData(host=conn.host, result=res)
|
||||||
|
|
||||||
return ReturnData(host=conn.host, result=res, executed_str=executed_str)
|
|
||||||
|
|
||||||
# *****************************************************
|
# *****************************************************
|
||||||
|
|
||||||
|
@ -597,7 +644,6 @@ class Runner(object):
|
||||||
|
|
||||||
# modify file attribs if needed
|
# modify file attribs if needed
|
||||||
if exec_rc.comm_ok:
|
if exec_rc.comm_ok:
|
||||||
exec_rc.executed_str = exec_rc.executed_str.replace("copy","template",1)
|
|
||||||
return self._chain_file_module(conn, tmp, exec_rc, options)
|
return self._chain_file_module(conn, tmp, exec_rc, options)
|
||||||
else:
|
else:
|
||||||
return exec_rc
|
return exec_rc
|
||||||
|
|
|
@ -54,6 +54,13 @@ def add_user_info(kwargs):
|
||||||
if user_exists(name):
|
if user_exists(name):
|
||||||
kwargs['state'] = 'present'
|
kwargs['state'] = 'present'
|
||||||
info = user_info(name)
|
info = user_info(name)
|
||||||
|
if info == False:
|
||||||
|
if 'failed' in kwargs:
|
||||||
|
kwargs['notice'] = "failed to look up user name: %s" % name
|
||||||
|
else:
|
||||||
|
kwargs['msg'] = "failed to look up user name: %s" % name
|
||||||
|
kwargs['failed'] = True
|
||||||
|
return kwargs
|
||||||
kwargs['uid'] = info[2]
|
kwargs['uid'] = info[2]
|
||||||
kwargs['group'] = info[3]
|
kwargs['group'] = info[3]
|
||||||
kwargs['comment'] = info[4]
|
kwargs['comment'] = info[4]
|
||||||
|
|
Loading…
Reference in New Issue