|
14 | 14 | import black
|
15 | 15 | import jinja2
|
16 | 16 | from ansible.errors import AnsibleError, AnsibleFilterError, AnsibleParserError
|
| 17 | +from ansible_compat.config import ansible_version |
17 | 18 | from jinja2.exceptions import TemplateSyntaxError
|
| 19 | +from packaging.version import Version |
18 | 20 |
|
19 | 21 | from ansiblelint.errors import RuleMatchTransformMeta
|
20 | 22 | from ansiblelint.file_utils import Lintable
|
@@ -145,11 +147,15 @@ def matchtask(
|
145 | 147 | except AnsibleFilterError:
|
146 | 148 | bypass = True
|
147 | 149 | # ValueError RepresenterError
|
148 |
| - except AnsibleError as exc: |
| 150 | + except (AnsibleError, ImportError) as exc: |
149 | 151 | bypass = False
|
150 |
| - orig_exc = ( |
151 |
| - exc.orig_exc if getattr(exc, "orig_exc", None) else exc |
152 |
| - ) |
| 152 | + orig_exc = exc |
| 153 | + if ( |
| 154 | + isinstance(exc, AnsibleError) |
| 155 | + and hasattr(exc, "orig_exc") |
| 156 | + and exc.orig_exc |
| 157 | + ): |
| 158 | + orig_exc = exc.orig_exc |
153 | 159 | orig_exc_message = getattr(orig_exc, "message", str(orig_exc))
|
154 | 160 | match = self._ansible_error_re.match(
|
155 | 161 | getattr(orig_exc, "message", str(orig_exc)),
|
@@ -185,6 +191,12 @@ def matchtask(
|
185 | 191 | bypass = True
|
186 | 192 | else:
|
187 | 193 | bypass = False
|
| 194 | + elif isinstance(exc, ImportError): |
| 195 | + if self.options and self.options.nodeps: |
| 196 | + msg = f"Ignored exception {exc} due to running with nodeps mode." |
| 197 | + _logger.debug(msg) |
| 198 | + continue |
| 199 | + bypass = False |
188 | 200 | elif re.match(r"^lookup plugin (.*) not found$", exc.message):
|
189 | 201 | # lookup plugin 'template' not found
|
190 | 202 | bypass = True
|
@@ -905,3 +917,25 @@ def _do_template(*args, **kwargs): # type: ignore[no-untyped-def] # Templar.do_
|
905 | 917 | with mock.patch.object(Templar, "do_template", _do_template):
|
906 | 918 | results = Runner(lintable, rules=collection).run()
|
907 | 919 | assert len(results) == 0
|
| 920 | + |
| 921 | + @pytest.mark.parametrize( |
| 922 | + ("nodeps", "expected_results"), |
| 923 | + ( |
| 924 | + pytest.param( |
| 925 | + "0", |
| 926 | + 0 if ansible_version() >= Version("2.19.0.dev0") else 1, |
| 927 | + id="normal", |
| 928 | + ), |
| 929 | + pytest.param("1", 0, id="nodeps"), |
| 930 | + ), |
| 931 | + ) |
| 932 | + def test_filter_import_failure( |
| 933 | + nodeps: str, expected_results: int, monkeypatch: pytest.MonkeyPatch |
| 934 | + ) -> None: |
| 935 | + """Tests how we process import failures from within filters.""" |
| 936 | + monkeypatch.setenv("ANSIBLE_LINT_NODEPS", nodeps) |
| 937 | + collection = RulesCollection() |
| 938 | + collection.register(JinjaRule()) |
| 939 | + lintable = Lintable("examples/playbooks/test_filter_with_importerror.yml") |
| 940 | + results = Runner(lintable, rules=collection).run() |
| 941 | + assert len(results) == expected_results |
0 commit comments