diff --git a/test/python/docker/compat/constant.py b/test/python/docker/compat/constant.py index 2a0046daf6..f6b9c9a35d 100644 --- a/test/python/docker/compat/constant.py +++ b/test/python/docker/compat/constant.py @@ -6,3 +6,4 @@ ALPINE_SHORTNAME = "alpine" ALPINE_TARBALL = "alpine.tar" BB = "quay.io/libpod/busybox:latest" NGINX = "quay.io/libpod/alpine_nginx:latest" +DOCKER_API_COMPATIBILITY_VERSION = "1.44" diff --git a/test/python/docker/compat/test_containers.py b/test/python/docker/compat/test_containers.py index 0595b29123..020c93abe1 100644 --- a/test/python/docker/compat/test_containers.py +++ b/test/python/docker/compat/test_containers.py @@ -2,19 +2,26 @@ Integration tests for exercising docker-py against Podman Service. """ import io +import json import tarfile import threading import time from typing import IO, List, Optional +import requests +import yaml 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 jsonschema.exceptions import best_match, ValidationError # pylint: disable=no-name-in-module,import-error,wrong-import-order from test.python.docker.compat import common, constant +from openapi_schema_validator import OAS31Validator + +from test.python.docker.compat.constant import DOCKER_API_COMPATIBILITY_VERSION # pylint: disable=missing-function-docstring @@ -302,3 +309,33 @@ class TestContainers(common.DockerTestCase): finally: ctr.stop() ctr.remove(force=True) + + def test_container_inspect_compatibility(self): + """Test conatainer inspect result compatibility with DOCKER_API""" + ctr = self.docker.containers.create(image="alpine", detach=True) + try: + spec = yaml.load( + requests.get(f"https://docs.docker.com/reference/engine/v{DOCKER_API_COMPATIBILITY_VERSION}.yaml").text, + Loader=yaml.SafeLoader) + + ctr_inspect = json.loads(self.podman.run("inspect", ctr.id).stdout)[0] + schema = spec['paths']["/containers/{id}/json"]["get"]['responses'][200]['schema'] + schema["definitions"] = spec["definitions"] + + OAS31Validator.check_schema(schema) + validator = OAS31Validator(schema) + important_error = [] + for error in validator.iter_errors(ctr_inspect): + if isinstance(error, ValidationError): + # ignore None instead of object/array/string errors + if error.message.startswith("None is not of type"): + continue + # ignore Windows specific option error + if error.json_path == '$.HostConfig.Isolation': + continue + important_error.append(error) + if important_error: + raise best_match(important_error) + finally: + ctr.stop() + ctr.remove(force=True) diff --git a/test/python/requirements.txt b/test/python/requirements.txt index 5a19ac00b8..7a805c8786 100644 --- a/test/python/requirements.txt +++ b/test/python/requirements.txt @@ -4,3 +4,4 @@ requests~=2.31.0 setuptools~=69.1.0 python-dateutil~=2.8.1 PyYAML~=6.0.0 +openapi-schema-validator~=0.6.2