Add code to flag legacy templating like $foo.{bar} as deprecated in favor of Jinja2 {{ foo.bar }} so we

can remove the legacy system at a later date.
This commit is contained in:
Michael DeHaan 2013-04-10 17:52:35 -04:00
parent 804056a563
commit b09ef21ec9
13 changed files with 102 additions and 61 deletions

View file

@ -24,6 +24,7 @@ import os
import ansible.playbook import ansible.playbook
import ansible.constants as C import ansible.constants as C
import ansible.utils.template
from ansible import errors from ansible import errors
from ansible import callbacks from ansible import callbacks
from ansible import utils from ansible import utils
@ -180,6 +181,11 @@ def main(args):
pb.run() pb.run()
if ansible.utils.template.Flags.LEGACY_TEMPLATE_WARNING:
print callbacks.banner("Deprecation Warnings")
print " legacy playbook variable references such as '$foo' will be removed in Ansible 1.4"
print " update playbooks to use '{{ foo }}' instead"
hosts = sorted(pb.stats.processed.keys()) hosts = sorted(pb.stats.processed.keys())
print callbacks.banner("PLAY RECAP") print callbacks.banner("PLAY RECAP")
playbook_cb.on_stats(pb.stats) playbook_cb.on_stats(pb.stats)
@ -202,6 +208,7 @@ def main(args):
colorize('changed', t['changed'], 'yellow'), colorize('changed', t['changed'], 'yellow'),
colorize('unreachable', t['unreachable'], 'red'), colorize('unreachable', t['unreachable'], 'red'),
colorize('failed', t['failures'], 'red')) colorize('failed', t['failures'], 'red'))
print "" print ""
if len(failed_hosts) > 0: if len(failed_hosts) > 0:
@ -211,7 +218,6 @@ def main(args):
print >>sys.stderr, "ERROR: %s" % e print >>sys.stderr, "ERROR: %s" % e
return 1 return 1
return 0 return 0

View file

@ -18,6 +18,7 @@
import ansible.inventory import ansible.inventory
import ansible.runner import ansible.runner
import ansible.constants as C import ansible.constants as C
from ansible.utils import template
from ansible import utils from ansible import utils
from ansible import errors from ansible import errors
import ansible.callbacks import ansible.callbacks
@ -174,9 +175,9 @@ class PlayBook(object):
for t in tokens[1:]: for t in tokens[1:]:
(k,v) = t.split("=", 1) (k,v) = t.split("=", 1)
incvars[k] = utils.template(basedir, v, incvars) incvars[k] = template.template(basedir, v, incvars)
included_path = utils.path_dwim(basedir, utils.template(basedir, tokens[0], incvars)) included_path = utils.path_dwim(basedir, template.template(basedir, tokens[0], incvars))
(plays, basedirs) = self._load_playbook_from_file(included_path, incvars) (plays, basedirs) = self._load_playbook_from_file(included_path, incvars)
for p in plays: for p in plays:
# support for parameterized play includes works by passing # support for parameterized play includes works by passing
@ -319,7 +320,7 @@ class PlayBook(object):
self.callbacks.task = task self.callbacks.task = task
self.runner_callbacks.task = task self.runner_callbacks.task = task
self.callbacks.on_task_start(utils.template(play.basedir, task.name, task.module_vars, lookup_fatal=False), is_handler) self.callbacks.on_task_start(template.template(play.basedir, task.name, task.module_vars, lookup_fatal=False), is_handler)
if hasattr(self.callbacks, 'skip_task') and self.callbacks.skip_task: if hasattr(self.callbacks, 'skip_task') and self.callbacks.skip_task:
return True return True
@ -354,7 +355,7 @@ class PlayBook(object):
for host, results in results.get('contacted',{}).iteritems(): for host, results in results.get('contacted',{}).iteritems():
if results.get('changed', False): if results.get('changed', False):
for handler_name in task.notify: for handler_name in task.notify:
self._flag_handler(play, utils.template(play.basedir, handler_name, task.module_vars), host) self._flag_handler(play, template.template(play.basedir, handler_name, task.module_vars), host)
return hosts_remaining return hosts_remaining
@ -369,7 +370,7 @@ class PlayBook(object):
found = False found = False
for x in play.handlers(): for x in play.handlers():
if handler_name == utils.template(play.basedir, x.name, x.module_vars): if handler_name == template.template(play.basedir, x.name, x.module_vars):
found = True found = True
self.callbacks.on_notify(host, x.name) self.callbacks.on_notify(host, x.name)
x.notified_by.append(host) x.notified_by.append(host)

View file

@ -17,6 +17,7 @@
############################################# #############################################
from ansible.utils import template
from ansible import utils from ansible import utils
from ansible import errors from ansible import errors
from ansible.playbook.task import Task from ansible.playbook.task import Task
@ -64,7 +65,7 @@ class Play(object):
self._update_vars_files_for_host(None) self._update_vars_files_for_host(None)
self._ds = ds = utils.template(basedir, ds, self.vars) self._ds = ds = template.template(basedir, ds, self.vars)
hosts = ds.get('hosts') hosts = ds.get('hosts')
if hosts is None: if hosts is None:
@ -202,7 +203,7 @@ class Play(object):
plugin_name = k[5:] plugin_name = k[5:]
if plugin_name not in utils.plugins.lookup_loader: 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)) raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name))
terms = utils.template(self.basedir, x[k], task_vars) terms = template.template(self.basedir, x[k], task_vars)
items = utils.plugins.lookup_loader.get(plugin_name, basedir=self.basedir, runner=None).run(terms, inject=task_vars) items = utils.plugins.lookup_loader.get(plugin_name, basedir=self.basedir, runner=None).run(terms, inject=task_vars)
elif k.startswith("when_"): elif k.startswith("when_"):
included_additional_conditions.append(utils.compile_when_to_only_if("%s %s" % (k[5:], x[k]))) included_additional_conditions.append(utils.compile_when_to_only_if("%s %s" % (k[5:], x[k])))
@ -223,11 +224,11 @@ class Play(object):
mv['item'] = item mv['item'] = item
for t in tokens[1:]: for t in tokens[1:]:
(k,v) = t.split("=", 1) (k,v) = t.split("=", 1)
mv[k] = utils.template(self.basedir, v, mv) mv[k] = template.template(self.basedir, v, mv)
dirname = self.basedir dirname = self.basedir
if original_file: if original_file:
dirname = os.path.dirname(original_file) dirname = os.path.dirname(original_file)
include_file = utils.template(dirname, tokens[0], mv) include_file = template.template(dirname, tokens[0], mv)
include_filename = utils.path_dwim(dirname, include_file) include_filename = utils.path_dwim(dirname, include_file)
data = utils.parse_yaml_from_file(include_filename) data = utils.parse_yaml_from_file(include_filename)
results += self._load_tasks(data, mv, included_additional_conditions, original_file=include_filename) results += self._load_tasks(data, mv, included_additional_conditions, original_file=include_filename)
@ -369,10 +370,10 @@ class Play(object):
found = False found = False
sequence = [] sequence = []
for real_filename in filename: for real_filename in filename:
filename2 = utils.template(self.basedir, real_filename, self.vars) filename2 = template.template(self.basedir, real_filename, self.vars)
filename3 = filename2 filename3 = filename2
if host is not None: if host is not None:
filename3 = utils.template(self.basedir, filename2, inject) filename3 = template.template(self.basedir, filename2, inject)
filename4 = utils.path_dwim(self.basedir, filename3) filename4 = utils.path_dwim(self.basedir, filename3)
sequence.append(filename4) sequence.append(filename4)
if os.path.exists(filename4): if os.path.exists(filename4):
@ -402,10 +403,10 @@ class Play(object):
else: else:
# just one filename supplied, load it! # just one filename supplied, load it!
filename2 = utils.template(self.basedir, filename, self.vars) filename2 = template.template(self.basedir, filename, self.vars)
filename3 = filename2 filename3 = filename2
if host is not None: if host is not None:
filename3 = utils.template(self.basedir, filename2, inject) filename3 = template.template(self.basedir, filename2, inject)
filename4 = utils.path_dwim(self.basedir, filename3) filename4 = utils.path_dwim(self.basedir, filename3)
if self._has_vars_in(filename4): if self._has_vars_in(filename4):
continue continue

View file

@ -34,6 +34,7 @@ import pipes
import ansible.constants as C import ansible.constants as C
import ansible.inventory import ansible.inventory
from ansible import utils from ansible import utils
from ansible.utils import template
from ansible import errors from ansible import errors
from ansible import module_common from ansible import module_common
import poller import poller
@ -62,7 +63,14 @@ def _executor_hook(job_queue, result_queue):
while not job_queue.empty(): while not job_queue.empty():
try: try:
host = job_queue.get(block=False) host = job_queue.get(block=False)
result_queue.put(multiprocessing_runner._executor(host)) return_data = multiprocessing_runner._executor(host)
result_queue.put(return_data)
# print "FLAGS=%s" % return_data.flags
if 'LEGACY_TEMPLATE_WARNING' in return_data.flags:
# pass data back up across the multiprocessing fork boundary
template.Flags.LEGACY_TEMPLATE_WARNING = True
except Queue.Empty: except Queue.Empty:
pass pass
except: except:
@ -233,7 +241,7 @@ class Runner(object):
if not self.environment: if not self.environment:
return "" return ""
enviro = utils.template(self.basedir, self.environment, inject) enviro = template.template(self.basedir, self.environment, inject)
if type(enviro) != dict: if type(enviro) != dict:
raise errors.AnsibleError("environment must be a dictionary, received %s" % enviro) raise errors.AnsibleError("environment must be a dictionary, received %s" % enviro)
result = "" result = ""
@ -271,7 +279,7 @@ class Runner(object):
# do --check mode, so to be safe we will not run it. # do --check mode, so to be safe we will not run it.
return ReturnData(conn=conn, result=dict(skippped=True, msg="cannot run check mode against old-style modules")) return ReturnData(conn=conn, result=dict(skippped=True, msg="cannot run check mode against old-style modules"))
args = utils.template(self.basedir, args, inject) args = template.template(self.basedir, args, inject)
argsfile = self._transfer_str(conn, tmp, 'arguments', args) argsfile = self._transfer_str(conn, tmp, 'arguments', args)
if async_jid is None: if async_jid is None:
cmd = "%s %s" % (remote_module_path, argsfile) cmd = "%s %s" % (remote_module_path, argsfile)
@ -300,10 +308,20 @@ class Runner(object):
def _executor(self, host): def _executor(self, host):
''' handler for multiprocessing library ''' ''' handler for multiprocessing library '''
def get_flags():
# flags are a way of passing arbitrary event information
# back up the chain, since multiprocessing forks and doesn't
# allow state exchange
flags = []
if template.Flags.LEGACY_TEMPLATE_WARNING:
flags.append('LEGACY_TEMPLATE_WARNING')
return flags
try: try:
exec_rc = self._executor_internal(host) exec_rc = self._executor_internal(host)
if type(exec_rc) != ReturnData: if type(exec_rc) != ReturnData:
raise Exception("unexpected return type: %s" % type(exec_rc)) raise Exception("unexpected return type: %s" % type(exec_rc))
exec_rc.flags = get_flags()
# redundant, right? # redundant, right?
if not exec_rc.comm_ok: if not exec_rc.comm_ok:
self.callbacks.on_unreachable(host, exec_rc.result) self.callbacks.on_unreachable(host, exec_rc.result)
@ -311,11 +329,11 @@ class Runner(object):
except errors.AnsibleError, ae: except errors.AnsibleError, ae:
msg = str(ae) msg = str(ae)
self.callbacks.on_unreachable(host, msg) self.callbacks.on_unreachable(host, msg)
return ReturnData(host=host, comm_ok=False, result=dict(failed=True, msg=msg)) return ReturnData(host=host, comm_ok=False, result=dict(failed=True, msg=msg), flags=get_flags())
except Exception: except Exception:
msg = traceback.format_exc() msg = traceback.format_exc()
self.callbacks.on_unreachable(host, msg) self.callbacks.on_unreachable(host, msg)
return ReturnData(host=host, comm_ok=False, result=dict(failed=True, msg=msg)) return ReturnData(host=host, comm_ok=False, result=dict(failed=True, msg=msg), flags=get_flags())
# ***************************************************** # *****************************************************
@ -353,7 +371,7 @@ class Runner(object):
if items_plugin is not None and items_plugin in utils.plugins.lookup_loader: if items_plugin is not None and items_plugin in utils.plugins.lookup_loader:
items_terms = self.module_vars.get('items_lookup_terms', '') items_terms = self.module_vars.get('items_lookup_terms', '')
items_terms = utils.template(self.basedir, items_terms, inject) items_terms = template.template(self.basedir, items_terms, inject)
items = utils.plugins.lookup_loader.get(items_plugin, runner=self, basedir=self.basedir).run(items_terms, inject=inject) items = utils.plugins.lookup_loader.get(items_plugin, runner=self, basedir=self.basedir).run(items_terms, inject=inject)
if type(items) != list: if type(items) != list:
raise errors.AnsibleError("lookup plugins have to return a list: %r" % items) raise errors.AnsibleError("lookup plugins have to return a list: %r" % items)
@ -423,9 +441,9 @@ class Runner(object):
new_args = new_args + "%s='%s' " % (k,v) new_args = new_args + "%s='%s' " % (k,v)
module_args = new_args module_args = new_args
module_name = utils.template(self.basedir, module_name, inject) module_name = template.template(self.basedir, module_name, inject)
module_args = utils.template(self.basedir, module_args, inject) module_args = template.template(self.basedir, module_args, inject)
complex_args = utils.template(self.basedir, complex_args, inject) complex_args = template.template(self.basedir, complex_args, inject)
if module_name in utils.plugins.action_loader: if module_name in utils.plugins.action_loader:
if self.background != 0: if self.background != 0:
@ -436,7 +454,7 @@ class Runner(object):
else: else:
handler = utils.plugins.action_loader.get('async', self) handler = utils.plugins.action_loader.get('async', self)
conditional = utils.template(self.basedir, self.conditional, inject, expand_lists=False) conditional = template.template(self.basedir, self.conditional, inject, expand_lists=False)
if not utils.check_conditional(conditional): if not utils.check_conditional(conditional):
result = utils.jsonify(dict(skipped=True)) result = utils.jsonify(dict(skipped=True))
@ -457,7 +475,7 @@ class Runner(object):
# and we need to transfer those, and only those, variables # and we need to transfer those, and only those, variables
delegate_to = inject.get('delegate_to', None) delegate_to = inject.get('delegate_to', None)
if delegate_to is not None: if delegate_to is not None:
delegate_to = utils.template(self.basedir, delegate_to, inject) delegate_to = template.template(self.basedir, delegate_to, inject)
inject = inject.copy() inject = inject.copy()
interpreters = [] interpreters = []
for i in inject: for i in inject:
@ -481,8 +499,8 @@ class Runner(object):
actual_host = delegate_to actual_host = delegate_to
actual_port = port actual_port = port
actual_user = utils.template(self.basedir, actual_user, inject) actual_user = template.template(self.basedir, actual_user, inject)
actual_pass = utils.template(self.basedir, actual_pass, inject) actual_pass = template.template(self.basedir, actual_pass, inject)
try: try:
if actual_port is not None: if actual_port is not None:

View file

@ -18,6 +18,7 @@
import os import os
from ansible import utils from ansible import utils
from ansible import template
from ansible import errors from ansible import errors
from ansible.runner.return_data import ReturnData from ansible.runner.return_data import ReturnData
import base64 import base64
@ -54,7 +55,7 @@ class ActionModule(object):
if 'first_available_file' in inject: if 'first_available_file' in inject:
found = False found = False
for fn in inject.get('first_available_file'): for fn in inject.get('first_available_file'):
fn = utils.template(self.runner.basedir, fn, inject) fn = template.template(self.runner.basedir, fn, inject)
fn = utils.path_dwim(self.runner.basedir, fn) fn = utils.path_dwim(self.runner.basedir, fn)
if not os.path.exists(fn) and '_original_file' in inject: 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) fn = utils.path_dwim_relative(inject['_original_file'], 'files', fn, self.runner.basedir, check=False)
@ -77,7 +78,7 @@ class ActionModule(object):
f.close() f.close()
source = tmp_content source = tmp_content
else: else:
source = utils.template(self.runner.basedir, source, inject) source = template.template(self.runner.basedir, source, inject)
if '_original_file' in inject: if '_original_file' in inject:
source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir) source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir)
else: else:

View file

@ -19,6 +19,7 @@ import os
import shlex import shlex
import ansible.constants as C import ansible.constants as C
from ansible.utils import template
from ansible import utils from ansible import utils
from ansible import errors from ansible import errors
from ansible.runner.return_data import ReturnData from ansible.runner.return_data import ReturnData
@ -39,7 +40,7 @@ class ActionModule(object):
source = tokens[0] source = tokens[0]
# FIXME: error handling # FIXME: error handling
args = " ".join(tokens[1:]) args = " ".join(tokens[1:])
source = utils.template(self.runner.basedir, source, inject) source = template.template(self.runner.basedir, source, inject)
source = utils.path_dwim(self.runner.basedir, source) source = utils.path_dwim(self.runner.basedir, source)
# transfer the file to a remote tmp location # transfer the file to a remote tmp location

View file

@ -17,6 +17,7 @@
import os import os
import pipes import pipes
from ansible.utils import template
from ansible import utils from ansible import utils
from ansible import errors from ansible import errors
from ansible.runner.return_data import ReturnData from ansible.runner.return_data import ReturnData
@ -56,7 +57,7 @@ class ActionModule(object):
found = False found = False
for fn in self.runner.module_vars.get('first_available_file'): for fn in self.runner.module_vars.get('first_available_file'):
fnt = utils.template(self.runner.basedir, fn, inject) fnt = template.template(self.runner.basedir, fn, inject)
fnd = utils.path_dwim(self.runner.basedir, fnt) fnd = utils.path_dwim(self.runner.basedir, fnt)
if not os.path.exists(fnd) and '_original_file' in inject: 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) fnd = utils.path_dwim_relative(inject['_original_file'], 'templates', fnd, self.runner.basedir, check=False)
@ -68,7 +69,7 @@ class ActionModule(object):
result = dict(failed=True, msg="could not find src in first_available_file list") result = dict(failed=True, msg="could not find src in first_available_file list")
return ReturnData(conn=conn, comm_ok=False, result=result) return ReturnData(conn=conn, comm_ok=False, result=result)
else: else:
source = utils.template(self.runner.basedir, source, inject) source = template.template(self.runner.basedir, source, inject)
if '_original_file' in inject: if '_original_file' in inject:
source = utils.path_dwim_relative(inject['_original_file'], 'templates', source, self.runner.basedir) source = utils.path_dwim_relative(inject['_original_file'], 'templates', source, self.runner.basedir)
@ -82,7 +83,7 @@ class ActionModule(object):
# template the source data locally & get ready to transfer # template the source data locally & get ready to transfer
try: try:
resultant = utils.template_from_file(self.runner.basedir, source, inject) resultant = template.template_from_file(self.runner.basedir, source, inject)
except Exception, e: except Exception, e:
result = dict(failed=True, msg=str(e)) result = dict(failed=True, msg=str(e))
return ReturnData(conn=conn, comm_ok=False, result=result) return ReturnData(conn=conn, comm_ok=False, result=result)

View file

@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
from ansible import utils from ansible.utils import template
class LookupModule(object): class LookupModule(object):
@ -27,5 +27,5 @@ class LookupModule(object):
terms = [ terms ] terms = [ terms ]
ret = [] ret = []
for term in terms: for term in terms:
ret.append(utils.template_from_file(self.basedir, term, inject)) ret.append(template.template_from_file(self.basedir, term, inject))
return ret return ret

View file

@ -20,10 +20,10 @@ from ansible import utils
class ReturnData(object): class ReturnData(object):
''' internal return class for runner execute methods, not part of public API signature ''' ''' internal return class for runner execute methods, not part of public API signature '''
__slots__ = [ 'result', 'comm_ok', 'host', 'diff' ] __slots__ = [ 'result', 'comm_ok', 'host', 'diff', 'flags' ]
def __init__(self, conn=None, host=None, result=None, def __init__(self, conn=None, host=None, result=None,
comm_ok=True, diff=dict()): comm_ok=True, diff=dict(), flags=None):
# which host is this ReturnData about? # which host is this ReturnData about?
if conn is not None: if conn is not None:
@ -32,7 +32,6 @@ class ReturnData(object):
if delegate is not None: if delegate is not None:
self.host = delegate self.host = delegate
else: else:
self.host = host self.host = host
@ -52,6 +51,10 @@ class ReturnData(object):
if type(self.result) != dict: if type(self.result) != dict:
raise Exception("dictionary result expected") raise Exception("dictionary result expected")
if flags is None:
flags = []
self.flags = []
def communicated_ok(self): def communicated_ok(self):
return self.comm_ok return self.comm_ok

View file

@ -16,6 +16,7 @@
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
import sys import sys
import re
import os import os
import shlex import shlex
import yaml import yaml
@ -24,7 +25,6 @@ import optparse
import operator import operator
from ansible import errors from ansible import errors
from ansible import __version__ from ansible import __version__
from ansible.utils.template import *
from ansible.utils.plugins import * from ansible.utils.plugins import *
import ansible.constants as C import ansible.constants as C
import time import time
@ -36,6 +36,7 @@ import pipes
import random import random
import difflib import difflib
import warnings import warnings
import traceback
VERBOSITY=0 VERBOSITY=0
@ -163,7 +164,7 @@ def check_conditional(conditional):
return result return result
except (NameError, SyntaxError): except (NameError, SyntaxError):
raise errors.AnsibleError("Could not evaluate the expression: " + conditional) 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?'''

View file

@ -29,13 +29,17 @@ import subprocess
import datetime import datetime
import pwd import pwd
class Flags:
LEGACY_TEMPLATE_WARNING = False
# TODO: refactor this file # TODO: refactor this file
FILTER_PLUGINS = {} FILTER_PLUGINS = {}
_LISTRE = re.compile(r"(\w+)\[(\d+)\]") _LISTRE = re.compile(r"(\w+)\[(\d+)\]")
JINJA2_OVERRIDE='#jinja2:' JINJA2_OVERRIDE='#jinja2:'
def _varFindLimitSpace(basedir, vars, space, part, lookup_fatal, depth, expand_lists): def _legacy_varFindLimitSpace(basedir, vars, space, part, lookup_fatal, depth, expand_lists):
''' limits the search space of space to part ''' limits the search space of space to part
basically does space.get(part, None), but with basically does space.get(part, None), but with
@ -49,7 +53,7 @@ def _varFindLimitSpace(basedir, vars, space, part, lookup_fatal, depth, expand_l
if part[0] == '{' and part[-1] == '}': if part[0] == '{' and part[-1] == '}':
part = part[1:-1] part = part[1:-1]
# Template part to resolve variables within (${var$var2}) # Template part to resolve variables within (${var$var2})
part = varReplace(basedir, part, vars, lookup_fatal=lookup_fatal, depth=depth + 1, expand_lists=expand_lists) part = legacy_varReplace(basedir, part, vars, lookup_fatal=lookup_fatal, depth=depth + 1, expand_lists=expand_lists)
# Now find it # Now find it
if part in space: if part in space:
@ -72,7 +76,7 @@ def _varFindLimitSpace(basedir, vars, space, part, lookup_fatal, depth, expand_l
return space return space
def _varFind(basedir, text, vars, lookup_fatal, depth, expand_lists): def _legacy_varFind(basedir, text, vars, lookup_fatal, depth, expand_lists):
''' Searches for a variable in text and finds its replacement in vars ''' Searches for a variable in text and finds its replacement in vars
The variables can have two formats; The variables can have two formats;
@ -145,7 +149,7 @@ def _varFind(basedir, text, vars, lookup_fatal, depth, expand_lists):
pass pass
elif is_complex and text[end] == '.': elif is_complex and text[end] == '.':
if brace_level == 1: if brace_level == 1:
space = _varFindLimitSpace(basedir, vars, space, text[part_start:end], lookup_fatal, depth, expand_lists) space = _legacy_varFindLimitSpace(basedir, vars, space, text[part_start:end], lookup_fatal, depth, expand_lists)
part_start = end + 1 part_start = end + 1
else: else:
# This breaks out of the loop on non-variable name characters # This breaks out of the loop on non-variable name characters
@ -190,10 +194,10 @@ def _varFind(basedir, text, vars, lookup_fatal, depth, expand_lists):
var_end -= 1 var_end -= 1
if text[var_end] != '}' or brace_level != 0: if text[var_end] != '}' or brace_level != 0:
return None return None
space = _varFindLimitSpace(basedir, vars, space, text[part_start:var_end], lookup_fatal, depth, expand_lists) space = _legacy_varFindLimitSpace(basedir, vars, space, text[part_start:var_end], lookup_fatal, depth, expand_lists)
return {'replacement': space, 'start': start, 'end': end} return {'replacement': space, 'start': start, 'end': end}
def varReplace(basedir, raw, vars, lookup_fatal=True, depth=0, expand_lists=False): def legacy_varReplace(basedir, raw, vars, lookup_fatal=True, depth=0, expand_lists=False):
''' Perform variable replacement of $variables in string raw using vars dictionary ''' ''' Perform variable replacement of $variables in string raw using vars dictionary '''
# this code originally from yum # this code originally from yum
@ -206,7 +210,7 @@ def varReplace(basedir, raw, vars, lookup_fatal=True, depth=0, expand_lists=Fals
done = [] # Completed chunks to return done = [] # Completed chunks to return
while raw: while raw:
m = _varFind(basedir, raw, vars, lookup_fatal, depth, expand_lists) m = _legacy_varFind(basedir, raw, vars, lookup_fatal, depth, expand_lists)
if not m: if not m:
done.append(raw) done.append(raw)
break break
@ -235,16 +239,20 @@ def template(basedir, varname, vars, lookup_fatal=True, depth=0, expand_lists=Tr
if isinstance(varname, basestring): if isinstance(varname, basestring):
if '{{' in varname or '{%' in varname: if '{{' in varname or '{%' in varname:
varname = template_from_string(basedir, varname, vars) varname = template_from_string(basedir, varname, vars)
m = _varFind(basedir, varname, vars, lookup_fatal, depth, expand_lists)
m = _legacy_varFind(basedir, varname, vars, lookup_fatal, depth, expand_lists)
if not m: if not m:
return varname return varname
if m['start'] == 0 and m['end'] == len(varname): if m['start'] == 0 and m['end'] == len(varname):
if m['replacement'] is not None: if m['replacement'] is not None:
Flags.LEGACY_TEMPLATE_WARNING = True
return template(basedir, m['replacement'], vars, lookup_fatal, depth, expand_lists) return template(basedir, m['replacement'], vars, lookup_fatal, depth, expand_lists)
else: else:
return varname return varname
else: else:
return varReplace(basedir, varname, vars, lookup_fatal, depth, expand_lists) Flags.LEGACY_TEMPLATE_WARNING = True
return legacy_varReplace(basedir, varname, vars, lookup_fatal, depth, expand_lists)
elif isinstance(varname, (list, tuple)): elif isinstance(varname, (list, tuple)):
return [template(basedir, v, vars, lookup_fatal, depth, expand_lists) for v in varname] return [template(basedir, v, vars, lookup_fatal, depth, expand_lists) for v in varname]
elif isinstance(varname, dict): elif isinstance(varname, dict):

View file

@ -67,7 +67,6 @@ class TestRunner(unittest.TestCase):
''' run a module and get the localhost results ''' ''' run a module and get the localhost results '''
self.runner.module_name = module_name self.runner.module_name = module_name
args = ' '.join(module_args) args = ' '.join(module_args)
print "DEBUG: using args=%s" % args
self.runner.module_args = args self.runner.module_args = args
self.runner.background = background self.runner.background = background
results = self.runner.run() results = self.runner.run()

View file

@ -3,6 +3,7 @@
import unittest import unittest
import ansible.utils import ansible.utils
import ansible.template as template
class TestUtils(unittest.TestCase): class TestUtils(unittest.TestCase):
@ -268,7 +269,7 @@ class TestUtils(unittest.TestCase):
}, },
} }
template = '${x.foo}' template = '${x.foo}'
res = ansible.utils.template(None, template, vars) res = template.template(None, template, vars)
assert res == 'result' assert res == 'result'
def test_template_varReplace_iterated(self): def test_template_varReplace_iterated(self):
@ -278,21 +279,21 @@ class TestUtils(unittest.TestCase):
'person': 'one', 'person': 'one',
} }
res = ansible.utils.template(None, template, vars) res = template.template(None, template, vars)
assert res == u'hello oh great one' assert res == u'hello oh great one'
def test_varReplace_include(self): def test_varReplace_include(self):
template = 'hello $FILE(world) $LOOKUP(file, $filename)' template = 'hello $FILE(world) $LOOKUP(file, $filename)'
res = ansible.utils.template("test", template, {'filename': 'world'}, expand_lists=True) res = template.template("test", template, {'filename': 'world'}, expand_lists=True)
assert res == u'hello world world' assert res == u'hello world world'
def test_varReplace_include_script(self): def test_varReplace_include_script(self):
template = 'hello $PIPE(echo world) $LOOKUP(pipe, echo world)' template = 'hello $PIPE(echo world) $LOOKUP(pipe, echo world)'
res = ansible.utils.template("test", template, {}, expand_lists=True) res = template.template("test", template, {}, expand_lists=True)
assert res == u'hello world world' assert res == u'hello world world'
@ -324,19 +325,19 @@ class TestUtils(unittest.TestCase):
} }
template = '${data.var}' template = '${data.var}'
res = ansible.utils.template(None, template, vars) res = template.template(None, template, vars)
assert sorted(res) == sorted(vars['data']['var']) assert sorted(res) == sorted(vars['data']['var'])
template = '${data.types}' template = '${data.types}'
res = ansible.utils.template(None, template, vars) res = template.template(None, template, vars)
assert sorted(res) == sorted(vars['data']['types']) assert sorted(res) == sorted(vars['data']['types'])
template = '${data.alphas}' template = '${data.alphas}'
res = ansible.utils.template(None, template, vars) res = template.template(None, template, vars)
assert sorted(res) == sorted(vars['alphas']) assert sorted(res) == sorted(vars['alphas'])
template = '${data.nonexisting}' template = '${data.nonexisting}'
res = ansible.utils.template(None, template, vars) res = template.template(None, template, vars)
assert res == template assert res == template
##################################### #####################################
@ -347,7 +348,7 @@ class TestUtils(unittest.TestCase):
'who': 'world', 'who': 'world',
} }
res = ansible.utils.template_from_file("test", "template-basic", vars) res = template.template_from_file("test", "template-basic", vars)
assert res == 'hello world' assert res == 'hello world'
@ -356,7 +357,7 @@ class TestUtils(unittest.TestCase):
'who': 'world', 'who': 'world',
} }
res = ansible.utils.template_from_file("test", "template-whitespace", vars) res = template.template_from_file("test", "template-whitespace", vars)
assert res == 'hello world\n' assert res == 'hello world\n'
@ -365,7 +366,7 @@ class TestUtils(unittest.TestCase):
'who': u'wórld', 'who': u'wórld',
} }
res = ansible.utils.template_from_file("test", "template-basic", vars) res = template.template_from_file("test", "template-basic", vars)
assert res == u'hello wórld' assert res == u'hello wórld'