Commit 8e5b7d30 by Michael DeHaan

Remove code underlying when_* and only_if, which are deprecated features slated…

Remove code underlying when_* and only_if, which are deprecated features slated for removal in the 1.5 release.
parent 191be7b9
...@@ -3,6 +3,19 @@ Ansible Changes By Release ...@@ -3,6 +3,19 @@ Ansible Changes By Release
## 1.5 "Love Walks In" - Release pending! ## 1.5 "Love Walks In" - Release pending!
Major features/changes:
* when_foo which was previously deprecated is now removed, use "when:" instead. Code generates appropriate error suggestion.
* include + with_items which was previously deprecated is now removed, ditto. Use with_nested / with_together, etc.
* only_if, which is much older than when_foo and was deprecated, is similarly removed.
* ssh_alt connection plugin, much more performant than standard -c ssh, in tree, soon to replace ssh.py (in this release)
New modules:
* Details pending
Misc:
* no_reboot is now defaulted to "no" in the ec2_ami module to ensure filesystem consistency in the resulting AMI. * no_reboot is now defaulted to "no" in the ec2_ami module to ensure filesystem consistency in the resulting AMI.
## 1.4.3 "Could This Be Magic" - December 20, 2013 ## 1.4.3 "Could This Be Magic" - December 20, 2013
......
...@@ -56,8 +56,8 @@ Conditionals ...@@ -56,8 +56,8 @@ Conditionals
++++++++++++ ++++++++++++
A conditional is an expression that evaluates to true or false that decides whether a given task will be executed on a given A conditional is an expression that evaluates to true or false that decides whether a given task will be executed on a given
machine or not. Ansible's conditionals include 'when_boolean', machine or not. Ansible's conditionals are powered by the 'when' statement, and are
'when_string', and 'when_integer'. These are discussed in the playbook documentation. discussed in the playbook documentation.
Diff Mode Diff Mode
+++++++++ +++++++++
...@@ -220,11 +220,6 @@ JSON ...@@ -220,11 +220,6 @@ JSON
Ansible uses JSON for return data from remote modules. This allows modules to be written in any language, not just Python. Ansible uses JSON for return data from remote modules. This allows modules to be written in any language, not just Python.
only_if
+++++++
A deprecated form of the "when:" statement. It should no longer be used.
Library Library
+++++++ +++++++
......
...@@ -310,7 +310,7 @@ class PlayBook(object): ...@@ -310,7 +310,7 @@ class PlayBook(object):
remote_port=task.play.remote_port, module_vars=task.module_vars, remote_port=task.play.remote_port, module_vars=task.module_vars,
default_vars=task.default_vars, private_key_file=self.private_key_file, default_vars=task.default_vars, private_key_file=self.private_key_file,
setup_cache=self.SETUP_CACHE, basedir=task.play.basedir, setup_cache=self.SETUP_CACHE, basedir=task.play.basedir,
conditional=task.only_if, callbacks=self.runner_callbacks, conditional=task.when, callbacks=self.runner_callbacks,
sudo=task.sudo, sudo_user=task.sudo_user, sudo=task.sudo, sudo_user=task.sudo_user,
transport=task.transport, sudo_pass=task.sudo_pass, is_playbook=True, transport=task.transport, sudo_pass=task.sudo_pass, is_playbook=True,
check=self.check, diff=self.diff, environment=task.environment, complex_args=task.args, check=self.check, diff=self.diff, environment=task.environment, complex_args=task.args,
......
...@@ -489,11 +489,11 @@ class Play(object): ...@@ -489,11 +489,11 @@ class Play(object):
utils.deprecated("\"when_<criteria>:\" is a removed deprecated feature, use the simplified 'when:' conditional directly", None, removed=True) utils.deprecated("\"when_<criteria>:\" is a removed deprecated feature, use the simplified 'when:' conditional directly", None, removed=True)
elif k == 'when': elif k == 'when':
if type(x[k]) is str: if type(x[k]) is str:
included_additional_conditions.insert(0, utils.compile_when_to_only_if("jinja2_compare %s" % x[k])) included_additional_conditions.insert(0, x[k])
elif type(x[k]) is list: elif type(x[k]) is list:
for i in x[k]: for i in x[k]:
included_additional_conditions.insert(0, utils.compile_when_to_only_if("jinja2_compare %s" % i)) included_additional_conditions.insert(0, i)
elif k in ("include", "vars", "default_vars", "only_if", "sudo", "sudo_user", "role_name"): elif k in ("include", "vars", "default_vars", "sudo", "sudo_user", "role_name"):
continue continue
else: else:
include_vars[k] = x[k] include_vars[k] = x[k]
...@@ -511,8 +511,8 @@ class Play(object): ...@@ -511,8 +511,8 @@ class Play(object):
if 'vars' in x: if 'vars' in x:
task_vars = utils.combine_vars(task_vars, x['vars']) task_vars = utils.combine_vars(task_vars, x['vars'])
if 'only_if' in x: if 'when' in x:
included_additional_conditions.append(x['only_if']) included_additional_conditions.append(x['when'])
new_role = None new_role = None
if 'role_name' in x: if 'role_name' in x:
......
...@@ -24,7 +24,7 @@ import sys ...@@ -24,7 +24,7 @@ import sys
class Task(object): class Task(object):
__slots__ = [ __slots__ = [
'name', 'meta', 'action', 'only_if', 'when', 'async_seconds', 'async_poll_interval', 'name', 'meta', 'action', 'when', 'async_seconds', 'async_poll_interval',
'notify', 'module_name', 'module_args', 'module_vars', 'default_vars', 'notify', 'module_name', 'module_args', 'module_vars', 'default_vars',
'play', 'notified_by', 'tags', 'register', 'role_name', 'play', 'notified_by', 'tags', 'register', 'role_name',
'delegate_to', 'first_available_file', 'ignore_errors', 'delegate_to', 'first_available_file', 'ignore_errors',
...@@ -35,7 +35,7 @@ class Task(object): ...@@ -35,7 +35,7 @@ class Task(object):
# to prevent typos and such # to prevent typos and such
VALID_KEYS = [ VALID_KEYS = [
'name', 'meta', 'action', 'only_if', 'async', 'poll', 'notify', 'name', 'meta', 'action', 'when', 'async', 'poll', 'notify',
'first_available_file', 'include', 'tags', 'register', 'ignore_errors', 'first_available_file', 'include', 'tags', 'register', 'ignore_errors',
'delegate_to', 'local_action', 'transport', 'remote_user', 'sudo', 'sudo_user', 'delegate_to', 'local_action', 'transport', 'remote_user', 'sudo', 'sudo_user',
'sudo_pass', 'when', 'connection', 'environment', 'args', 'sudo_pass', 'when', 'connection', 'environment', 'args',
...@@ -96,7 +96,6 @@ class Task(object): ...@@ -96,7 +96,6 @@ class Task(object):
elif x in [ 'changed_when', 'failed_when', 'when']: elif x in [ 'changed_when', 'failed_when', 'when']:
if isinstance(ds[x], basestring) and ds[x].lstrip().startswith("{{"): if isinstance(ds[x], basestring) and ds[x].lstrip().startswith("{{"):
utils.warning("It is unneccessary to use '{{' in conditionals, leave variables in loop expressions bare.") utils.warning("It is unneccessary to use '{{' in conditionals, leave variables in loop expressions bare.")
ds[x] = "jinja2_compare %s" % (ds[x])
elif x.startswith("when_"): elif x.startswith("when_"):
utils.deprecated("The 'when_' conditional has been removed. Switch to using the regular unified 'when' statements as described in ansibleworks.com/docs/.","1.5", removed=True) utils.deprecated("The 'when_' conditional has been removed. Switch to using the regular unified 'when' statements as described in ansibleworks.com/docs/.","1.5", removed=True)
...@@ -128,8 +127,8 @@ class Task(object): ...@@ -128,8 +127,8 @@ class Task(object):
self.module_vars['delay'] = ds.get('delay', 5) self.module_vars['delay'] = ds.get('delay', 5)
self.module_vars['retries'] = ds.get('retries', 3) self.module_vars['retries'] = ds.get('retries', 3)
self.module_vars['register'] = ds.get('register', None) self.module_vars['register'] = ds.get('register', None)
self.until = "jinja2_compare %s" % (ds.get('until')) self.until = ds.get('until')
self.module_vars['until'] = utils.compile_when_to_only_if(self.until) self.module_vars['until'] = self.until
# rather than simple key=value args on the options line, these represent structured data and the values # rather than simple key=value args on the options line, these represent structured data and the values
# can be hashes and lists, not just scalars # can be hashes and lists, not just scalars
...@@ -188,22 +187,10 @@ class Task(object): ...@@ -188,22 +187,10 @@ class Task(object):
self.name = self.action self.name = self.action
# load various attributes # load various attributes
self.only_if = ds.get('only_if', 'True')
if self.only_if != 'True':
utils.deprecated("only_if is a very old feature and has been obsolete since 0.9, please switch to the 'when' conditional as described at http://ansibleworks.com/docs","1.5",removed=True)
self.when = ds.get('when', None) self.when = ds.get('when', None)
self.changed_when = ds.get('changed_when', None) self.changed_when = ds.get('changed_when', None)
if self.changed_when is not None:
self.changed_when = utils.compile_when_to_only_if(self.changed_when)
self.failed_when = ds.get('failed_when', None) self.failed_when = ds.get('failed_when', None)
if self.failed_when is not None:
self.failed_when = utils.compile_when_to_only_if(self.failed_when)
self.async_seconds = int(ds.get('async', 0)) # not async by default self.async_seconds = int(ds.get('async', 0)) # not async by default
self.async_poll_interval = int(ds.get('poll', 10)) # default poll = 10 seconds self.async_poll_interval = int(ds.get('poll', 10)) # default poll = 10 seconds
self.notify = ds.get('notify', []) self.notify = ds.get('notify', [])
...@@ -276,12 +263,7 @@ class Task(object): ...@@ -276,12 +263,7 @@ class Task(object):
self.tags.extend(apply_tags) self.tags.extend(apply_tags)
self.tags.extend(import_tags) self.tags.extend(import_tags)
if self.when is not None:
if self.only_if != 'True':
raise errors.AnsibleError('when obsoletes only_if, only use one or the other')
self.only_if = utils.compile_when_to_only_if(self.when)
if additional_conditions: if additional_conditions:
new_conditions = additional_conditions new_conditions = additional_conditions
new_conditions.append(self.only_if) new_conditions.append(self.when)
self.only_if = new_conditions self.when = new_conditions
...@@ -1067,6 +1067,6 @@ class Runner(object): ...@@ -1067,6 +1067,6 @@ class Runner(object):
if self.always_run is None: if self.always_run is None:
self.always_run = self.module_vars.get('always_run', False) self.always_run = self.module_vars.get('always_run', False)
self.always_run = check_conditional( self.always_run = check_conditional(
self.always_run, self.basedir, inject, fail_on_undefined=True, jinja2=True) self.always_run, self.basedir, inject, fail_on_undefined=True)
return (self.check and not self.always_run) return (self.check and not self.always_run)
...@@ -163,18 +163,17 @@ def is_changed(result): ...@@ -163,18 +163,17 @@ def is_changed(result):
return (result.get('changed', False) in [ True, 'True', 'true']) return (result.get('changed', False) in [ True, 'True', 'true'])
def check_conditional(conditional, basedir, inject, fail_on_undefined=False, jinja2=False): def check_conditional(conditional, basedir, inject, fail_on_undefined=False):
if isinstance(conditional, list): if isinstance(conditional, list):
for x in conditional: for x in conditional:
if not check_conditional(x, basedir, inject, fail_on_undefined=fail_on_undefined, jinja2=jinja2): if not check_conditional(x, basedir, inject, fail_on_undefined=fail_on_undefined):
return False return False
return True return True
if jinja2: if not isinstance(conditional, basestring):
conditional = "jinja2_compare %s" % conditional return conditional
if conditional.startswith("jinja2_compare"):
conditional = conditional.replace("jinja2_compare ","") conditional = conditional.replace("jinja2_compare ","")
# allow variable names # allow variable names
if conditional in inject and str(inject[conditional]).find('-') == -1: if conditional in inject and str(inject[conditional]).find('-') == -1:
...@@ -203,19 +202,6 @@ def check_conditional(conditional, basedir, inject, fail_on_undefined=False, jin ...@@ -203,19 +202,6 @@ def check_conditional(conditional, basedir, inject, fail_on_undefined=False, jin
else: else:
raise errors.AnsibleError("unable to evaluate conditional: %s" % original) raise errors.AnsibleError("unable to evaluate conditional: %s" % original)
if not isinstance(conditional, basestring):
return conditional
try:
conditional = conditional.replace("\n", "\\n")
result = safe_eval(conditional)
if result not in [ True, False ]:
raise errors.AnsibleError("Conditional expression must evaluate to True or False: %s" % conditional)
return result
except (NameError, SyntaxError):
raise errors.AnsibleError("Could not evaluate the expression: (%s)" % conditional)
def is_executable(path): def is_executable(path):
'''is the given path executable?''' '''is the given path executable?'''
return (stat.S_IXUSR & os.stat(path)[stat.ST_MODE] return (stat.S_IXUSR & os.stat(path)[stat.ST_MODE]
...@@ -756,86 +742,6 @@ def boolean(value): ...@@ -756,86 +742,6 @@ 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: failed $json_result
# when: changed $json_result
# when: int $x >= $z and $y < 3
# when: int $x in $alist
# when: float $x > 2 and $y <= $z
# when: str $x != $y
# when: jinja2_compare asdf # implies {{ asdf }}
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' ]:
tcopy = tokens[1:]
for (i,t) in enumerate(tokens[1:]):
if t.find("$") != -1:
tcopy[i] = "is_%s('''%s''')" % (tokens[0], t)
else:
tcopy[i] = t
return " ".join(tcopy)
# when_failed / when_changed
elif tokens[0] in [ 'failed', 'changed' ]:
tcopy = tokens[1:]
for (i,t) in enumerate(tokens[1:]):
if t.find("$") != -1:
tcopy[i] = "is_%s(%s)" % (tokens[0], t)
else:
tcopy[i] = t
return " ".join(tcopy)
# 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 re.search(t, r"^\w"):
# bare word will turn into Jinja2 so all the above
# casting is really not needed
#tcopy[i] = "%s('''%s''')" % (cast, t)
t2 = t.strip()
if (t2[0].isalpha() or t2[0] == '$') and cast == 'str' and t2 != 'in':
tcopy[i] = "'%s'" % (t)
else:
tcopy[i] = t
result = " ".join(tcopy)
return result
# 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)
# the stock 'when' without qualification (new in 1.2), assumes Jinja2 terms
elif tokens[0] == 'jinja2_compare':
return " ".join(tokens)
else:
raise errors.AnsibleError("invalid usage of when_ operator: %s" % expression)
def make_sudo_cmd(sudo_user, executable, cmd): def make_sudo_cmd(sudo_user, executable, cmd):
""" """
helper function for connection plugins to create sudo commands helper function for connection plugins to create sudo commands
......
...@@ -112,27 +112,27 @@ class TestUtils(unittest.TestCase): ...@@ -112,27 +112,27 @@ class TestUtils(unittest.TestCase):
# boolean # boolean
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare true', '/', {}) == True) 'true', '/', {}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare false', '/', {}) == False) 'false', '/', {}) == False)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare True', '/', {}) == True) 'True', '/', {}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare False', '/', {}) == False) 'False', '/', {}) == False)
# integer # integer
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare 1', '/', {}) == True) '1', '/', {}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare 0', '/', {}) == False) '0', '/', {}) == False)
# string, beware, a string is truthy unless empty # string, beware, a string is truthy unless empty
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare "yes"', '/', {}) == True) '"yes"', '/', {}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare "no"', '/', {}) == True) '"no"', '/', {}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare ""', '/', {}) == False) '""', '/', {}) == False)
def test_check_conditional_jinja2_variable_literals(self): def test_check_conditional_jinja2_variable_literals(self):
...@@ -140,61 +140,61 @@ class TestUtils(unittest.TestCase): ...@@ -140,61 +140,61 @@ class TestUtils(unittest.TestCase):
# boolean # boolean
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': 'True'}) == True) 'var', '/', {'var': 'True'}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': 'true'}) == True) 'var', '/', {'var': 'true'}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': 'False'}) == False) 'var', '/', {'var': 'False'}) == False)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': 'false'}) == False) 'var', '/', {'var': 'false'}) == False)
# integer # integer
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': '1'}) == True) 'var', '/', {'var': '1'}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': 1}) == True) 'var', '/', {'var': 1}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': '0'}) == False) 'var', '/', {'var': '0'}) == False)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': 0}) == False) 'var', '/', {'var': 0}) == False)
# string, beware, a string is truthy unless empty # string, beware, a string is truthy unless empty
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': '"yes"'}) == True) 'var', '/', {'var': '"yes"'}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': '"no"'}) == True) 'var', '/', {'var': '"no"'}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': '""'}) == False) 'var', '/', {'var': '""'}) == False)
# Python boolean in Jinja2 expression # Python boolean in Jinja2 expression
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': True}) == True) 'var', '/', {'var': True}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': False}) == False) 'var', '/', {'var': False}) == False)
def test_check_conditional_jinja2_expression(self): def test_check_conditional_jinja2_expression(self):
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare 1 == 1', '/', {}) == True) '1 == 1', '/', {}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare bar == 42', '/', {'bar': 42}) == True) 'bar == 42', '/', {'bar': 42}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare bar != 42', '/', {'bar': 42}) == False) 'bar != 42', '/', {'bar': 42}) == False)
def test_check_conditional_jinja2_expression_in_variable(self): def test_check_conditional_jinja2_expression_in_variable(self):
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': '1 == 1'}) == True) 'var', '/', {'var': '1 == 1'}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': 'bar == 42', 'bar': 42}) == True) 'var', '/', {'var': 'bar == 42', 'bar': 42}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
'jinja2_compare var', '/', {'var': 'bar != 42', 'bar': 42}) == False) 'var', '/', {'var': 'bar != 42', 'bar': 42}) == False)
def test_check_conditional_jinja2_unicode(self): def test_check_conditional_jinja2_unicode(self):
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
u'jinja2_compare "\u00df"', '/', {}) == True) u'"\u00df"', '/', {}) == True)
assert(ansible.utils.check_conditional( assert(ansible.utils.check_conditional(
u'jinja2_compare var == "\u00df"', '/', {'var': u'\u00df'}) == True) u'var == "\u00df"', '/', {'var': u'\u00df'}) == True)
##################################### #####################################
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment