Add method for retrieving a V1-compatible manifest for any manifest or manifest list

This is used to serve older clients that don't support the V2 schema format
This commit is contained in:
Joseph Schorr 2018-11-13 10:40:57 +02:00
parent d77d383e46
commit 1b3daac3c3
7 changed files with 119 additions and 7 deletions

View file

@ -1,9 +1,11 @@
import logging
import json
from cachetools import lru_cache
from jsonschema import validate as validate_schema, ValidationError
from digest import digest_tools
from image.docker import ManifestException
from image.docker.interfaces import ManifestInterface
from image.docker.schema1 import DOCKER_SCHEMA1_MANIFEST_CONTENT_TYPE
from image.docker.schema1 import DockerSchema1Manifest
@ -11,6 +13,9 @@ from image.docker.schema2 import (DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE,
DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE)
from image.docker.schema2.manifest import DockerSchema2Manifest
logger = logging.getLogger(__name__)
# Keys.
DOCKER_SCHEMA2_MANIFESTLIST_VERSION_KEY = 'schemaVersion'
DOCKER_SCHEMA2_MANIFESTLIST_MEDIATYPE_KEY = 'mediaType'
@ -228,16 +233,28 @@ class DockerSchema2ManifestList(ManifestInterface):
def get_manifest_labels(self, lookup_config_fn):
return None
def get_v1_compatible_manifest(self, lookup_manifest_fn):
def get_v1_compatible_manifest(self, namespace_name, repo_name, tag_name, lookup_fn):
""" Returns the manifest that is compatible with V1, by virtue of being `amd64` and `linux`.
If none, returns None.
"""
for manifest in self.manifests(lookup_manifest_fn):
platform = manifest._manifest_data[DOCKER_SCHEMA2_MANIFESTLIST_PLATFORM_KEY]
for manifest_ref in self.manifests(lookup_fn):
platform = manifest_ref._manifest_data[DOCKER_SCHEMA2_MANIFESTLIST_PLATFORM_KEY]
architecture = platform[DOCKER_SCHEMA2_MANIFESTLIST_ARCHITECTURE_KEY]
os = platform[DOCKER_SCHEMA2_MANIFESTLIST_OS_KEY]
if architecture == 'amd64' and os == 'linux':
return manifest
if architecture != 'amd64' or os != 'linux':
continue
try:
manifest = manifest_ref.manifest_obj
except ManifestException:
logger.exception('Could not load child manifest')
return None
except IOError:
logger.exception('Could not load child manifest')
return None
return manifest.get_v1_compatible_manifest(namespace_name, repo_name, tag_name, lookup_fn)
return None