Fix manifest UI display for manifests with empty layers

Also fixes the command for schema 2 manifests
This commit is contained in:
Joseph Schorr 2018-12-10 17:10:54 -05:00
parent 4106f5ce51
commit 7fa60d5802
2 changed files with 22 additions and 4 deletions

View file

@ -12,6 +12,7 @@ from data.registry_model.datatype import FromDictionaryException
from data.registry_model.datatypes import (RepositoryReference, Blob, TorrentInfo, BlobUpload, from data.registry_model.datatypes import (RepositoryReference, Blob, TorrentInfo, BlobUpload,
LegacyImage, ManifestLayer, DerivedImage) LegacyImage, ManifestLayer, DerivedImage)
from image.docker.schema1 import ManifestException, DockerSchema1ManifestBuilder from image.docker.schema1 import ManifestException, DockerSchema1ManifestBuilder
from image.docker.schema2 import EMPTY_LAYER_BLOB_DIGEST
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -344,14 +345,21 @@ class SharedModel:
working towards the leaf, including the associated Blob and its placements (if specified). working towards the leaf, including the associated Blob and its placements (if specified).
Returns None if the manifest could not be parsed and validated. Returns None if the manifest could not be parsed and validated.
""" """
retriever = RepositoryContentRetriever(repo_id, storage)
requires_empty_blob = parsed.get_requires_empty_layer_blob(retriever)
storage_map = {} storage_map = {}
if parsed.local_blob_digests: blob_digests = list(parsed.local_blob_digests)
if requires_empty_blob:
blob_digests.append(EMPTY_LAYER_BLOB_DIGEST)
if blob_digests:
blob_query = model.storage.lookup_repo_storages_by_content_checksum(repo_id, blob_query = model.storage.lookup_repo_storages_by_content_checksum(repo_id,
parsed.local_blob_digests, blob_digests,
by_manifest=by_manifest) by_manifest=by_manifest)
storage_map = {blob.content_checksum: blob for blob in blob_query} storage_map = {blob.content_checksum: blob for blob in blob_query}
retriever = RepositoryContentRetriever(repo_id, storage)
layers = parsed.get_layers(retriever) layers = parsed.get_layers(retriever)
if layers is None: if layers is None:
logger.error('Could not load layers for manifest `%s`', parsed.digest) logger.error('Could not load layers for manifest `%s`', parsed.digest)

View file

@ -1,5 +1,6 @@
""" Manage the manifests of a repository. """ """ Manage the manifests of a repository. """
import json import json
import logging
from flask import request from flask import request
@ -20,6 +21,9 @@ BASE_MANIFEST_ROUTE = '/v1/repository/<apirepopath:repository>/manifest/<regex("
MANIFEST_DIGEST_ROUTE = BASE_MANIFEST_ROUTE.format(digest_tools.DIGEST_PATTERN) MANIFEST_DIGEST_ROUTE = BASE_MANIFEST_ROUTE.format(digest_tools.DIGEST_PATTERN)
ALLOWED_LABEL_MEDIA_TYPES = ['text/plain', 'application/json'] ALLOWED_LABEL_MEDIA_TYPES = ['text/plain', 'application/json']
logger = logging.getLogger(__name__)
def _label_dict(label): def _label_dict(label):
return { return {
'id': label.uuid, 'id': label.uuid,
@ -31,10 +35,12 @@ def _label_dict(label):
def _layer_dict(manifest_layer, index): def _layer_dict(manifest_layer, index):
# NOTE: The `command` in the layer is either a JSON string of an array (schema 1) or
# a single string (schema 2). The block below normalizes it to have the same format.
try: try:
command = json.loads(manifest_layer.command) command = json.loads(manifest_layer.command)
except (TypeError, ValueError): except (TypeError, ValueError):
command = [] command = [manifest_layer.command]
return { return {
'index': index, 'index': index,
@ -53,6 +59,10 @@ def _manifest_dict(manifest):
image = image_dict(manifest.legacy_image, with_history=True) image = image_dict(manifest.legacy_image, with_history=True)
layers = registry_model.list_manifest_layers(manifest, storage) layers = registry_model.list_manifest_layers(manifest, storage)
if layers is None and not manifest.is_manifest_list:
logger.debug('Missing layers for manifest `%s`', manifest.digest)
abort(404)
return { return {
'digest': manifest.digest, 'digest': manifest.digest,
'is_manifest_list': manifest.is_manifest_list, 'is_manifest_list': manifest.is_manifest_list,