diff --git a/lib/ansible/callbacks.py b/lib/ansible/callbacks.py index 800d6e551bb..1322a53b10d 100644 --- a/lib/ansible/callbacks.py +++ b/lib/ansible/callbacks.py @@ -421,7 +421,11 @@ class CliRunnerCallbacks(DefaultRunnerCallbacks): class PlaybookRunnerCallbacks(DefaultRunnerCallbacks): ''' callbacks used for Runner() from /usr/bin/ansible-playbook ''' - def __init__(self, stats, verbose=utils.VERBOSITY): + def __init__(self, stats, verbose=None): + + if verbose is None: + verbose = utils.VERBOSITY + self.verbose = verbose self.stats = stats self._async_notified = {} diff --git a/lib/ansible/constants.py b/lib/ansible/constants.py index 9c3623892ec..b84bb0777ba 100644 --- a/lib/ansible/constants.py +++ b/lib/ansible/constants.py @@ -133,6 +133,11 @@ DEFAULT_LOG_PATH = shell_expand_path(get_config(p, DEFAULTS, 'log_ ANSIBLE_NOCOLOR = get_config(p, DEFAULTS, 'nocolor', 'ANSIBLE_NOCOLOR', None, boolean=True) ANSIBLE_NOCOWS = get_config(p, DEFAULTS, 'nocows', 'ANSIBLE_NOCOWS', None, boolean=True) DISPLAY_SKIPPED_HOSTS = get_config(p, DEFAULTS, 'display_skipped_hosts', 'DISPLAY_SKIPPED_HOSTS', True, boolean=True) +DEFAULT_UNDEFINED_VAR_BEHAVIOR = get_config(p, DEFAULTS, 'error_on_undefined_vars', 'ANSIBLE_ERROR_ON_UNDEFINED_VARS', True, boolean=True) +HOST_KEY_CHECKING = get_config(p, DEFAULTS, 'host_key_checking', 'ANSIBLE_HOST_KEY_CHECKING', True, boolean=True) +DEPRECATION_WARNINGS = get_config(p, DEFAULTS, 'deprecation_warnings', 'ANSIBLE_DEPRECATION_WARNINGS', True, boolean=True) + +# CONNECTION RELATED ANSIBLE_SSH_ARGS = get_config(p, 'ssh_connection', 'ssh_args', 'ANSIBLE_SSH_ARGS', None) ANSIBLE_SSH_CONTROL_PATH = get_config(p, 'ssh_connection', 'control_path', 'ANSIBLE_SSH_CONTROL_PATH', "%(directory)s/ansible-ssh-%%h-%%p-%%r") PARAMIKO_RECORD_HOST_KEYS = get_config(p, 'paramiko_connection', 'record_host_keys', 'ANSIBLE_PARAMIKO_RECORD_HOST_KEYS', True, boolean=True) @@ -142,8 +147,6 @@ ACCELERATE_TIMEOUT = get_config(p, 'accelerate', 'accelerate_timeout ACCELERATE_CONNECT_TIMEOUT = get_config(p, 'accelerate', 'accelerate_connect_timeout', 'ACCELERATE_CONNECT_TIMEOUT', 1.0, floating=True) PARAMIKO_PTY = get_config(p, 'paramiko_connection', 'pty', 'ANSIBLE_PARAMIKO_PTY', True, boolean=True) -DEFAULT_UNDEFINED_VAR_BEHAVIOR = get_config(p, DEFAULTS, 'error_on_undefined_vars', 'ANSIBLE_ERROR_ON_UNDEFINED_VARS', True, boolean=True) -HOST_KEY_CHECKING = get_config(p, DEFAULTS, 'host_key_checking', 'ANSIBLE_HOST_KEY_CHECKING', True, boolean=True) # non-configurable things DEFAULT_SUDO_PASS = None diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py index 841dfea7bb4..fb5338bc5d0 100644 --- a/lib/ansible/playbook/play.py +++ b/lib/ansible/playbook/play.py @@ -427,7 +427,7 @@ class Play(object): include_vars = {} for k in x: if k.startswith("with_"): - sys.stderr.write("DEPRECATION: include + with_items is unsupported/undocumented and will be removed in Ansible 1.5, it will likely not do what you think it does.\n") + utils.deprecated("include + with_items is an unsupported feature and has been undocumented for many releases because of this", "1.5") plugin_name = k[5:] if plugin_name not in utils.plugins.lookup_loader: raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name)) diff --git a/lib/ansible/playbook/task.py b/lib/ansible/playbook/task.py index c5f3337637c..d401a67ac81 100644 --- a/lib/ansible/playbook/task.py +++ b/lib/ansible/playbook/task.py @@ -19,6 +19,7 @@ from ansible import errors from ansible import utils import os import ansible.utils.template as template +import sys class Task(object): @@ -91,8 +92,10 @@ class Task(object): elif x in [ 'changed_when', 'failed_when', 'when']: ds[x] = "jinja2_compare %s" % (ds[x]) elif x.startswith("when_"): + utils.deprecated("The 'when_' conditional is a deprecated syntax as of 1.2. Switch to using the regular unified 'when' statements as described in ansibleworks.com/docs/.","1.5") + if 'when' in ds: - raise errors.AnsibleError("multiple when_* statements specified in task %s" % (ds.get('name', ds['action']))) + raise errors.AnsibleError("multiple when_* statements specified in task %s" % (ds.get('name', ds['action']))) when_name = x.replace("when_","") ds['when'] = "%s %s" % (when_name, ds[x]) ds.pop(x) @@ -172,6 +175,10 @@ class Task(object): # 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") + self.when = ds.get('when', None) self.changed_when = ds.get('changed_when', None) diff --git a/lib/ansible/utils/__init__.py b/lib/ansible/utils/__init__.py index 7432b00c31b..dbb14e2e5c6 100644 --- a/lib/ansible/utils/__init__.py +++ b/lib/ansible/utils/__init__.py @@ -27,6 +27,7 @@ from ansible import errors from ansible import __version__ from ansible.utils.plugins import * from ansible.utils import template +from ansible.callbacks import display import ansible.constants as C import time import StringIO @@ -39,9 +40,14 @@ import difflib import warnings import traceback import getpass +import sys +import textwrap VERBOSITY=0 +# list of all deprecation messages to prevent duplicate display +deprecations = {} + MAX_FILE_SIZE_FOR_DIFF=1*1024*1024 try: @@ -385,10 +391,14 @@ Or: if len(parts) > 1: middle = parts[1].strip() match = False - if middle.startswith("'") and not middle.endswith('"'): + unbalanced = False + if middle.startswith("'") and not middle.endswith("'"): match = True elif middle.startswith('"') and not middle.endswith('"'): match = True + if middle[0] in [ '"', "'" ] and middle[-1] in [ '"', "'" ]: + unbalanced = True + if match: msg = msg + """ This one looks easy to fix. It seems that there is a value started @@ -405,6 +415,22 @@ or equivalently: when: "'ok' in result.stdout" +""" + return msg + + if unbalanced: + msg = msg + """ +We could be wrong, but this one looks like it might be an issue with +unbalanced quotes. If starting a value with a quote, make sure the +line ends with the same set of quotes. For instance this arbitrary +example: + + foo: "bad" "wolf" + +Could be written as: + + foo: '"bad" "wolf"' + """ return msg @@ -930,6 +956,19 @@ def listify_lookup_plugin_terms(terms, basedir, inject): return terms +def deprecated(msg, version): + ''' used to print out a deprecation message.''' + if not C.DEPRECATION_WARNINGS: + return + new_msg = "\n[DEPRECATION WARNING]: %s. This feature will be removed in version %s." % (msg, version) + new_msg = new_msg + " Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.\n\n" + wrapped = textwrap.wrap(new_msg, 79) + new_msg = "\n".join(wrapped) + "\n" + + if new_msg not in deprecations: + display(new_msg, color='purple', stderr=True) + deprecations[new_msg] = 1 + def combine_vars(a, b): if C.DEFAULT_HASH_BEHAVIOUR == "merge": return merge_hash(a, b) diff --git a/lib/ansible/utils/template.py b/lib/ansible/utils/template.py index dbc1957b099..92b77335d92 100644 --- a/lib/ansible/utils/template.py +++ b/lib/ansible/utils/template.py @@ -292,7 +292,13 @@ def legacy_varReplace(basedir, raw, vars, lookup_fatal=True, depth=0, expand_lis done.append(unicode(replacement)) # Append replacement value raw = raw[end:] # Continue with remainder of string - return ''.join(done) + result = ''.join(done) + + if result != raw: + import utils + utils.deprecated("Legacy variable subsitution, such as using ${foo} or $foo instead of {{ foo }} is currently valid but will be phased out and has been out of favor since version 1.2. This is the last of legacy features on our deprecation list. You may continue to use this if you have specific needs for now","1.6") + return result + # TODO: varname is misnamed here