diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index fc4e0465c9..2bb6b50771 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -47,7 +47,7 @@ jobs: matrix: ${{ fromJson(needs.pre.outputs.matrix) }} env: - PYTEST_REQPASS: 450 + PYTEST_REQPASS: 452 environment: test steps: - uses: actions/checkout@v4 diff --git a/src/molecule/provisioner/ansible.py b/src/molecule/provisioner/ansible.py index 92f1abb54c..e292115579 100644 --- a/src/molecule/provisioner/ansible.py +++ b/src/molecule/provisioner/ansible.py @@ -515,32 +515,7 @@ def default_env(self): self._config.ansible_collections_path: ":".join(collections_path_list), "ANSIBLE_LIBRARY": ":".join(self._get_modules_directories()), "ANSIBLE_FILTER_PLUGINS": ":".join( - [ - self._get_filter_plugin_directory(), - util.abs_path( - os.path.join( - self._config.scenario.ephemeral_directory, - "plugins", - "filter", - ), - ), - util.abs_path( - os.path.join( - self._config.project_directory, - "plugins", - "filter", - ), - ), - util.abs_path( - os.path.join( - os.path.expanduser("~"), - ".ansible", - "plugins", - "filter", - ), - ), - "/usr/share/ansible/plugins/filter", - ], + self._get_filter_plugins_directories(), ), }, ) @@ -1012,5 +987,44 @@ def _get_modules_directories(self) -> list[str]: def _get_filter_plugin_directory(self): return util.abs_path(os.path.join(self._get_plugin_directory(), "filter")) + def _get_filter_plugins_directories(self) -> list[str]: + """Return list of ansilbe filter plugins includes directories.""" + paths: list[str | None] = [] + if os.environ.get("ANSIBLE_FILTER_PLUGINS"): + paths = list( + map(util.abs_path, os.environ["ANSIBLE_FILTER_PLUGINS"].split(":")), + ) + + paths.extend( + [ + self._get_filter_plugin_directory(), + util.abs_path( + os.path.join( + self._config.scenario.ephemeral_directory, + "plugins", + "filter", + ), + ), + util.abs_path( + os.path.join( + self._config.project_directory, + "plugins", + "filter", + ), + ), + util.abs_path( + os.path.join( + os.path.expanduser("~"), + ".ansible", + "plugins", + "filter", + ), + ), + "/usr/share/ansible/plugins/filter", + ], + ) + + return [path for path in paths if path is not None] + def _absolute_path_for(self, env, key): return ":".join([self.abs_path(p) for p in env[key].split(":")]) diff --git a/test/a_unit/provisioner/test_ansible.py b/test/a_unit/provisioner/test_ansible.py index 58f3c61637..9e4a365783 100644 --- a/test/a_unit/provisioner/test_ansible.py +++ b/test/a_unit/provisioner/test_ansible.py @@ -749,6 +749,47 @@ def test_get_filter_plugin_directory(_instance): assert x == parts[-5:] +def test_get_filter_plugins_directories_default(_instance, monkeypatch): + monkeypatch.delenv("ANSIBLE_FILTER_PLUGINS", raising=False) + + paths = _instance._get_filter_plugins_directories() + + assert len(paths) == 5 + assert re.search(r"molecule/provisioner/ansible/plugins/filter$", paths[0]) + assert re.search(r"\.cache/molecule/[^/]+/default/plugins/filter$", paths[1]) + assert re.search(r"/filter$", paths[2]) + assert re.search(r"\.ansible/plugins/filter$", paths[3]) + assert re.search(r"/usr/share/ansible/plugins/filter$", paths[4]) + + +def tes_get_filter_plugins_directories_single_ansible_filter_plugins( + _instance, + monkeypatch, +): + monkeypatch.setenv("ANSIBLE_FILTER_PLUGINS", "/abs/path/plugins/filter") + + paths = _instance._get_filter_plugins_directories() + + assert len(paths) == 6 + assert paths[0] == "/abs/path/plugins/filter" + + +def test_get_filter_plugins_directories_multi_ansible_filter_plugins( + _instance, + monkeypatch, +): + monkeypatch.setenv( + "ANSIBLE_FILTER_PLUGINS", + "relpath/plugins/filter:/abs/path/plugins/filter", + ) + + paths = _instance._get_filter_plugins_directories() + + assert len(paths) == 7 + assert paths[0].endswith("relpath/plugins/filter") + assert paths[1] == "/abs/path/plugins/filter" + + def test_absolute_path_for(_instance): env = {"foo": "foo:bar"} x = ":".join(