diff --git a/lib/ansible/plugins/lookup/file.py b/lib/ansible/plugins/lookup/file.py index efb039497dd..ea53c37e039 100644 --- a/lib/ansible/plugins/lookup/file.py +++ b/lib/ansible/plugins/lookup/file.py @@ -42,18 +42,22 @@ class LookupModule(LookupBase): # role/files/ directory, and finally the playbook directory # itself (which will be relative to the current working dir) + if 'role_path' in variables: + relative_path = self._loader.path_dwim_relative(variables['role_path'], 'files', term, check=False) + # FIXME: the original file stuff still needs to be worked out, but the # playbook_dir stuff should be able to be removed as it should # be covered by the fact that the loader contains that info - #if '_original_file' in variables: - # relative_path = self._loader.path_dwim_relative(variables['_original_file'], 'files', term, self.basedir, check=False) #if 'playbook_dir' in variables: # playbook_path = os.path.join(variables['playbook_dir'], term) for path in (basedir_path, relative_path, playbook_path): - if path and os.path.exists(path): - ret.append(codecs.open(path, encoding="utf8").read().rstrip()) + try: + contents = self._loader._get_file_contents(path) + ret.append(contents.rstrip()) break + except AnsibleParserError: + continue else: raise AnsibleError("could not locate file in lookup: %s" % term) diff --git a/lib/ansible/template/__init__.py b/lib/ansible/template/__init__.py index 19e091b9b27..8ad9917d602 100644 --- a/lib/ansible/template/__init__.py +++ b/lib/ansible/template/__init__.py @@ -218,7 +218,7 @@ class Templar: # safely catch run failures per #5059 try: ran = instance.run(*args, variables=self._available_variables, **kwargs) - except AnsibleUndefinedVariable: + except (AnsibleUndefinedVariable, UndefinedError): raise except Exception, e: if self._fail_on_lookup_errors: diff --git a/test/units/mock/loader.py b/test/units/mock/loader.py index cf9d7ea72d0..078ca3f0e6c 100644 --- a/test/units/mock/loader.py +++ b/test/units/mock/loader.py @@ -38,6 +38,12 @@ class DictDataLoader(DataLoader): return self.load(self._file_mapping[path], path) return None + def _get_file_contents(self, path): + if path in self._file_mapping: + return self._file_mapping[path] + else: + raise AnsibleParserError("file not found: %s" % path) + def path_exists(self, path): return path in self._file_mapping or path in self._known_directories diff --git a/test/units/template/test_templar.py b/test/units/template/test_templar.py index f2f727d1c79..eb634994fd7 100644 --- a/test/units/template/test_templar.py +++ b/test/units/template/test_templar.py @@ -19,10 +19,13 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type +from jinja2.exceptions import UndefinedError + from ansible.compat.tests import unittest from ansible.compat.tests.mock import patch, MagicMock from ansible import constants as C +from ansible.errors import * from ansible.plugins import filter_loader, lookup_loader, module_loader from ansible.plugins.strategies import SharedPluginLoaderObj from ansible.template import Templar @@ -38,9 +41,11 @@ class TestTemplar(unittest.TestCase): pass def test_templar_simple(self): - fake_loader = DictDataLoader({}) + fake_loader = DictDataLoader({ + "/path/to/my_file.txt": "foo\n", + }) shared_loader = SharedPluginLoaderObj() - templar = Templar(loader=fake_loader, variables=dict(foo="bar", bam="{{foo}}", num=1, var_true=True, var_false=False, var_dict=dict(a="b"), bad_dict="{a='b'", var_list=[1])) + templar = Templar(loader=fake_loader, variables=dict(foo="bar", bam="{{foo}}", num=1, var_true=True, var_false=False, var_dict=dict(a="b"), bad_dict="{a='b'", var_list=[1], recursive="{{recursive}}")) # test some basic templating self.assertEqual(templar.template("{{foo}}"), "bar") @@ -54,6 +59,17 @@ class TestTemplar(unittest.TestCase): self.assertEqual(templar.template("{{var_dict}}"), dict(a="b")) self.assertEqual(templar.template("{{bad_dict}}"), "{a='b'") self.assertEqual(templar.template("{{var_list}}"), [1]) + self.assertEqual(templar.template(1, convert_bare=True), 1) + self.assertRaises(UndefinedError, templar.template, "{{bad_var}}") + self.assertEqual(templar.template("{{lookup('file', '/path/to/my_file.txt')}}"), "foo") + self.assertRaises(UndefinedError, templar.template, "{{lookup('file', bad_var)}}") + self.assertRaises(AnsibleError, templar.template, "{{lookup('bad_lookup')}}") + self.assertRaises(AnsibleError, templar.template, "{{recursive}}") + self.assertRaises(AnsibleUndefinedVariable, templar.template, "{{foo-bar}}") + + # test with fail_on_undefined=False + templar = Templar(loader=fake_loader, fail_on_undefined=False) + self.assertEqual(templar.template("{{bad_var}}"), "{{bad_var}}") # test set_available_variables() templar.set_available_variables(variables=dict(foo="bam"))