mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-04-26 04:11:25 -07:00
Allow only_if/when_* on task includes and apply it on all tasks within
This commit is contained in:
parent
07b215d4fa
commit
caee51e90e
3 changed files with 75 additions and 72 deletions
|
@ -97,7 +97,7 @@ class Play(object):
|
||||||
|
|
||||||
# *************************************************
|
# *************************************************
|
||||||
|
|
||||||
def _load_tasks(self, tasks, vars={}):
|
def _load_tasks(self, tasks, vars={}, additional_conditions=[]):
|
||||||
''' handle task and handler include statements '''
|
''' handle task and handler include statements '''
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
@ -107,20 +107,25 @@ class Play(object):
|
||||||
if 'include' in x:
|
if 'include' in x:
|
||||||
tokens = shlex.split(x['include'])
|
tokens = shlex.split(x['include'])
|
||||||
items = ['']
|
items = ['']
|
||||||
|
included_additional_conditions = list(additional_conditions)
|
||||||
for k in x:
|
for k in x:
|
||||||
if not k.startswith("with_"):
|
if k.startswith("with_"):
|
||||||
if k in ("include", "vars"):
|
plugin_name = k[5:]
|
||||||
continue
|
if plugin_name not in utils.plugins.lookup_loader:
|
||||||
else:
|
raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name))
|
||||||
raise errors.AnsibleError("parse error: task includes cannot be used with other directives: %s" % k)
|
terms = utils.template_ds(self.basedir, x[k], task_vars)
|
||||||
plugin_name = k[5:]
|
items = utils.plugins.lookup_loader.get(plugin_name, basedir=self.basedir, runner=None).run(terms, inject=task_vars)
|
||||||
if plugin_name not in utils.plugins.lookup_loader:
|
elif k.startswith("when_"):
|
||||||
raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name))
|
included_additional_conditions.append(utils.compile_when_to_only_if("%s %s" % (k[5:], x[k])))
|
||||||
terms = utils.template_ds(self.basedir, x[k], task_vars)
|
elif k in ("include", "vars", "only_if"):
|
||||||
items = utils.plugins.lookup_loader.get(plugin_name, basedir=self.basedir, runner=None).run(terms, inject=task_vars)
|
pass
|
||||||
|
else:
|
||||||
|
raise errors.AnsibleError("parse error: task includes cannot be used with other directives: %s" % k)
|
||||||
|
|
||||||
if 'vars' in x:
|
if 'vars' in x:
|
||||||
task_vars.update(x['vars'])
|
task_vars.update(x['vars'])
|
||||||
|
if 'only_if' in x:
|
||||||
|
included_additional_conditions.append(x['only_if'])
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
mv = task_vars.copy()
|
mv = task_vars.copy()
|
||||||
|
@ -130,9 +135,9 @@ class Play(object):
|
||||||
mv[k] = utils.template_ds(self.basedir, v, mv)
|
mv[k] = utils.template_ds(self.basedir, v, mv)
|
||||||
include_file = utils.template(self.basedir, tokens[0], mv)
|
include_file = utils.template(self.basedir, tokens[0], mv)
|
||||||
data = utils.parse_yaml_from_file(utils.path_dwim(self.basedir, include_file))
|
data = utils.parse_yaml_from_file(utils.path_dwim(self.basedir, include_file))
|
||||||
results += self._load_tasks(data, mv)
|
results += self._load_tasks(data, mv, included_additional_conditions)
|
||||||
elif type(x) == dict:
|
elif type(x) == dict:
|
||||||
results.append(Task(self,x,module_vars=task_vars))
|
results.append(Task(self,x,module_vars=task_vars, additional_conditions=additional_conditions))
|
||||||
else:
|
else:
|
||||||
raise Exception("unexpected task type")
|
raise Exception("unexpected task type")
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Task(object):
|
||||||
'sudo_pass', 'when'
|
'sudo_pass', 'when'
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, play, ds, module_vars=None):
|
def __init__(self, play, ds, module_vars=None, additional_conditions=None):
|
||||||
''' constructor loads from a task or handler datastructure '''
|
''' constructor loads from a task or handler datastructure '''
|
||||||
|
|
||||||
for x in ds.keys():
|
for x in ds.keys():
|
||||||
|
@ -182,63 +182,8 @@ class Task(object):
|
||||||
if self.when is not None:
|
if self.when is not None:
|
||||||
if self.only_if != 'True':
|
if self.only_if != 'True':
|
||||||
raise errors.AnsibleError('when obsoletes only_if, only use one or the other')
|
raise errors.AnsibleError('when obsoletes only_if, only use one or the other')
|
||||||
self.only_if = self.compile_when_to_only_if(self.when)
|
self.only_if = utils.compile_when_to_only_if(self.when)
|
||||||
|
|
||||||
def compile_when_to_only_if(self, expression):
|
|
||||||
'''
|
|
||||||
when is a shorthand for writing only_if conditionals. It requires less quoting
|
|
||||||
magic. only_if is retained for backwards compatibility.
|
|
||||||
'''
|
|
||||||
|
|
||||||
# when: set $variable
|
|
||||||
# when: unset $variable
|
|
||||||
# when: int $x >= $z and $y < 3
|
|
||||||
# when: int $x in $alist
|
|
||||||
# when: float $x > 2 and $y <= $z
|
|
||||||
# when: str $x != $y
|
|
||||||
|
|
||||||
if type(expression) not in [ str, unicode ]:
|
|
||||||
raise errors.AnsibleError("invalid usage of when_ operator: %s" % expression)
|
|
||||||
tokens = expression.split()
|
|
||||||
if len(tokens) < 2:
|
|
||||||
raise errors.AnsibleError("invalid usage of when_ operator: %s" % expression)
|
|
||||||
|
|
||||||
# when_set / when_unset
|
|
||||||
if tokens[0] in [ 'set', 'unset' ]:
|
|
||||||
if len(tokens) != 2:
|
|
||||||
raise errors.AnsibleError("usage: when: <set|unset> <$variableName>")
|
|
||||||
return "is_%s('''%s''')" % (tokens[0], tokens[1])
|
|
||||||
|
|
||||||
# when_integer / when_float / when_string
|
|
||||||
elif tokens[0] in [ 'integer', 'float', 'string' ]:
|
|
||||||
cast = None
|
|
||||||
if tokens[0] == 'integer':
|
|
||||||
cast = 'int'
|
|
||||||
elif tokens[0] == 'string':
|
|
||||||
cast = 'str'
|
|
||||||
elif tokens[0] == 'float':
|
|
||||||
cast = 'float'
|
|
||||||
tcopy = tokens[1:]
|
|
||||||
for (i,t) in enumerate(tokens[1:]):
|
|
||||||
if t.find("$") != -1:
|
|
||||||
# final variable substitution will happen in Runner code
|
|
||||||
tcopy[i] = "%s('''%s''')" % (cast, t)
|
|
||||||
else:
|
|
||||||
tcopy[i] = t
|
|
||||||
return " ".join(tcopy)
|
|
||||||
|
|
||||||
# when_boolean
|
|
||||||
elif tokens[0] in [ 'bool', 'boolean' ]:
|
|
||||||
tcopy = tokens[1:]
|
|
||||||
for (i, t) in enumerate(tcopy):
|
|
||||||
if t.find("$") != -1:
|
|
||||||
tcopy[i] = "(is_set('''%s''') and '''%s'''.lower() not in ('false', 'no', 'n', 'none', '0', ''))" % (t, t)
|
|
||||||
return " ".join(tcopy)
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise errors.AnsibleError("invalid usage of when_ operator: %s" % expression)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if additional_conditions:
|
||||||
|
self.only_if = '(' + self.only_if + ') and (' + ' ) and ('.join(additional_conditions) + ')'
|
||||||
|
|
||||||
|
|
|
@ -476,4 +476,57 @@ def boolean(value):
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def compile_when_to_only_if(expression):
|
||||||
|
'''
|
||||||
|
when is a shorthand for writing only_if conditionals. It requires less quoting
|
||||||
|
magic. only_if is retained for backwards compatibility.
|
||||||
|
'''
|
||||||
|
|
||||||
|
# when: set $variable
|
||||||
|
# when: unset $variable
|
||||||
|
# when: int $x >= $z and $y < 3
|
||||||
|
# when: int $x in $alist
|
||||||
|
# when: float $x > 2 and $y <= $z
|
||||||
|
# when: str $x != $y
|
||||||
|
|
||||||
|
if type(expression) not in [ str, unicode ]:
|
||||||
|
raise errors.AnsibleError("invalid usage of when_ operator: %s" % expression)
|
||||||
|
tokens = expression.split()
|
||||||
|
if len(tokens) < 2:
|
||||||
|
raise errors.AnsibleError("invalid usage of when_ operator: %s" % expression)
|
||||||
|
|
||||||
|
# when_set / when_unset
|
||||||
|
if tokens[0] in [ 'set', 'unset' ]:
|
||||||
|
if len(tokens) != 2:
|
||||||
|
raise errors.AnsibleError("usage: when: <set|unset> <$variableName>")
|
||||||
|
return "is_%s('''%s''')" % (tokens[0], tokens[1])
|
||||||
|
|
||||||
|
# when_integer / when_float / when_string
|
||||||
|
elif tokens[0] in [ 'integer', 'float', 'string' ]:
|
||||||
|
cast = None
|
||||||
|
if tokens[0] == 'integer':
|
||||||
|
cast = 'int'
|
||||||
|
elif tokens[0] == 'string':
|
||||||
|
cast = 'str'
|
||||||
|
elif tokens[0] == 'float':
|
||||||
|
cast = 'float'
|
||||||
|
tcopy = tokens[1:]
|
||||||
|
for (i,t) in enumerate(tokens[1:]):
|
||||||
|
if t.find("$") != -1:
|
||||||
|
# final variable substitution will happen in Runner code
|
||||||
|
tcopy[i] = "%s('''%s''')" % (cast, t)
|
||||||
|
else:
|
||||||
|
tcopy[i] = t
|
||||||
|
return " ".join(tcopy)
|
||||||
|
|
||||||
|
# when_boolean
|
||||||
|
elif tokens[0] in [ 'bool', 'boolean' ]:
|
||||||
|
tcopy = tokens[1:]
|
||||||
|
for (i, t) in enumerate(tcopy):
|
||||||
|
if t.find("$") != -1:
|
||||||
|
tcopy[i] = "(is_set('''%s''') and '''%s'''.lower() not in ('false', 'no', 'n', 'none', '0', ''))" % (t, t)
|
||||||
|
return " ".join(tcopy)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise errors.AnsibleError("invalid usage of when_ operator: %s" % expression)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue