diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2fafccce..e2a45c03 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,10 +19,10 @@ jobs: TOX_PARALLEL_NO_SPINNER: 1 steps: - - name: Switch to using Python 3.9 by default + - name: Switch to using Python 3.10 by default uses: actions/setup-python@v5 with: - python-version: 3.9 + python-version: 3.10 - name: Install tox run: >- diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 0763b07b..f3c09af4 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -23,9 +23,9 @@ jobs: id: generate_matrix uses: coactions/dynamic-matrix@v1 with: - min_python: "3.9" + min_python: "3.10" max_python: "3.12" - default_python: "3.9" # used by jobs in other_names + default_python: "3.10" # used by jobs in other_names other_names: | lint pkg diff --git a/conftest.py b/conftest.py index c9b4a4f2..2a96b19d 100644 --- a/conftest.py +++ b/conftest.py @@ -3,10 +3,12 @@ import random import shutil import string +from pathlib import Path import pytest -from molecule import config, logger, util +from molecule import config, logger +from molecule.app import get_app from molecule.scenario import ephemeral_directory LOG = logger.get_logger(__name__) @@ -18,7 +20,7 @@ def run_command(cmd, env=os.environ, log=True): if log: cmd = _rebake_command(cmd, env) cmd = cmd.bake(_truncate_exc=False) - return util.run_command(cmd, env=env) + return get_app(Path()).run_command(cmd, env=env) def _rebake_command(cmd, env, out=LOG.info, err=LOG.error): diff --git a/pyproject.toml b/pyproject.toml index 18d1c2df..46294d93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] # https://peps.python.org/pep-0621/#readme -requires-python = ">=3.9" +requires-python = ">=3.10" dynamic = ["version"] name = "molecule-plugins" description = "Molecule Plugins" @@ -26,7 +26,6 @@ classifiers = [ "Operating System :: MacOS", "Operating System :: POSIX", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -40,7 +39,7 @@ classifiers = [ keywords = ["ansible", "testing", "molecule", "plugin"] dependencies = [ # molecule plugins are not allowed to mention Ansible as a direct dependency - "molecule >= 6.0.0a1", + "molecule >= 25.1.0", ] [project.urls] @@ -52,7 +51,7 @@ changelog = "https://github.com/ansible-community/molecule-plugins/releases" [project.optional-dependencies] test = [ "pytest-helpers-namespace >= 2019.1.8", - "molecule[test] >= 6.0.0a1" + "molecule[test] >= 25.1.0" ] azure = [] docker = [ @@ -89,7 +88,7 @@ openstack = [ ] [tool.ruff] -ignore = [ +lint.ignore = [ "E501", # we use black # we deliberately ignore these: "EM102", @@ -101,6 +100,7 @@ ignore = [ "B028", "BLE", "C901", + "COM812", "D", "DTZ", "FBT", @@ -119,15 +119,15 @@ ignore = [ "FIX002", "TRY", ] -select = ["ALL"] +lint.select = ["ALL"] target-version = "py39" # Same as Black. line-length = 88 -[tool.ruff.flake8-pytest-style] +[tool.ruff.lint.flake8-pytest-style] parametrize-values-type = "tuple" -[tool.ruff.isort] +[tool.ruff.lint.isort] known-first-party = ["molecule_plugins"] [project.entry-points."molecule.driver"] diff --git a/src/molecule_plugins/docker/driver.py b/src/molecule_plugins/docker/driver.py index 385a6138..7c8f9fc2 100644 --- a/src/molecule_plugins/docker/driver.py +++ b/src/molecule_plugins/docker/driver.py @@ -19,7 +19,6 @@ # DEALINGS IN THE SOFTWARE. """Docker Driver Module.""" - import os from molecule import logger diff --git a/src/molecule_plugins/podman/driver.py b/src/molecule_plugins/podman/driver.py index 5f7621c6..8c7a150b 100644 --- a/src/molecule_plugins/podman/driver.py +++ b/src/molecule_plugins/podman/driver.py @@ -19,9 +19,9 @@ # DEALINGS IN THE SOFTWARE. """Podman Driver Module.""" - import os import warnings +from pathlib import Path from shutil import which from ansible_compat.runtime import Runtime @@ -29,8 +29,9 @@ from molecule import logger, util from molecule.api import Driver, MoleculeRuntimeWarning +from molecule.app import get_app from molecule.constants import RC_SETUP_ERROR -from molecule.util import run_command, sysexit_with_message +from molecule.util import sysexit_with_message log = logger.get_logger(__name__) @@ -246,4 +247,6 @@ def required_collections(self) -> dict[str, str]: def reset(self): # keep `--filter` in sync with playbooks/create.yml - run_command(["podman", "rm", "--force", "--filter=label=owner=molecule"]) + get_app(Path()).run_command( + ["podman", "rm", "--force", "--filter=label=owner=molecule"] + ) diff --git a/src/molecule_plugins/vagrant/modules/vagrant.py b/src/molecule_plugins/vagrant/modules/vagrant.py index 10661bc0..0e094280 100755 --- a/src/molecule_plugins/vagrant/modules/vagrant.py +++ b/src/molecule_plugins/vagrant/modules/vagrant.py @@ -503,10 +503,7 @@ def _conf_instance(self, instance_name): try: return self._vagrant.conf(vm_name=instance_name) except Exception: - msg = "Failed to get vagrant config for {}: See log file '{}'".format( - instance_name, - self._get_stderr_log(), - ) + msg = f"Failed to get vagrant config for {instance_name}: See log file '{self._get_stderr_log()}'" with open(self._get_stderr_log(), encoding="utf-8") as f: self.result["stderr"] = f.read() self._module.fail_json(msg=msg, **self.result) @@ -517,10 +514,7 @@ def _status_instance(self, instance_name): return {"name": s.name, "state": s.state, "provider": s.provider} except Exception: - msg = "Failed to get status for {}: See log file '{}'".format( - instance_name, - self._get_stderr_log(), - ) + msg = f"Failed to get status for {instance_name}: See log file '{self._get_stderr_log()}'" with open(self._get_stderr_log(), encoding="utf-8") as f: self.result["stderr"] = f.read() self._module.fail_json(msg=msg, **self.result) @@ -697,7 +691,7 @@ def _get_stdout_log(self): def _get_stderr_log(self): return self._get_vagrant_log("err") - def _get_vagrant_log(self, __type): + def _get_vagrant_log(self, __type, /): return os.path.join(self._config["workdir"], f"vagrant.{__type}") diff --git a/test/azure/functional/test_azure.py b/test/azure/functional/test_azure.py index ffe94689..f8f0438e 100644 --- a/test/azure/functional/test_azure.py +++ b/test/azure/functional/test_azure.py @@ -20,12 +20,13 @@ # DEALINGS IN THE SOFTWARE. import os +from pathlib import Path import pytest from conftest import change_dir_to from molecule import logger -from molecule.util import run_command +from molecule.app import get_app LOG = logger.get_logger(__name__) @@ -33,7 +34,7 @@ def test_azure_command_init_scenario(temp_dir): role_directory = os.path.join(temp_dir.strpath, "test_init") cmd = ["ansible-galaxy", "role", "init", "test_init"] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 with change_dir_to(role_directory): @@ -47,7 +48,7 @@ def test_azure_command_init_scenario(temp_dir): "-a", 'path=meta/main.yml line=" namespace: foo" insertafter=" author: your name"', ] - run_command(cmd_meta, check=True) + get_app(Path()).run_command(cmd_meta, check=True) # we need to inject namespace info into tests/test.yml cmd_tests = [ @@ -59,7 +60,7 @@ def test_azure_command_init_scenario(temp_dir): "-a", 'path=tests/test.yml line=" - foo.test_init" regex="^(.*) - test_init"', ] - run_command(cmd_tests, check=True) + get_app(Path()).run_command(cmd_tests, check=True) molecule_directory = pytest.helpers.molecule_directory() scenario_directory = os.path.join(molecule_directory, "test_scenario") @@ -71,7 +72,7 @@ def test_azure_command_init_scenario(temp_dir): "--driver-name", "azure", ] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 assert os.path.isdir(scenario_directory) @@ -82,5 +83,5 @@ def test_azure_command_init_scenario(temp_dir): # temporary trick to pass on CI/CD if "AZURE_SECRET" in os.environ: cmd = ["molecule", "test", "-s", "test-scenario"] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 diff --git a/test/containers/functional/test_containers.py b/test/containers/functional/test_containers.py index 3b3ddea0..25799777 100644 --- a/test/containers/functional/test_containers.py +++ b/test/containers/functional/test_containers.py @@ -19,11 +19,13 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. """Functional Tests.""" + import os +from pathlib import Path from conftest import change_dir_to, molecule_directory from molecule import logger -from molecule.util import run_command +from molecule.app import get_app LOG = logger.get_logger(__name__) @@ -40,7 +42,7 @@ def test_containers_command_init_scenario(temp_dir): "--driver-name", "containers", ] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 assert os.path.isdir(scenario_directory) @@ -49,5 +51,5 @@ def test_containers_command_init_scenario(temp_dir): # is shorter but comprehensive enough to test the most important # functionality: destroy, dependency, create, prepare, converge cmd = ["molecule", "check", "-s", "default"] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 diff --git a/test/docker/test_func.py b/test/docker/test_func.py index 481ebf6d..aba06115 100644 --- a/test/docker/test_func.py +++ b/test/docker/test_func.py @@ -4,12 +4,13 @@ import pathlib import shutil import subprocess +from pathlib import Path import pytest from conftest import change_dir_to from molecule import logger -from molecule.util import run_command +from molecule.app import get_app LOG = logger.get_logger(__name__) @@ -40,21 +41,25 @@ def test_command_init_and_test_scenario(tmp_path: pathlib.Path, DRIVER: str) -> "--driver-name", DRIVER, ] - result = run_command(cmd) + result = get_app(tmp_path).run_command(cmd) assert result.returncode == 0 assert scenario_directory.exists() # run molecule reset as this may clean some leftovers from other # test runs and also ensure that reset works. - result = run_command(["molecule", "reset"]) # default scenario + result = get_app(tmp_path).run_command( + ["molecule", "reset"] + ) # default scenario assert result.returncode == 0 - result = run_command(["molecule", "reset", "-s", scenario_name]) + result = get_app(tmp_path).run_command( + ["molecule", "reset", "-s", scenario_name] + ) assert result.returncode == 0 cmd = ["molecule", "--debug", "test", "-s", scenario_name] - result = run_command(cmd) + result = get_app(tmp_path).run_command(cmd) assert result.returncode == 0 @@ -63,7 +68,7 @@ def test_command_static_scenario() -> None: """Validate that the scenario we included with code still works.""" cmd = ["molecule", "test"] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 @@ -72,7 +77,7 @@ def test_dockerfile_with_context() -> None: """Verify that Dockerfile.j2 with context works.""" with change_dir_to("test/docker/scenarios/with-context"): cmd = ["molecule", "--debug", "test"] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 @@ -82,5 +87,5 @@ def test_env_substitution() -> None: os.environ["MOLECULE_ROLE_IMAGE"] = "debian:bullseye" with change_dir_to("test/docker/scenarios/env-substitution"): cmd = ["molecule", "--debug", "test"] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 diff --git a/test/ec2/functional/test_ec2.py b/test/ec2/functional/test_ec2.py index e546a442..f721a791 100644 --- a/test/ec2/functional/test_ec2.py +++ b/test/ec2/functional/test_ec2.py @@ -20,12 +20,13 @@ # DEALINGS IN THE SOFTWARE. import os +from pathlib import Path import pytest from conftest import change_dir_to, metadata_lint_update from molecule import logger -from molecule.util import run_command +from molecule.app import get_app LOG = logger.get_logger(__name__) @@ -34,7 +35,7 @@ def test_ec2_command_init_scenario(temp_dir): role_directory = os.path.join(temp_dir.strpath, "test-init") cmd = ["molecule", "init", "role", "test-init"] - assert run_command(cmd).returncode == 0 + assert get_app(Path()).run_command(cmd).returncode == 0 metadata_lint_update(role_directory) with change_dir_to(role_directory): @@ -48,11 +49,11 @@ def test_ec2_command_init_scenario(temp_dir): "--role_name=test-init", "--driver-name=ec2", ] - assert run_command(cmd).returncode == 0 + assert get_app(Path()).run_command(cmd).returncode == 0 assert os.path.isdir(scenario_directory) os.unlink(os.path.join(scenario_directory, "create.yml")) os.unlink(os.path.join(scenario_directory, "destroy.yml")) cmd = ["molecule", "test", "-s", "test-scenario"] - assert run_command(cmd).returncode == 0 + assert get_app(Path()).run_command(cmd).returncode == 0 diff --git a/test/gce/functional/test_func.py b/test/gce/functional/test_func.py index 8fe05f15..8fbacdbe 100644 --- a/test/gce/functional/test_func.py +++ b/test/gce/functional/test_func.py @@ -20,12 +20,13 @@ # DEALINGS IN THE SOFTWARE. import os +from pathlib import Path import pytest from conftest import change_dir_to, metadata_lint_update from molecule import logger -from molecule.util import run_command +from molecule.app import get_app LOG = logger.get_logger(__name__) driver_name = __name__.split(".")[0].split("_")[-1] @@ -36,7 +37,7 @@ def test_gce_command_init_scenario(temp_dir): """Test init scenario with driver.""" role_directory = os.path.join(temp_dir.strpath, "test-init") cmd = ["molecule", "init", "role", "test-init"] - assert run_command(cmd).returncode == 0 + assert get_app(Path()).run_command(cmd).returncode == 0 metadata_lint_update(role_directory) with change_dir_to(role_directory): @@ -52,11 +53,11 @@ def test_gce_command_init_scenario(temp_dir): "--driver-name", driver_name, ] - assert run_command(cmd).returncode == 0 + assert get_app(Path()).run_command(cmd).returncode == 0 assert os.path.isdir(scenario_directory) os.unlink(os.path.join(scenario_directory, "create.yml")) os.unlink(os.path.join(scenario_directory, "destroy.yml")) cmd = ["molecule", "test", "-s", "test-scenario"] - assert run_command(cmd).returncode == 0 + assert get_app(Path()).run_command(cmd).returncode == 0 diff --git a/test/openstack/test_func.py b/test/openstack/test_func.py index 44e57c5b..6ca8aa81 100644 --- a/test/openstack/test_func.py +++ b/test/openstack/test_func.py @@ -4,13 +4,14 @@ import pathlib import shutil import subprocess +from pathlib import Path import pytest import openstack from conftest import change_dir_to from molecule import logger -from molecule.util import run_command +from molecule.app import get_app LOG = logger.get_logger(__name__) @@ -53,7 +54,7 @@ def test_openstack_init_and_test_scenario(tmp_path: pathlib.Path, DRIVER: str) - "--driver-name", DRIVER, ] - result = run_command(cmd) + result = get_app(tmp_path).run_command(cmd) assert result.returncode == 0 assert scenario_directory.exists() @@ -71,7 +72,7 @@ def test_openstack_init_and_test_scenario(tmp_path: pathlib.Path, DRIVER: str) - shutil.copyfile(testconf, confpath) cmd = ["molecule", "--debug", "test", "-s", scenario_name] - result = run_command(cmd) + result = get_app(tmp_path).run_command(cmd) assert result.returncode == 0 @@ -86,5 +87,5 @@ def test_specific_scenarios(temp_dir, scenario) -> None: with change_dir_to(scenario_directory): cmd = ["molecule", "test", "--scenario-name", scenario] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 diff --git a/test/podman/test_func.py b/test/podman/test_func.py index f314a156..25cc7793 100644 --- a/test/podman/test_func.py +++ b/test/podman/test_func.py @@ -3,10 +3,11 @@ import os import pathlib import subprocess +from pathlib import Path from conftest import change_dir_to from molecule import logger -from molecule.util import run_command +from molecule.app import get_app from molecule_plugins.podman import __file__ as module_file LOG = logger.get_logger(__name__) @@ -35,27 +36,33 @@ def test_podman_command_init_scenario(tmp_path: pathlib.Path): "--driver-name", "podman", ] - result = run_command(cmd) + result = get_app(tmp_path).run_command(cmd) assert result.returncode == 0 assert scenario_directory.exists() # run molecule reset as this may clean some leftovers from other # test runs and also ensure that reset works. - result = run_command(["molecule", "reset"]) # default sceanario + result = get_app(tmp_path).run_command( + ["molecule", "reset"] + ) # default sceanario assert result.returncode == 0 - result = run_command(["molecule", "reset", "-s", scenario_name]) + result = get_app(tmp_path).run_command( + ["molecule", "reset", "-s", scenario_name] + ) assert result.returncode == 0 cmd = ["molecule", "--debug", "test", "-s", scenario_name] - result = run_command(cmd) + result = get_app(tmp_path).run_command(cmd) assert result.returncode == 0 def test_sample() -> None: """Runs the sample scenario present at the repository root.""" - result = run_command(["molecule", "test", "-s", "test-podman"]) # default sceanario + result = get_app(Path()).run_command( + ["molecule", "test", "-s", "test-podman"] + ) # default sceanario assert result.returncode == 0 diff --git a/test/vagrant-plugin/functional/test_func.py b/test/vagrant-plugin/functional/test_func.py index 9fedef4e..3373ab15 100644 --- a/test/vagrant-plugin/functional/test_func.py +++ b/test/vagrant-plugin/functional/test_func.py @@ -22,14 +22,15 @@ import os import platform import shutil +from pathlib import Path import pytest import vagrant from conftest import change_dir_to from molecule import logger, util +from molecule.app import get_app from molecule.scenario import ephemeral_directory -from molecule.util import run_command LOG = logger.get_logger(__name__) @@ -38,9 +39,8 @@ def is_vagrant_supported() -> bool: """Return True if vagrant is installed and current platform is supported.""" if not shutil.which("vagrant"): return False - if platform.machine() == "arm64" and platform.system() == "Darwin": - return False - return True + if not (platform.machine() == "arm64" and platform.system() == "Darwin"): + return True @pytest.mark.skipif( @@ -59,7 +59,7 @@ def test_vagrant_command_init_scenario(temp_dir): "--driver-name", "vagrant", ] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 assert os.path.isdir(scenario_directory) @@ -77,7 +77,7 @@ def test_vagrant_command_init_scenario(temp_dir): conf["driver"]["provider"] = {"name": "libvirt"} util.write_file(confpath, util.safe_dump(conf)) cmd = ["molecule", "--debug", "test", "-s", "test-scenario"] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 @@ -94,7 +94,7 @@ def test_invalid_settings(temp_dir): with change_dir_to(scenario_directory): cmd = ["molecule", "create", "--scenario-name", "invalid"] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 2 assert "Failed to validate generated Vagrantfile" in result.stdout @@ -126,7 +126,7 @@ def test_vagrant_root(temp_dir, scenario): with change_dir_to(scenario_directory): cmd = ["molecule", "test", "--scenario-name", scenario] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 @@ -143,7 +143,7 @@ def test_multi_node(temp_dir): with change_dir_to(scenario_directory): cmd = ["molecule", "test", "--scenario-name", "multi-node"] - result = run_command(cmd) + result = get_app(Path()).run_command(cmd) assert result.returncode == 0 molecule_eph_directory = ephemeral_directory()