import json import pytest from image.docker.schema1 import DockerSchema1Manifest from image.docker.schema2.manifest import DockerSchema2Manifest from image.docker.schema2.list import (MalformedSchema2ManifestList, DockerSchema2ManifestList, DockerSchema2ManifestListBuilder) from image.docker.schema2.test.test_manifest import MANIFEST_BYTES as v22_bytes from image.docker.test.test_schema1 import MANIFEST_BYTES as v21_bytes @pytest.mark.parametrize('json_data', [ '', '{}', """ { "unknown": "key" } """, ]) def test_malformed_manifest_lists(json_data): with pytest.raises(MalformedSchema2ManifestList): DockerSchema2ManifestList(json_data) MANIFESTLIST_BYTES = json.dumps({ "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", "manifests": [ { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 946, "digest": "sha256:e6", "platform": { "architecture": "ppc64le", "os": "linux", } }, { "mediaType": "application/vnd.docker.distribution.manifest.v1+json", "size": 878, "digest": "sha256:5b", "platform": { "architecture": "amd64", "os": "linux", "features": [ "sse4" ] } } ] }) NO_AMD_MANIFESTLIST_BYTES = json.dumps({ "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", "manifests": [ { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 946, "digest": "sha256:e6", "platform": { "architecture": "ppc64le", "os": "linux", } }, ] }) def test_valid_manifestlist(): def _get_manifest(digest): if digest == 'sha256:e6': return v22_bytes else: return v21_bytes manifestlist = DockerSchema2ManifestList(MANIFESTLIST_BYTES) assert len(manifestlist.manifests(_get_manifest)) == 2 assert manifestlist.media_type == 'application/vnd.docker.distribution.manifest.list.v2+json' assert manifestlist.bytes == MANIFESTLIST_BYTES assert manifestlist.manifest_dict == json.loads(MANIFESTLIST_BYTES) assert set(manifestlist.blob_digests) == {'sha256:e6', 'sha256:5b'} for index, manifest in enumerate(manifestlist.manifests(_get_manifest)): if index == 0: assert isinstance(manifest.manifest_obj, DockerSchema2Manifest) assert manifest.manifest_obj.schema_version == 2 else: assert isinstance(manifest.manifest_obj, DockerSchema1Manifest) assert manifest.manifest_obj.schema_version == 1 compatible_manifest = manifestlist.get_v1_compatible_manifest('foo', 'bar', 'baz', _get_manifest) assert compatible_manifest.schema_version == 1 assert manifestlist.layers is None assert manifestlist.leaf_layer_v1_image_id is None assert manifestlist.legacy_image_ids is None def test_get_v1_compatible_manifest_no_matching_list(): def _get_manifest(digest): if digest == 'sha256:e6': return v22_bytes else: return v21_bytes manifestlist = DockerSchema2ManifestList(NO_AMD_MANIFESTLIST_BYTES) assert len(manifestlist.manifests(_get_manifest)) == 1 assert manifestlist.media_type == 'application/vnd.docker.distribution.manifest.list.v2+json' assert manifestlist.bytes == NO_AMD_MANIFESTLIST_BYTES compatible_manifest = manifestlist.get_v1_compatible_manifest('foo', 'bar', 'baz', _get_manifest) assert compatible_manifest is None def test_builder(): def _get_manifest(digest): if digest == 'sha256:e6': return v22_bytes else: return v21_bytes existing = DockerSchema2ManifestList(MANIFESTLIST_BYTES) builder = DockerSchema2ManifestListBuilder() for index, manifest in enumerate(existing.manifests(_get_manifest)): builder.add_manifest(manifest.manifest_obj, "amd64", "os") built = builder.build() assert len(built.manifests(_get_manifest)) == 2