diff options
Diffstat (limited to 'test/python')
| -rw-r--r-- | test/python/docker/__init__.py | 30 | ||||
| -rw-r--r-- | test/python/docker/compat/common.py | 77 | ||||
| -rw-r--r-- | test/python/docker/compat/constant.py | 4 | ||||
| -rw-r--r-- | test/python/docker/compat/test_containers.py | 232 | ||||
| -rw-r--r-- | test/python/docker/compat/test_images.py | 131 | ||||
| -rw-r--r-- | test/python/docker/compat/test_system.py | 75 | ||||
| -rw-r--r-- | test/python/docker/conftest.py | 8 | 
7 files changed, 259 insertions, 298 deletions
diff --git a/test/python/docker/__init__.py b/test/python/docker/__init__.py index 816667b82..d46f465f7 100644 --- a/test/python/docker/__init__.py +++ b/test/python/docker/__init__.py @@ -1,4 +1,6 @@ -import configparser +""" +Helpers for integration tests using DockerClient +"""  import json  import os  import pathlib @@ -11,7 +13,7 @@ from docker import DockerClient  from .compat import constant -class Podman(object): +class PodmanAPI:      """      Instances hold the configuration and setup for running podman commands      """ @@ -53,17 +55,13 @@ location = "mirror.localhost:5000"  """ -        with open(os.environ["CONTAINERS_REGISTRIES_CONF"], "w") as w: -            w.write(conf) +        with open(os.environ["CONTAINERS_REGISTRIES_CONF"], "w") as file: +            file.write(conf) -        os.environ["CNI_CONFIG_PATH"] = os.path.join( -            self.anchor_directory, "cni", "net.d" -        ) +        os.environ["CNI_CONFIG_PATH"] = os.path.join(self.anchor_directory, "cni", "net.d")          os.makedirs(os.environ["CNI_CONFIG_PATH"], exist_ok=True)          self.cmd.append("--network-config-dir=" + os.environ["CNI_CONFIG_PATH"]) -        cni_cfg = os.path.join( -            os.environ["CNI_CONFIG_PATH"], "87-podman-bridge.conflist" -        ) +        cni_cfg = os.path.join(os.environ["CNI_CONFIG_PATH"], "87-podman-bridge.conflist")          # json decoded and encoded to ensure legal json          buf = json.loads(              """ @@ -93,8 +91,8 @@ location = "mirror.localhost:5000"              }              """          ) -        with open(cni_cfg, "w") as w: -            json.dump(buf, w) +        with open(cni_cfg, "w") as file: +            json.dump(buf, file)      def open(self, command, *args, **kwargs):          """Podman initialized instance to run a given command @@ -111,6 +109,7 @@ location = "mirror.localhost:5000"          shell = kwargs.get("shell", False) +        # pylint: disable=consider-using-with          return subprocess.Popen(              cmd,              shell=shell, @@ -144,9 +143,11 @@ location = "mirror.localhost:5000"          )      def tear_down(self): +        """Delete test environment."""          shutil.rmtree(self.anchor_directory, ignore_errors=True)      def restore_image_from_cache(self, client: DockerClient): +        """Populate images from cache."""          path = os.path.join(self.image_cache, constant.ALPINE_TARBALL)          if not os.path.exists(path):              img = client.images.pull(constant.ALPINE) @@ -157,5 +158,6 @@ location = "mirror.localhost:5000"              self.run("load", "-i", path, check=True)      def flush_image_cache(self): -        for f in pathlib.Path(self.image_cache).glob("*.tar"): -            f.unlink(f) +        """Delete image cache.""" +        for file in pathlib.Path(self.image_cache).glob("*.tar"): +            file.unlink(missing_ok=True) diff --git a/test/python/docker/compat/common.py b/test/python/docker/compat/common.py index bdc67c287..218ac9872 100644 --- a/test/python/docker/compat/common.py +++ b/test/python/docker/compat/common.py @@ -1,23 +1,92 @@ +""" +Fixtures and Helpers for unittests. +""" +import subprocess +import sys +import time +import unittest + +# pylint: disable=no-name-in-module,import-error,wrong-import-order  from docker import DockerClient +from test.python.docker import PodmanAPI  from test.python.docker.compat import constant  def run_top_container(client: DockerClient): -    c = client.containers.create( -        constant.ALPINE, command="top", detach=True, tty=True, name="top" +    """Run top command in a alpine container.""" +    ctnr = client.containers.create( +        constant.ALPINE, +        command="top", +        detach=True, +        tty=True, +        name="top",      ) -    c.start() -    return c.id +    ctnr.start() +    return ctnr.id  def remove_all_containers(client: DockerClient): +    """Delete all containers from the Podman service."""      for ctnr in client.containers.list(all=True):          ctnr.remove(force=True)  def remove_all_images(client: DockerClient): +    """Delete all images from the Podman service."""      for img in client.images.list():          # FIXME should DELETE /images accept the sha256: prefix?          id_ = img.id.removeprefix("sha256:")          client.images.remove(id_, force=True) + + +class DockerTestCase(unittest.TestCase): +    """Specialized TestCase class for testing against Podman service.""" + +    podman: PodmanAPI = None  # initialized podman configuration for tests +    service: subprocess.Popen = None  # podman service instance + +    top_container_id: str = None +    docker: DockerClient = None + +    @classmethod +    def setUpClass(cls) -> None: +        super().setUpClass() + +        cls.podman = PodmanAPI() +        super().addClassCleanup(cls.podman.tear_down) + +        cls.service = cls.podman.open("system", "service", "tcp:127.0.0.1:8080", "--time=0") +        # give the service some time to be ready... +        time.sleep(2) + +        return_code = cls.service.poll() +        if return_code is not None: +            raise subprocess.CalledProcessError(return_code, "podman system service") + +    @classmethod +    def tearDownClass(cls) -> None: +        cls.service.terminate() +        stdout, stderr = cls.service.communicate(timeout=0.5) +        if stdout: +            sys.stdout.write("\ndocker-py -- Service Stdout:\n" + stdout.decode("utf-8")) +        if stderr: +            sys.stderr.write("\ndocker-py -- Service Stderr:\n" + stderr.decode("utf-8")) + +        return super().tearDownClass() + +    def setUp(self) -> None: +        super().setUp() + +        self.docker = DockerClient(base_url="tcp://127.0.0.1:8080", timeout=15) +        self.addCleanup(self.docker.close) + +        self.podman.restore_image_from_cache(self.docker) +        self.top_container_id = run_top_container(self.docker) +        self.assertIsNotNone(self.top_container_id, "Failed to create 'top' container") + +    def tearDown(self) -> None: +        remove_all_containers(self.docker) +        remove_all_images(self.docker) + +        super().tearDown() diff --git a/test/python/docker/compat/constant.py b/test/python/docker/compat/constant.py index 892293c97..2a0046daf 100644 --- a/test/python/docker/compat/constant.py +++ b/test/python/docker/compat/constant.py @@ -1,6 +1,8 @@ +""" +Constants to use in writing unittests. +"""  ALPINE = "quay.io/libpod/alpine:latest"  ALPINE_SHORTNAME = "alpine"  ALPINE_TARBALL = "alpine.tar"  BB = "quay.io/libpod/busybox:latest"  NGINX = "quay.io/libpod/alpine_nginx:latest" -infra = "k8s.gcr.io/pause:3.2" diff --git a/test/python/docker/compat/test_containers.py b/test/python/docker/compat/test_containers.py index d14c09fc1..c0b6c9abe 100644 --- a/test/python/docker/compat/test_containers.py +++ b/test/python/docker/compat/test_containers.py @@ -1,111 +1,56 @@ +""" +Integration tests for exercising docker-py against Podman Service. +"""  import io -import subprocess -import sys -import time -import unittest -from typing import IO, Optional, List +import tarfile +from typing import IO, List, Optional -from docker import DockerClient, errors +from docker import errors  from docker.models.containers import Container  from docker.models.images import Image  from docker.models.volumes import Volume  from docker.types import Mount -from test.python.docker import Podman +# pylint: disable=no-name-in-module,import-error,wrong-import-order  from test.python.docker.compat import common, constant -import tarfile - - -class TestContainers(unittest.TestCase): -    podman = None  # initialized podman configuration for tests -    service = None  # podman service instance -    topContainerId = "" - -    def setUp(self): -        super().setUp() -        self.client = DockerClient(base_url="tcp://127.0.0.1:8080", timeout=15) -        TestContainers.podman.restore_image_from_cache(self.client) -        TestContainers.topContainerId = common.run_top_container(self.client) -        self.assertIsNotNone(TestContainers.topContainerId) - -    def tearDown(self): -        common.remove_all_containers(self.client) -        common.remove_all_images(self.client) -        self.client.close() -        return super().tearDown() - -    @classmethod -    def setUpClass(cls): -        super().setUpClass() -        TestContainers.podman = Podman() -        TestContainers.service = TestContainers.podman.open( -            "system", "service", "tcp:127.0.0.1:8080", "--time=0" -        ) -        # give the service some time to be ready... -        time.sleep(2) - -        rc = TestContainers.service.poll() -        if rc is not None: -            raise subprocess.CalledProcessError(rc, "podman system service") -    @classmethod -    def tearDownClass(cls): -        TestContainers.service.terminate() -        stdout, stderr = TestContainers.service.communicate(timeout=0.5) -        if stdout: -            sys.stdout.write("\nContainers Service Stdout:\n" + stdout.decode("utf-8")) -        if stderr: -            sys.stderr.write("\nContainers Service Stderr:\n" + stderr.decode("utf-8")) - -        TestContainers.podman.tear_down() -        return super().tearDownClass() +# pylint: disable=missing-function-docstring +class TestContainers(common.DockerTestCase): +    """TestCase for exercising containers."""      def test_create_container(self): -        # Run a container with detach mode -        self.client.containers.create(image="alpine", detach=True) -        self.assertEqual(len(self.client.containers.list(all=True)), 2) +        """Run a container with detach mode.""" +        self.docker.containers.create(image="alpine", detach=True) +        self.assertEqual(len(self.docker.containers.list(all=True)), 2)      def test_create_network(self): -        net = self.client.networks.create("testNetwork", driver="bridge") -        ctnr = self.client.containers.create(image="alpine", detach=True) - -        #  TODO fix when ready -        # This test will not work until all connect|disconnect -        # code is fixed. -        # net.connect(ctnr) - -        # nets = self.client.networks.list(greedy=True) -        # self.assertGreaterEqual(len(nets), 1) - -        # TODO fix endpoint to include containers -        # for n in nets: -        #     if n.id == "testNetwork": -        #         self.assertEqual(ctnr.id, n.containers) -        # self.assertTrue(False, "testNetwork not found") +        """Add network to a container.""" +        self.docker.networks.create("testNetwork", driver="bridge") +        self.docker.containers.create(image="alpine", detach=True)      def test_start_container(self):          # Podman docs says it should give a 304 but returns with no response          # # Start a already started container should return 304 -        # response = self.client.api.start(container=TestContainers.topContainerId) +        # response = self.docker.api.start(container=self.top_container_id)          # self.assertEqual(error.exception.response.status_code, 304)          # Create a new container and validate the count -        self.client.containers.create(image=constant.ALPINE, name="container2") -        containers = self.client.containers.list(all=True) +        self.docker.containers.create(image=constant.ALPINE, name="container2") +        containers = self.docker.containers.list(all=True)          self.assertEqual(len(containers), 2)      def test_start_container_with_random_port_bind(self): -        container = self.client.containers.create( +        container = self.docker.containers.create(              image=constant.ALPINE,              name="containerWithRandomBind",              ports={"1234/tcp": None},          ) -        containers = self.client.containers.list(all=True) +        containers = self.docker.containers.list(all=True)          self.assertTrue(container in containers)      def test_stop_container(self): -        top = self.client.containers.get(TestContainers.topContainerId) +        top = self.docker.containers.get(self.top_container_id)          self.assertEqual(top.status, "running")          # Stop a running container and validate the state @@ -114,7 +59,7 @@ class TestContainers(unittest.TestCase):          self.assertIn(top.status, ("stopped", "exited"))      def test_kill_container(self): -        top = self.client.containers.get(TestContainers.topContainerId) +        top = self.docker.containers.get(self.top_container_id)          self.assertEqual(top.status, "running")          # Kill a running container and validate the state @@ -124,7 +69,7 @@ class TestContainers(unittest.TestCase):      def test_restart_container(self):          # Validate the container state -        top = self.client.containers.get(TestContainers.topContainerId) +        top = self.docker.containers.get(self.top_container_id)          top.stop()          top.reload()          self.assertIn(top.status, ("stopped", "exited")) @@ -136,16 +81,16 @@ class TestContainers(unittest.TestCase):      def test_remove_container(self):          # Remove container by ID with force -        top = self.client.containers.get(TestContainers.topContainerId) +        top = self.docker.containers.get(self.top_container_id)          top.remove(force=True) -        self.assertEqual(len(self.client.containers.list()), 0) +        self.assertEqual(len(self.docker.containers.list()), 0)      def test_remove_container_without_force(self):          # Validate current container count -        self.assertEqual(len(self.client.containers.list()), 1) +        self.assertEqual(len(self.docker.containers.list()), 1)          # Remove running container should throw error -        top = self.client.containers.get(TestContainers.topContainerId) +        top = self.docker.containers.get(self.top_container_id)          with self.assertRaises(errors.APIError) as error:              top.remove()          self.assertEqual(error.exception.response.status_code, 500) @@ -153,11 +98,11 @@ class TestContainers(unittest.TestCase):          # Remove container by ID without force          top.stop()          top.remove() -        self.assertEqual(len(self.client.containers.list()), 0) +        self.assertEqual(len(self.docker.containers.list()), 0)      def test_pause_container(self):          # Validate the container state -        top = self.client.containers.get(TestContainers.topContainerId) +        top = self.docker.containers.get(self.top_container_id)          self.assertEqual(top.status, "running")          # Pause a running container and validate the state @@ -167,7 +112,7 @@ class TestContainers(unittest.TestCase):      def test_pause_stopped_container(self):          # Stop the container -        top = self.client.containers.get(TestContainers.topContainerId) +        top = self.docker.containers.get(self.top_container_id)          top.stop()          # Pause exited container should throw error @@ -176,7 +121,7 @@ class TestContainers(unittest.TestCase):          self.assertEqual(error.exception.response.status_code, 500)      def test_unpause_container(self): -        top = self.client.containers.get(TestContainers.topContainerId) +        top = self.docker.containers.get(self.top_container_id)          # Validate the container state          top.pause() @@ -190,21 +135,21 @@ class TestContainers(unittest.TestCase):      def test_list_container(self):          # Add container and validate the count -        self.client.containers.create(image="alpine", detach=True) -        containers = self.client.containers.list(all=True) +        self.docker.containers.create(image="alpine", detach=True) +        containers = self.docker.containers.list(all=True)          self.assertEqual(len(containers), 2)      def test_filters(self):          self.skipTest("TODO Endpoint does not yet support filters")          # List container with filter by id -        filters = {"id": TestContainers.topContainerId} -        ctnrs = self.client.containers.list(all=True, filters=filters) +        filters = {"id": self.top_container_id} +        ctnrs = self.docker.containers.list(all=True, filters=filters)          self.assertEqual(len(ctnrs), 1)          # List container with filter by name          filters = {"name": "top"} -        ctnrs = self.client.containers.list(all=True, filters=filters) +        ctnrs = self.docker.containers.list(all=True, filters=filters)          self.assertEqual(len(ctnrs), 1)      def test_copy_to_container(self): @@ -212,31 +157,33 @@ class TestContainers(unittest.TestCase):          vol: Optional[Volume] = None          try:              test_file_content = b"Hello World!" -            vol = self.client.volumes.create("test-volume") -            ctr = self.client.containers.create(image="alpine", -                                                detach=True, -                                                command="top", -                                                volumes=["test-volume:/test-volume-read-only:ro"]) +            vol = self.docker.volumes.create("test-volume") +            ctr = self.docker.containers.create( +                image="alpine", +                detach=True, +                command="top", +                volumes=["test-volume:/test-volume-read-only:ro"], +            )              ctr.start()              buff: IO[bytes] = io.BytesIO() -            with tarfile.open(fileobj=buff, mode="w:") as tf: -                ti: tarfile.TarInfo = tarfile.TarInfo() -                ti.uid = 1042 -                ti.gid = 1043 -                ti.name = "a.txt" -                ti.path = "a.txt" -                ti.mode = 0o644 -                ti.type = tarfile.REGTYPE -                ti.size = len(test_file_content) -                tf.addfile(ti, fileobj=io.BytesIO(test_file_content)) +            with tarfile.open(fileobj=buff, mode="w:") as file: +                info: tarfile.TarInfo = tarfile.TarInfo() +                info.uid = 1042 +                info.gid = 1043 +                info.name = "a.txt" +                info.path = "a.txt" +                info.mode = 0o644 +                info.type = tarfile.REGTYPE +                info.size = len(test_file_content) +                file.addfile(info, fileobj=io.BytesIO(test_file_content))              buff.seek(0)              ctr.put_archive("/tmp/", buff)              ret, out = ctr.exec_run(["stat", "-c", "%u:%g", "/tmp/a.txt"])              self.assertEqual(ret, 0) -            self.assertEqual(out.rstrip(), b'1042:1043', "UID/GID of copied file") +            self.assertEqual(out.rstrip(), b"1042:1043", "UID/GID of copied file")              ret, out = ctr.exec_run(["cat", "/tmp/a.txt"])              self.assertEqual(ret, 0) @@ -253,48 +200,61 @@ class TestContainers(unittest.TestCase):                  vol.remove(force=True)      def test_mount_preexisting_dir(self): -        dockerfile = (B'FROM quay.io/libpod/alpine:latest\n' -                      B'USER root\n' -                      B'RUN mkdir -p /workspace\n' -                      B'RUN chown 1042:1043 /workspace') +        dockerfile = ( +            b"FROM quay.io/libpod/alpine:latest\n" +            b"USER root\n" +            b"RUN mkdir -p /workspace\n" +            b"RUN chown 1042:1043 /workspace" +        )          img: Image -        img, out = self.client.images.build(fileobj=io.BytesIO(dockerfile)) -        ctr: Container = self.client.containers.create(image=img.id, detach=True, command="top", -                                                       volumes=["test_mount_preexisting_dir_vol:/workspace"]) +        img, out = self.docker.images.build(fileobj=io.BytesIO(dockerfile)) +        ctr: Container = self.docker.containers.create( +            image=img.id, +            detach=True, +            command="top", +            volumes=["test_mount_preexisting_dir_vol:/workspace"], +        )          ctr.start() -        ret, out = ctr.exec_run(["stat", "-c", "%u:%g", "/workspace"]) -        self.assertEqual(out.rstrip(), b'1042:1043', "UID/GID set in dockerfile") - +        _, out = ctr.exec_run(["stat", "-c", "%u:%g", "/workspace"]) +        self.assertEqual(out.rstrip(), b"1042:1043", "UID/GID set in dockerfile")      def test_non_existant_workdir(self): -        dockerfile = (B'FROM quay.io/libpod/alpine:latest\n' -                      B'USER root\n' -                      B'WORKDIR /workspace/scratch\n' -                      B'RUN touch test') +        dockerfile = ( +            b"FROM quay.io/libpod/alpine:latest\n" +            b"USER root\n" +            b"WORKDIR /workspace/scratch\n" +            b"RUN touch test" +        )          img: Image -        img, out = self.client.images.build(fileobj=io.BytesIO(dockerfile)) -        ctr: Container = self.client.containers.create(image=img.id, detach=True, command="top", -                                                       volumes=["test_non_existant_workdir:/workspace"]) +        img, _ = self.docker.images.build(fileobj=io.BytesIO(dockerfile)) +        ctr: Container = self.docker.containers.create( +            image=img.id, +            detach=True, +            command="top", +            volumes=["test_non_existant_workdir:/workspace"], +        )          ctr.start() -        ret, out = ctr.exec_run(["stat", "/workspace/scratch/test"]) +        ret, _ = ctr.exec_run(["stat", "/workspace/scratch/test"])          self.assertEqual(ret, 0, "Working directory created if it doesn't exist")      def test_mount_rw_by_default(self):          ctr: Optional[Container] = None          vol: Optional[Volume] = None +          try: -            vol = self.client.volumes.create("test-volume") -            ctr = self.client.containers.create(image="alpine", -                                                detach=True, -                                                command="top", -                                                mounts=[Mount(target="/vol-mnt", -                                                              source="test-volume", -                                                              type='volume', -                                                              read_only=False)]) -            ctr_inspect = self.client.api.inspect_container(ctr.id) +            vol = self.docker.volumes.create("test-volume") +            ctr = self.docker.containers.create( +                image="alpine", +                detach=True, +                command="top", +                mounts=[ +                    Mount(target="/vol-mnt", source="test-volume", type="volume", read_only=False) +                ], +            ) +            ctr_inspect = self.docker.api.inspect_container(ctr.id)              binds: List[str] = ctr_inspect["HostConfig"]["Binds"]              self.assertEqual(len(binds), 1) -            self.assertEqual(binds[0], 'test-volume:/vol-mnt:rw,rprivate,nosuid,nodev,rbind') +            self.assertEqual(binds[0], "test-volume:/vol-mnt:rw,rprivate,nosuid,nodev,rbind")          finally:              if ctr is not None:                  ctr.remove() diff --git a/test/python/docker/compat/test_images.py b/test/python/docker/compat/test_images.py index 05d0e3e12..ac9a8d671 100644 --- a/test/python/docker/compat/test_images.py +++ b/test/python/docker/compat/test_images.py @@ -1,116 +1,73 @@ -import collections +""" +Integration tests for exercising docker-py against Podman Service. +"""  import io  import os -import subprocess -import sys -import time  import unittest -from docker import DockerClient, errors -from docker.errors import APIError +from docker import errors -from test.python.docker import Podman +# pylint: disable=no-name-in-module,import-error,wrong-import-order  from test.python.docker.compat import common, constant -class TestImages(unittest.TestCase): -    podman = None  # initialized podman configuration for tests -    service = None  # podman service instance - -    def setUp(self): -        super().setUp() -        self.client = DockerClient(base_url="tcp://127.0.0.1:8080", timeout=15) - -        TestImages.podman.restore_image_from_cache(self.client) - -    def tearDown(self): -        common.remove_all_images(self.client) -        self.client.close() -        return super().tearDown() - -    @classmethod -    def setUpClass(cls): -        super().setUpClass() -        TestImages.podman = Podman() -        TestImages.service = TestImages.podman.open( -            "system", "service", "tcp:127.0.0.1:8080", "--time=0" -        ) -        # give the service some time to be ready... -        time.sleep(2) - -        returncode = TestImages.service.poll() -        if returncode is not None: -            raise subprocess.CalledProcessError(returncode, "podman system service") - -    @classmethod -    def tearDownClass(cls): -        TestImages.service.terminate() -        stdout, stderr = TestImages.service.communicate(timeout=0.5) -        if stdout: -            sys.stdout.write("\nImages Service Stdout:\n" + stdout.decode("utf-8")) -        if stderr: -            sys.stderr.write("\nImAges Service Stderr:\n" + stderr.decode("utf-8")) - -        TestImages.podman.tear_down() -        return super().tearDownClass() +class TestImages(common.DockerTestCase): +    """TestCase for exercising images."""      def test_tag_valid_image(self):          """Validates if the image is tagged successfully""" -        alpine = self.client.images.get(constant.ALPINE) +        alpine = self.docker.images.get(constant.ALPINE)          self.assertTrue(alpine.tag("demo", constant.ALPINE_SHORTNAME)) -        alpine = self.client.images.get(constant.ALPINE) -        for t in alpine.tags: -            self.assertIn("alpine", t) +        alpine = self.docker.images.get(constant.ALPINE) +        for tag in alpine.tags: +            self.assertIn("alpine", tag) -    # @unittest.skip("doesn't work now")      def test_retag_valid_image(self): -        """Validates if name updates when the image is retagged""" -        alpine = self.client.images.get(constant.ALPINE) +        """Validates if name updates when the image is re-tagged.""" +        alpine = self.docker.images.get(constant.ALPINE)          self.assertTrue(alpine.tag("demo", "rename")) -        alpine = self.client.images.get(constant.ALPINE) +        alpine = self.docker.images.get(constant.ALPINE)          self.assertNotIn("demo:test", alpine.tags)      def test_list_images(self):          """List images""" -        self.assertEqual(len(self.client.images.list()), 1) +        self.assertEqual(len(self.docker.images.list()), 1)          # Add more images -        self.client.images.pull(constant.BB) -        self.assertEqual(len(self.client.images.list()), 2) -        self.assertEqual(len(self.client.images.list(all=True)), 2) +        self.docker.images.pull(constant.BB) +        self.assertEqual(len(self.docker.images.list()), 2) +        self.assertEqual(len(self.docker.images.list(all=True)), 2)          # List images with filter -        self.assertEqual(len(self.client.images.list(filters={"reference": "alpine"})), 1) +        self.assertEqual(len(self.docker.images.list(filters={"reference": "alpine"})), 1)      def test_search_image(self):          """Search for image""" -        for r in self.client.images.search("alpine"): +        for registry in self.docker.images.search("alpine"):              # registry matches if string is in either one -            self.assertIn("alpine", r["Name"]+" "+r["Description"].lower()) +            self.assertIn("alpine", registry["Name"] + " " + registry["Description"].lower())      def test_search_bogus_image(self):          """Search for bogus image should throw exception""" -        try: -            r = self.client.images.search("bogus/bogus") -        except: -            return -        self.assertTrue(len(r) == 0) +        with self.assertRaises(errors.APIError): +            self.docker.images.search("bogus/bogus")      def test_remove_image(self):          """Remove image"""          # Check for error with wrong image name          with self.assertRaises(errors.NotFound): -            self.client.images.remove("dummy") -        self.assertEqual(len(self.client.images.list()), 1) +            self.docker.images.remove("dummy") -        self.client.images.remove(constant.ALPINE) -        self.assertEqual(len(self.client.images.list()), 0) +        common.remove_all_containers(self.docker) +        self.assertEqual(len(self.docker.images.list()), 1) +        self.docker.images.remove(constant.ALPINE) +        self.assertEqual(len(self.docker.images.list()), 0)      def test_image_history(self):          """Image history""" -        img = self.client.images.get(constant.ALPINE) +        img = self.docker.images.get(constant.ALPINE)          history = img.history()          image_id = img.id[7:] if img.id.startswith("sha256:") else img.id @@ -122,47 +79,49 @@ class TestImages(unittest.TestCase):      def test_get_image_exists_not(self):          """Negative test for get image"""          with self.assertRaises(errors.NotFound): -            response = self.client.images.get("image_does_not_exists") -            collections.deque(response) +            self.docker.images.get("image_does_not_exists")      def test_save_image(self):          """Export Image""" -        image = self.client.images.pull(constant.BB) +        image = self.docker.images.pull(constant.BB)          file = os.path.join(TestImages.podman.image_cache, "busybox.tar")          with open(file, mode="wb") as tarball:              for frame in image.save(named=True):                  tarball.write(frame) -        sz = os.path.getsize(file) -        self.assertGreater(sz, 0) +        self.assertGreater(os.path.getsize(file), 0)      def test_load_image(self):          """Import|Load Image""" -        self.assertEqual(len(self.client.images.list()), 1) +        self.assertEqual(len(self.docker.images.list()), 1) -        image = self.client.images.pull(constant.BB) +        image = self.docker.images.pull(constant.BB)          file = os.path.join(TestImages.podman.image_cache, "busybox.tar")          with open(file, mode="wb") as tarball:              for frame in image.save():                  tarball.write(frame)          with open(file, mode="rb") as saved: -            _ = self.client.images.load(saved) +            self.docker.images.load(saved) -        self.assertEqual(len(self.client.images.list()), 2) +        self.assertEqual(len(self.docker.images.list()), 2)      def test_load_corrupt_image(self):          """Import|Load Image failure"""          tarball = io.BytesIO("This is a corrupt tarball".encode("utf-8")) -        with self.assertRaises(APIError): -            self.client.images.load(tarball) +        with self.assertRaises(errors.APIError): +            self.docker.images.load(tarball)      def test_build_image(self): +        """Build Image with custom labels."""          labels = {"apple": "red", "grape": "green"} -        _ = self.client.images.build( -            path="test/python/docker/build_labels", labels=labels, tag="labels", isolation="default" +        self.docker.images.build( +            path="test/python/docker/build_labels", +            labels=labels, +            tag="labels", +            isolation="default",          ) -        image = self.client.images.get("labels") +        image = self.docker.images.get("labels")          self.assertEqual(image.labels["apple"], labels["apple"])          self.assertEqual(image.labels["grape"], labels["grape"]) diff --git a/test/python/docker/compat/test_system.py b/test/python/docker/compat/test_system.py index a928de0ee..f6092996b 100644 --- a/test/python/docker/compat/test_system.py +++ b/test/python/docker/compat/test_system.py @@ -1,71 +1,32 @@ -import subprocess -import sys -import time -import unittest +""" +Integration tests for exercising docker-py against Podman Service. +""" -from docker import DockerClient - -from test.python.docker import Podman, constant +# pylint: disable=no-name-in-module,import-error,wrong-import-order +from test.python.docker import constant  from test.python.docker.compat import common -class TestSystem(unittest.TestCase): -    podman = None  # initialized podman configuration for tests -    service = None  # podman service instance -    topContainerId = "" - -    def setUp(self): -        super().setUp() -        self.client = DockerClient(base_url="tcp://127.0.0.1:8080", timeout=15) - -        TestSystem.podman.restore_image_from_cache(self.client) -        TestSystem.topContainerId = common.run_top_container(self.client) - -    def tearDown(self): -        common.remove_all_containers(self.client) -        common.remove_all_images(self.client) -        self.client.close() -        return super().tearDown() - -    @classmethod -    def setUpClass(cls): -        super().setUpClass() -        TestSystem.podman = Podman() -        TestSystem.service = TestSystem.podman.open( -            "system", "service", "tcp:127.0.0.1:8080", "--time=0" -        ) -        # give the service some time to be ready... -        time.sleep(2) - -        returncode = TestSystem.service.poll() -        if returncode is not None: -            raise subprocess.CalledProcessError(returncode, "podman system service") - -    @classmethod -    def tearDownClass(cls): -        TestSystem.service.terminate() -        stdout, stderr = TestSystem.service.communicate(timeout=0.5) -        if stdout: -            sys.stdout.write("\nImages Service Stdout:\n" + stdout.decode("utf-8")) -        if stderr: -            sys.stderr.write("\nImAges Service Stderr:\n" + stderr.decode("utf-8")) +# pylint: disable=missing-function-docstring +class TestSystem(common.DockerTestCase): +    """TestCase for exercising Podman system services.""" -        TestSystem.podman.tear_down() -        return super().tearDownClass() - -    def test_Info(self): -        info = self.client.info() +    def test_info(self): +        info = self.docker.info()          self.assertIsNotNone(info)          self.assertEqual(info["RegistryConfig"]["IndexConfigs"]["localhost:5000"]["Secure"], False) -        self.assertEqual(info["RegistryConfig"]["IndexConfigs"]["localhost:5000"]["Mirrors"], ["mirror.localhost:5000"]) +        self.assertEqual( +            info["RegistryConfig"]["IndexConfigs"]["localhost:5000"]["Mirrors"], +            ["mirror.localhost:5000"], +        )      def test_info_container_details(self): -        info = self.client.info() +        info = self.docker.info()          self.assertEqual(info["Containers"], 1) -        self.client.containers.create(image=constant.ALPINE) -        info = self.client.info() +        self.docker.containers.create(image=constant.ALPINE) +        info = self.docker.info()          self.assertEqual(info["Containers"], 2)      def test_version(self): -        version = self.client.version() +        version = self.docker.version()          self.assertIsNotNone(version["Platform"]["Name"]) diff --git a/test/python/docker/conftest.py b/test/python/docker/conftest.py new file mode 100644 index 000000000..c63780fa8 --- /dev/null +++ b/test/python/docker/conftest.py @@ -0,0 +1,8 @@ +""" +Configure pytest +""" + + +def pytest_report_header(config): +    """Add header to report.""" +    return "python client -- DockerClient"  | 
