diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 6ebb6fd4..30ad719d 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-22.04 needs: pre env: - PYTEST_REQPASS: 11 + PYTEST_REQPASS: 13 strategy: fail-fast: false matrix: ${{ fromJson(needs.pre.outputs.matrix) }} diff --git a/pyproject.toml b/pyproject.toml index a54f1367..7154c9ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -79,6 +79,7 @@ podman = [ [project.entry-points."molecule.driver"] azure = "molecule_plugins.azure.driver:Azure" +containers = "molecule_plugins.containers.driver:Container" docker = "molecule_plugins.docker.driver:Docker" ec2 = "molecule_plugins.ec2.driver:EC2" gce = "molecule_plugins.gce.driver:GCE" diff --git a/src/molecule_plugins/containers/__init__.py b/src/molecule_plugins/containers/__init__.py new file mode 100644 index 00000000..c116a8de --- /dev/null +++ b/src/molecule_plugins/containers/__init__.py @@ -0,0 +1 @@ +"""Molecule Containers Drivers.""" diff --git a/src/molecule_plugins/containers/cookiecutter/cookiecutter.json b/src/molecule_plugins/containers/cookiecutter/cookiecutter.json new file mode 100644 index 00000000..2ec6fb29 --- /dev/null +++ b/src/molecule_plugins/containers/cookiecutter/cookiecutter.json @@ -0,0 +1,5 @@ +{ + "molecule_directory": "molecule", + "role_name": "OVERRIDDEN", + "scenario_name": "OVERRIDDEN" +} diff --git a/src/molecule_plugins/containers/cookiecutter/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/converge.yml b/src/molecule_plugins/containers/cookiecutter/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/converge.yml new file mode 100644 index 00000000..64290974 --- /dev/null +++ b/src/molecule_plugins/containers/cookiecutter/{{cookiecutter.molecule_directory}}/{{cookiecutter.scenario_name}}/converge.yml @@ -0,0 +1,10 @@ +--- +- name: Converge + hosts: all + # Disabled gather as it seems broken on podman + # https://github.com/ansible-community/molecule-podman/issues/2 + gather_facts: false + tasks: + - name: Test implementation + debug: + msg: Add test implementation here diff --git a/src/molecule_plugins/containers/driver.py b/src/molecule_plugins/containers/driver.py new file mode 100644 index 00000000..105447a9 --- /dev/null +++ b/src/molecule_plugins/containers/driver.py @@ -0,0 +1,54 @@ +"""Containers Driver Module.""" +from __future__ import absolute_import + +import inspect +import os +import shutil +from typing import Dict + +from molecule import logger + +_logger = logger.get_logger(__name__) + +# Preference logic for picking backend driver to be used. +drivers = os.environ.get("MOLECULE_CONTAINERS_BACKEND", "podman,docker").split(",") +for driver in drivers: + if shutil.which(driver): + break +else: + driver = drivers[0] + +# Logic for picking backend is subject to change. +if driver == "docker": + from molecule_plugins.docker.driver import Docker as DriverBackend +elif driver == "podman": + from molecule_plugins.podman.driver import Podman as DriverBackend +else: + raise NotImplementedError(f"Driver {driver} is not supported.") +_logger.debug("Containers driver will use %s backend", driver) + + +class Container(DriverBackend): + """ + Container Driver Class. + + This class aims to provide an agnostic container enginer implementation, + which should allow users to consume whichever enginer they have available. + """ # noqa + + def __init__(self, config=None): + """Construct Container.""" + super().__init__(config) + self._name = "containers" + # Assure that _path points to the driver we would be using, or + # molecule will fail to find the embedded playbooks. + self._path = os.path.abspath(os.path.dirname(inspect.getfile(DriverBackend))) + + @property + def required_collections(self) -> Dict[str, str]: + """Return collections dict containing names and versions required.""" + return { + "ansible.posix": "1.3.0", + "community.docker": "1.9.1", + "containers.podman": "1.8.1", + } diff --git a/test/containers/__init__.py b/test/containers/__init__.py new file mode 100644 index 00000000..db4323ed --- /dev/null +++ b/test/containers/__init__.py @@ -0,0 +1 @@ +"""Molecule Containers Driver Tests.""" diff --git a/test/containers/functional/.ansible-lint b/test/containers/functional/.ansible-lint new file mode 100644 index 00000000..c54b8ec5 --- /dev/null +++ b/test/containers/functional/.ansible-lint @@ -0,0 +1,9 @@ +# ansible-lint config for functional testing, used to bypass expected metadata +# errors in molecule-generated roles. Loaded via the metadata_lint_update +# pytest helper. For reference, see "E7xx - metadata" in: +# https://docs.ansible.com/ansible-lint/rules/default_rules.html +skip_list: + # metadata/701 - Role info should contain platforms + - '701' + # metadata/703 - Should change default metadata: " + - '703' diff --git a/test/containers/functional/__init__.py b/test/containers/functional/__init__.py new file mode 100644 index 00000000..31a929af --- /dev/null +++ b/test/containers/functional/__init__.py @@ -0,0 +1 @@ +"""Functional Tests.""" diff --git a/test/containers/functional/conftest.py b/test/containers/functional/conftest.py new file mode 100644 index 00000000..452fb67b --- /dev/null +++ b/test/containers/functional/conftest.py @@ -0,0 +1,23 @@ +# Copyright (c) 2015-2018 Cisco Systems, Inc. +# Copyright (c) 2018 Red Hat, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +"""PyTest Config.""" + +from molecule.test.conftest import * # noqa pylint: disable=wildcard-import,unused-wildcard-import diff --git a/test/containers/functional/test_containers.py b/test/containers/functional/test_containers.py new file mode 100644 index 00000000..b9ae722a --- /dev/null +++ b/test/containers/functional/test_containers.py @@ -0,0 +1,53 @@ +# Copyright (c) 2015-2018 Cisco Systems, Inc. +# Copyright (c) 2018 Red Hat, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +"""Functional Tests.""" +import os + +from molecule import logger +from molecule.test.conftest import change_dir_to, molecule_directory +from molecule.util import run_command + +LOG = logger.get_logger(__name__) + + +def test_command_init_scenario(temp_dir): + """Verify that we can initialize a new scenario with this driver.""" + with change_dir_to(temp_dir): + scenario_directory = os.path.join(molecule_directory(), "default") + cmd = [ + "molecule", + "init", + "scenario", + "default", + "--driver-name", + "containers", + ] + result = run_command(cmd) + assert result.returncode == 0 + + assert os.path.isdir(scenario_directory) + + # we do not run the full "test" sequence because lint will fail, check + # 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) + assert result.returncode == 0 diff --git a/test/containers/scenarios/driver/containers/molecule/default/converge.yml b/test/containers/scenarios/driver/containers/molecule/default/converge.yml new file mode 100644 index 00000000..46c15dd2 --- /dev/null +++ b/test/containers/scenarios/driver/containers/molecule/default/converge.yml @@ -0,0 +1,9 @@ +--- +- name: Converge + hosts: all + gather_facts: false + become: true + tasks: + - name: Display bogus message + ansible.builtin.debug: + msg: seems ok diff --git a/test/containers/scenarios/driver/containers/molecule/default/molecule.yml b/test/containers/scenarios/driver/containers/molecule/default/molecule.yml new file mode 100644 index 00000000..c6fe9c3c --- /dev/null +++ b/test/containers/scenarios/driver/containers/molecule/default/molecule.yml @@ -0,0 +1,7 @@ +--- +driver: + name: containers +platforms: + - name: instance +provisioner: + name: ansible diff --git a/test/containers/test_driver.py b/test/containers/test_driver.py new file mode 100644 index 00000000..96f28a6e --- /dev/null +++ b/test/containers/test_driver.py @@ -0,0 +1,7 @@ +"""Unit Tests.""" +from molecule import api + + +def test_driver_is_detected(): + """Check that driver is recognized.""" + assert "containers" in [str(d) for d in api.drivers()] diff --git a/tox.ini b/tox.ini index 8b84af57..de8d2d69 100644 --- a/tox.ini +++ b/tox.ini @@ -50,7 +50,7 @@ passenv = CI CURL_CA_BUNDLE DOCKER_* - PYTEST_OPTIONS + PYTEST_* REQUESTS_CA_BUNDLE SSH_AUTH_SOCK SSL_CERT_FILE