From be761ae439ef7035ebd31b0b8870e75b52762c5f Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Fri, 25 Jun 2021 16:01:11 +0100 Subject: [PATCH] Replace ansible-lint dependency with ansible-compat Related: https://github.com/ansible-community/ansible-compat/issues/4 --- .github/workflows/tox.yml | 12 ++++++------ .pre-commit-config.yaml | 3 +-- setup.cfg | 2 +- src/molecule/command/base.py | 3 +-- src/molecule/config.py | 17 +++++++++++++++-- src/molecule/dependency/base.py | 4 ---- src/molecule/provisioner/ansible.py | 1 - src/molecule/shell.py | 8 ++++---- src/molecule/test/functional/conftest.py | 10 ++++++---- src/molecule/test/unit/conftest.py | 11 ++++++++--- .../test/unit/provisioner/test_ansible.py | 12 ------------ 11 files changed, 42 insertions(+), 41 deletions(-) diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index a560fa4344..720200fe49 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -25,17 +25,17 @@ jobs: - tox_env: lint - tox_env: docs - tox_env: py36 - PREFIX: PYTEST_REQPASS=449 + PREFIX: PYTEST_REQPASS=448 - tox_env: py37 - PREFIX: PYTEST_REQPASS=449 + PREFIX: PYTEST_REQPASS=448 - tox_env: py38 - PREFIX: PYTEST_REQPASS=449 + PREFIX: PYTEST_REQPASS=448 - tox_env: py39 - PREFIX: PYTEST_REQPASS=449 + PREFIX: PYTEST_REQPASS=448 - tox_env: py36-devel - PREFIX: PYTEST_REQPASS=449 + PREFIX: PYTEST_REQPASS=448 - tox_env: py39-devel - PREFIX: PYTEST_REQPASS=449 + PREFIX: PYTEST_REQPASS=448 - tox_env: packaging - tox_env: eco - tox_env: dockerfile diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 71ef15085f..27500f3be0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -54,7 +54,7 @@ repos: entry: mypy src/ pass_filenames: false additional_dependencies: - - ansible-lint>=5.0.10 + - ansible-compat>=0.3.0 - packaging - enrich>=1.2.5 - subprocess-tee>=0.2.0 @@ -63,7 +63,6 @@ repos: hooks: - id: pylint additional_dependencies: - - ansible-lint>=5.0.10 - enrich>=1.2.5 - subprocess-tee>=0.2.0 - testinfra diff --git a/setup.cfg b/setup.cfg index 423d6fa378..c506385fcf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -66,7 +66,7 @@ setup_requires = # These are required in actual runtime: install_requires = - ansible-lint >= 5.0.12 # only for the prerun functionality + ansible-compat >= 0.3.0 cerberus >= 1.3.1, !=1.3.3, !=1.3.4 click >= 8.0, < 9 click-help-colors >= 0.9 diff --git a/src/molecule/command/base.py b/src/molecule/command/base.py index d32f57c7de..b85b0324ab 100644 --- a/src/molecule/command/base.py +++ b/src/molecule/command/base.py @@ -28,7 +28,6 @@ from typing import Any, Callable import click -from ansiblelint.prerun import prepare_environment from click_help_colors import HelpColorsCommand, HelpColorsGroup import molecule.scenarios @@ -109,7 +108,7 @@ def execute_cmdline_scenarios(scenario_name, args, command_args, ansible_args=() if scenario.config.config["prerun"]: LOG.info("Performing prerun...") - prepare_environment() + scenario.config.runtime.prepare_environment() if command_args.get("subcommand") == "reset": LOG.info("Removing %s" % scenario.ephemeral_directory) diff --git a/src/molecule/config.py b/src/molecule/config.py index d926b8c728..09869cdb0b 100644 --- a/src/molecule/config.py +++ b/src/molecule/config.py @@ -23,10 +23,12 @@ import functools import logging import os +import warnings from typing import Callable, MutableMapping, TypeVar from uuid import uuid4 -from ansiblelint.config import ansible_version +from ansible_compat.runtime import Runtime +from packaging.version import Version from molecule import api, interpolation, platforms, scenario, state, util from molecule.dependency import ansible_galaxy, shell @@ -51,6 +53,16 @@ def cache(func: Callable[..., T]) -> T: return functools.lru_cache()(func) # type: ignore +@cache +def ansible_version() -> Version: + """Retrieve Ansible version.""" + warnings.warn( + "molecule.config.ansible_version is deprecated, will be removed in the future.", + category=DeprecationWarning, + ) + return Runtime().version + + # https://stackoverflow.com/questions/16017397/injecting-function-call-after-init-with-decorator # noqa class NewInitCaller(type): """NewInitCaller.""" @@ -102,6 +114,7 @@ def __init__(self, molecule_file: str, args={}, command_args={}, ansible_args=() self._action = None self._run_uuid = str(uuid4()) self.project_directory = os.getenv("MOLECULE_PROJECT_DIRECTORY", os.getcwd()) + self.runtime = Runtime(isolated=True) def after_init(self): self.config = self._reget_config() @@ -115,7 +128,7 @@ def write(self) -> None: def ansible_collections_path(self): """Return collection path variable for current version of Ansible.""" # https://github.com/ansible/ansible/pull/70007 - if ansible_version() >= ansible_version("2.10.0.dev0"): + if self.runtime.version >= Version("2.10.0.dev0"): return "ANSIBLE_COLLECTIONS_PATH" else: return "ANSIBLE_COLLECTIONS_PATHS" diff --git a/src/molecule/dependency/base.py b/src/molecule/dependency/base.py index 0a857764fb..bf7cfff0f2 100644 --- a/src/molecule/dependency/base.py +++ b/src/molecule/dependency/base.py @@ -105,10 +105,6 @@ def default_env(self): # pragma: no cover :return: dict """ env = util.merge_dicts(os.environ, self._config.env) - # inject ephemeral_directory on top of path - env[self._config.ansible_collections_path] = os.path.join( - self._config.scenario.ephemeral_directory, "collections" - ) return env @property diff --git a/src/molecule/provisioner/ansible.py b/src/molecule/provisioner/ansible.py index 734429cb3f..72ac636640 100644 --- a/src/molecule/provisioner/ansible.py +++ b/src/molecule/provisioner/ansible.py @@ -457,7 +457,6 @@ def default_env(self): *os.environ.get("ANSIBLE_ROLES_PATH", "").split(":"), ] ), - self._config.ansible_collections_path: ":".join(collections_path_list), "ANSIBLE_LIBRARY": ":".join(self._get_modules_directories()), "ANSIBLE_FILTER_PLUGINS": ":".join( [ diff --git a/src/molecule/shell.py b/src/molecule/shell.py index 6fca6103e8..6764a097df 100644 --- a/src/molecule/shell.py +++ b/src/molecule/shell.py @@ -24,12 +24,13 @@ import click import pkg_resources +from ansible_compat.runtime import Runtime import molecule from molecule import command, logger from molecule.api import drivers from molecule.command.base import click_group_ex -from molecule.config import MOLECULE_DEBUG, MOLECULE_VERBOSITY, ansible_version +from molecule.config import MOLECULE_DEBUG, MOLECULE_VERBOSITY from molecule.console import console from molecule.util import do_report, lookup_config_file @@ -59,9 +60,8 @@ def print_version(ctx, param, value): color = "bright_yellow" if v.is_prerelease else "green" msg = f"molecule [{color}]{v}[/] using python [repr.number]{sys.version_info[0]}.{sys.version_info[1]}[/] \n" - msg += ( - f" [repr.attrib_name]ansible[/][dim]:[/][repr.number]{ansible_version()}[/]" - ) + runtime = Runtime() + msg += f" [repr.attrib_name]ansible[/][dim]:[/][repr.number]{runtime.version}[/]" for driver in drivers(): msg += f"\n [repr.attrib_name]{str(driver)}[/][dim]:[/][repr.number]{driver.version}[/][dim] from {driver.module}[/]" console.print(msg) diff --git a/src/molecule/test/functional/conftest.py b/src/molecule/test/functional/conftest.py index ebcab1c4a1..9dee60c86d 100644 --- a/src/molecule/test/functional/conftest.py +++ b/src/molecule/test/functional/conftest.py @@ -27,9 +27,10 @@ import pexpect import pkg_resources import pytest +from ansible_compat.runtime import Runtime +from packaging.version import Version from molecule import logger, util -from molecule.config import ansible_version from molecule.test.conftest import change_dir_to from molecule.text import strip_ansi_color from molecule.util import run_command @@ -106,9 +107,9 @@ def idempotence(scenario_name): @pytest.helpers.register def init_role(temp_dir, driver_name): - role_directory = os.path.join(temp_dir.strpath, "test-init") + role_directory = os.path.join(temp_dir.strpath, "myorg.myrole") - cmd = ["molecule", "init", "role", "test-init", "--driver-name", driver_name] + cmd = ["molecule", "init", "role", "myorg.myrole", "--driver-name", driver_name] assert run_command(cmd).returncode == 0 pytest.helpers.metadata_lint_update(role_directory) @@ -267,4 +268,5 @@ def supports_docker(): def min_ansible(version: str) -> bool: """Ensure current Ansible is newer than a given a minimal one.""" - return ansible_version() >= ansible_version(version) + runtime = Runtime() + return bool(runtime.version >= Version(version)) diff --git a/src/molecule/test/unit/conftest.py b/src/molecule/test/unit/conftest.py index 4daca0edf4..534befb2ae 100644 --- a/src/molecule/test/unit/conftest.py +++ b/src/molecule/test/unit/conftest.py @@ -24,6 +24,7 @@ import shutil from pathlib import Path from subprocess import CompletedProcess +from typing import Generator from uuid import uuid4 import pytest @@ -140,15 +141,19 @@ def molecule_file_fixture( @pytest.fixture def config_instance( molecule_file_fixture: str, molecule_data, request -) -> config.Config: +) -> Generator[config.Config, None, None]: mdc = copy.deepcopy(molecule_data) if hasattr(request, "param"): mdc = util.merge_dicts(mdc, request.getfixturevalue(request.param)) pytest.helpers.write_molecule_file(molecule_file_fixture, mdc) + + _environ = dict(os.environ) c = config.Config(molecule_file_fixture) c.command_args = {"subcommand": "test"} - - return c + yield c + # restore environ which can be modified by Config() + os.environ.clear() + os.environ.update(_environ) # Mocks diff --git a/src/molecule/test/unit/provisioner/test_ansible.py b/src/molecule/test/unit/provisioner/test_ansible.py index faaf7a9999..74b28fc550 100644 --- a/src/molecule/test/unit/provisioner/test_ansible.py +++ b/src/molecule/test/unit/provisioner/test_ansible.py @@ -133,18 +133,6 @@ def test_default_env_property(_instance): assert "ANSIBLE_FILTER_PLUGINS" in _instance.env -def test_default_env_property_collections_path(config_instance): - config_instance.project_directory = ( - "/some/path/ansible_collections/namespace/collection/but/not/really" - "/ansible_collections/other_ns/other_name/and/some/more/segments" - ) - - env = ansible.Ansible(config_instance).default_env - - paths = env[config_instance.ansible_collections_path].split(":") - assert "/some/path/ansible_collections/namespace/collection/but/not/really" in paths - - def test_name_property(_instance): assert "ansible" == _instance.name