diff --git a/lib/ansible/runner/__init__.py b/lib/ansible/runner/__init__.py index 0d167462552..082dd44c8a4 100644 --- a/lib/ansible/runner/__init__.py +++ b/lib/ansible/runner/__init__.py @@ -723,18 +723,21 @@ class Runner(object): # strip out any jinja2 template syntax within # the data returned by the lookup plugin items = utils._clean_data_struct(items, from_remote=True) - if type(items) != list: - raise errors.AnsibleError("lookup plugins have to return a list: %r" % items) - - if len(items) and utils.is_list_of_strings(items) and self.module_name in [ 'apt', 'yum', 'pkgng', 'zypper' ]: - # hack for apt, yum, and pkgng so that with_items maps back into a single module call - use_these_items = [] - for x in items: - inject['item'] = x - if not self.conditional or utils.check_conditional(self.conditional, self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars): - use_these_items.append(x) - inject['item'] = ",".join(use_these_items) - items = None + if items is None: + items = [] + else: + if type(items) != list: + raise errors.AnsibleError("lookup plugins have to return a list: %r" % items) + + if len(items) and utils.is_list_of_strings(items) and self.module_name in [ 'apt', 'yum', 'pkgng', 'zypper' ]: + # hack for apt, yum, and pkgng so that with_items maps back into a single module call + use_these_items = [] + for x in items: + inject['item'] = x + if not self.conditional or utils.check_conditional(self.conditional, self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars): + use_these_items.append(x) + inject['item'] = ",".join(use_these_items) + items = None def _safe_template_complex_args(args, inject): # Ensure the complex args here are a dictionary, but diff --git a/lib/ansible/runner/lookup_plugins/flattened.py b/lib/ansible/runner/lookup_plugins/flattened.py index 831b2e91302..b93573fe40b 100644 --- a/lib/ansible/runner/lookup_plugins/flattened.py +++ b/lib/ansible/runner/lookup_plugins/flattened.py @@ -50,7 +50,7 @@ class LookupModule(object): if isinstance(term, basestring): # convert a variable to a list - term2 = utils.listify_lookup_plugin_terms(term, self.basedir, inject) + term2 = utils.listify_lookup_plugin_terms(term, self.basedir, inject, fail_on_undefined=False) # but avoid converting a plain string to a list of one string if term2 != [ term ]: term = term2 diff --git a/lib/ansible/utils/__init__.py b/lib/ansible/utils/__init__.py index 674ca1cb112..1bfe16c5b9e 100644 --- a/lib/ansible/utils/__init__.py +++ b/lib/ansible/utils/__init__.py @@ -1451,7 +1451,7 @@ def safe_eval(expr, locals={}, include_exceptions=False): return expr -def listify_lookup_plugin_terms(terms, basedir, inject): +def listify_lookup_plugin_terms(terms, basedir, inject, fail_on_undefined=C.DEFAULT_UNDEFINED_VAR_BEHAVIOR): from ansible.utils import template @@ -1469,7 +1469,7 @@ def listify_lookup_plugin_terms(terms, basedir, inject): # if not already a list, get ready to evaluate with Jinja2 # not sure why the "/" is in above code :) try: - new_terms = template.template(basedir, terms, inject, convert_bare=True, fail_on_undefined=C.DEFAULT_UNDEFINED_VAR_BEHAVIOR) + new_terms = template.template(basedir, "{{%s}}" % terms, inject, convert_bare=True, fail_on_undefined=fail_on_undefined) if isinstance(new_terms, basestring) and "{{" in new_terms: pass else: diff --git a/lib/ansible/utils/template.py b/lib/ansible/utils/template.py index 5146057dac9..73f03afe7a0 100644 --- a/lib/ansible/utils/template.py +++ b/lib/ansible/utils/template.py @@ -100,33 +100,33 @@ def lookup(name, *args, **kwargs): else: raise errors.AnsibleError("lookup plugin (%s) not found" % name) -def template(basedir, varname, vars, lookup_fatal=True, depth=0, expand_lists=True, convert_bare=False, fail_on_undefined=False, filter_fatal=True): +def template(basedir, varname, templatevars, lookup_fatal=True, depth=0, expand_lists=True, convert_bare=False, fail_on_undefined=False, filter_fatal=True): ''' templates a data structure by traversing it and substituting for other data structures ''' from ansible import utils try: if convert_bare and isinstance(varname, basestring): first_part = varname.split(".")[0].split("[")[0] - if first_part in vars and '{{' not in varname and '$' not in varname: + if first_part in templatevars and '{{' not in varname and '$' not in varname: varname = "{{%s}}" % varname - + if isinstance(varname, basestring): if '{{' in varname or '{%' in varname: - varname = template_from_string(basedir, varname, vars, fail_on_undefined) + varname = template_from_string(basedir, varname, templatevars, fail_on_undefined) if (varname.startswith("{") and not varname.startswith("{{")) or varname.startswith("["): - eval_results = utils.safe_eval(varname, locals=vars, include_exceptions=True) + eval_results = utils.safe_eval(varname, locals=templatevars, include_exceptions=True) if eval_results[1] is None: varname = eval_results[0] return varname - + elif isinstance(varname, (list, tuple)): - return [template(basedir, v, vars, lookup_fatal, depth, expand_lists, fail_on_undefined=fail_on_undefined) for v in varname] + return [template(basedir, v, templatevars, lookup_fatal, depth, expand_lists, convert_bare, fail_on_undefined, filter_fatal) for v in varname] elif isinstance(varname, dict): d = {} for (k, v) in varname.iteritems(): - d[k] = template(basedir, v, vars, lookup_fatal, depth, expand_lists, fail_on_undefined=fail_on_undefined) + d[k] = template(basedir, v, templatevars, lookup_fatal, depth, expand_lists, convert_bare, fail_on_undefined, filter_fatal) return d else: return varname diff --git a/test/units/TestUtils.py b/test/units/TestUtils.py index 541849fd666..d93fc70329b 100644 --- a/test/units/TestUtils.py +++ b/test/units/TestUtils.py @@ -568,10 +568,8 @@ class TestUtils(unittest.TestCase): basedir = os.path.dirname(__file__) # Straight lookups - self.assertEqual(ansible.utils.listify_lookup_plugin_terms('things', basedir, dict()), - ['things']) - self.assertEqual(ansible.utils.listify_lookup_plugin_terms('things', basedir, dict(things=['one', 'two'])), - ['one', 'two']) + self.assertEqual(ansible.utils.listify_lookup_plugin_terms('things', basedir, dict(things=[])), []) + self.assertEqual(ansible.utils.listify_lookup_plugin_terms('things', basedir, dict(things=['one', 'two'])), ['one', 'two']) # Variable interpolation self.assertEqual(ansible.utils.listify_lookup_plugin_terms('things', basedir, dict(things=['{{ foo }}', '{{ bar }}'], foo="hello", bar="world")),