Skip parsing the manifest where applicable
Instead of always parsing (like we did previously), we now only parse the manifest if conversion is necessary. This should save significant CPU.
This commit is contained in:
parent
396ce21020
commit
7f068c3fc3
1 changed files with 24 additions and 30 deletions
|
@ -57,15 +57,9 @@ def fetch_manifest_by_tagname(namespace_name, repo_name, manifest_ref):
|
|||
# Something went wrong.
|
||||
raise ManifestInvalid()
|
||||
|
||||
try:
|
||||
parsed = manifest.get_parsed_manifest()
|
||||
except ManifestException:
|
||||
logger.exception('Got exception when trying to parse manifest `%s`', manifest_ref)
|
||||
raise ManifestInvalid()
|
||||
|
||||
supported = _rewrite_schema_if_necessary(namespace_name, repo_name, manifest_ref, manifest,
|
||||
parsed)
|
||||
if supported is None:
|
||||
manifest_bytes, manifest_digest, manifest_media_type = _rewrite_schema_if_necessary(
|
||||
namespace_name, repo_name, manifest_ref, manifest)
|
||||
if manifest_bytes is None:
|
||||
raise ManifestUnknown()
|
||||
|
||||
track_and_log('pull_repo', repository_ref, analytics_name='pull_repo_100x', analytics_sample=0.01,
|
||||
|
@ -73,11 +67,11 @@ def fetch_manifest_by_tagname(namespace_name, repo_name, manifest_ref):
|
|||
metric_queue.repository_pull.Inc(labelvalues=[namespace_name, repo_name, 'v2', True])
|
||||
|
||||
return Response(
|
||||
supported.bytes.as_unicode(),
|
||||
manifest_bytes.as_unicode(),
|
||||
status=200,
|
||||
headers={
|
||||
'Content-Type': '%s; charset=utf-8' % supported.media_type,
|
||||
'Docker-Content-Digest': supported.digest,
|
||||
'Content-Type': '%s; charset=utf-8' % manifest_media_type,
|
||||
'Docker-Content-Digest': manifest_digest,
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -96,43 +90,43 @@ def fetch_manifest_by_digest(namespace_name, repo_name, manifest_ref):
|
|||
if manifest is None:
|
||||
raise ManifestUnknown()
|
||||
|
||||
try:
|
||||
parsed = manifest.get_parsed_manifest()
|
||||
except ManifestException:
|
||||
logger.exception('Got exception when trying to parse manifest `%s`', manifest_ref)
|
||||
raise ManifestInvalid()
|
||||
|
||||
supported = _rewrite_schema_if_necessary(namespace_name, repo_name, '$digest', manifest,
|
||||
parsed)
|
||||
if supported is None:
|
||||
manifest_bytes, manifest_digest, manifest_media_type = _rewrite_schema_if_necessary(
|
||||
namespace_name, repo_name, '$digest', manifest)
|
||||
if manifest_digest is None:
|
||||
raise ManifestUnknown()
|
||||
|
||||
track_and_log('pull_repo', repository_ref, manifest_digest=manifest_ref)
|
||||
metric_queue.repository_pull.Inc(labelvalues=[namespace_name, repo_name, 'v2', True])
|
||||
|
||||
return Response(supported.bytes.as_unicode(), status=200, headers={
|
||||
'Content-Type': '%s; charset=utf-8' % supported.media_type,
|
||||
'Docker-Content-Digest': supported.digest,
|
||||
return Response(manifest_bytes.as_unicode(), status=200, headers={
|
||||
'Content-Type': '%s; charset=utf-8' % manifest_media_type,
|
||||
'Docker-Content-Digest': manifest_digest,
|
||||
})
|
||||
|
||||
|
||||
def _rewrite_schema_if_necessary(namespace_name, repo_name, tag_name, manifest, parsed):
|
||||
def _rewrite_schema_if_necessary(namespace_name, repo_name, tag_name, manifest):
|
||||
# As per the Docker protocol, if the manifest is not schema version 1 and the manifest's
|
||||
# media type is not in the Accept header, we return a schema 1 version of the manifest for
|
||||
# the amd64+linux platform, if any, or None if none.
|
||||
# See: https://docs.docker.com/registry/spec/manifest-v2-2
|
||||
mimetypes = [mimetype for mimetype, _ in request.accept_mimetypes]
|
||||
if parsed.media_type in mimetypes:
|
||||
return parsed
|
||||
if manifest.media_type in mimetypes:
|
||||
return manifest.internal_manifest_bytes, manifest.digest, manifest.media_type
|
||||
|
||||
logger.debug('Manifest `%s` not compatible against %s; checking for conversion', manifest.digest,
|
||||
request.accept_mimetypes)
|
||||
converted = registry_model.convert_manifest(manifest, namespace_name, repo_name, tag_name,
|
||||
mimetypes, storage)
|
||||
if converted is not None:
|
||||
return converted
|
||||
return converted.bytes, converted.digest, converted.media_type
|
||||
|
||||
# For back-compat, we always default to schema 1 if the manifest could not be converted.
|
||||
return registry_model.get_schema1_parsed_manifest(manifest, namespace_name, repo_name, tag_name,
|
||||
storage)
|
||||
schema1 = registry_model.get_schema1_parsed_manifest(manifest, namespace_name, repo_name,
|
||||
tag_name, storage)
|
||||
if schema1 is None:
|
||||
return None, None, None
|
||||
|
||||
return schema1.bytes, schema1.digest, schema1.media_type
|
||||
|
||||
|
||||
def _reject_manifest2_schema2(func):
|
||||
|
|
Reference in a new issue