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.
|
# Something went wrong.
|
||||||
raise ManifestInvalid()
|
raise ManifestInvalid()
|
||||||
|
|
||||||
try:
|
manifest_bytes, manifest_digest, manifest_media_type = _rewrite_schema_if_necessary(
|
||||||
parsed = manifest.get_parsed_manifest()
|
namespace_name, repo_name, manifest_ref, manifest)
|
||||||
except ManifestException:
|
if manifest_bytes is None:
|
||||||
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:
|
|
||||||
raise ManifestUnknown()
|
raise ManifestUnknown()
|
||||||
|
|
||||||
track_and_log('pull_repo', repository_ref, analytics_name='pull_repo_100x', analytics_sample=0.01,
|
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])
|
metric_queue.repository_pull.Inc(labelvalues=[namespace_name, repo_name, 'v2', True])
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
supported.bytes.as_unicode(),
|
manifest_bytes.as_unicode(),
|
||||||
status=200,
|
status=200,
|
||||||
headers={
|
headers={
|
||||||
'Content-Type': '%s; charset=utf-8' % supported.media_type,
|
'Content-Type': '%s; charset=utf-8' % manifest_media_type,
|
||||||
'Docker-Content-Digest': supported.digest,
|
'Docker-Content-Digest': manifest_digest,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -96,43 +90,43 @@ def fetch_manifest_by_digest(namespace_name, repo_name, manifest_ref):
|
||||||
if manifest is None:
|
if manifest is None:
|
||||||
raise ManifestUnknown()
|
raise ManifestUnknown()
|
||||||
|
|
||||||
try:
|
manifest_bytes, manifest_digest, manifest_media_type = _rewrite_schema_if_necessary(
|
||||||
parsed = manifest.get_parsed_manifest()
|
namespace_name, repo_name, '$digest', manifest)
|
||||||
except ManifestException:
|
if manifest_digest is None:
|
||||||
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:
|
|
||||||
raise ManifestUnknown()
|
raise ManifestUnknown()
|
||||||
|
|
||||||
track_and_log('pull_repo', repository_ref, manifest_digest=manifest_ref)
|
track_and_log('pull_repo', repository_ref, manifest_digest=manifest_ref)
|
||||||
metric_queue.repository_pull.Inc(labelvalues=[namespace_name, repo_name, 'v2', True])
|
metric_queue.repository_pull.Inc(labelvalues=[namespace_name, repo_name, 'v2', True])
|
||||||
|
|
||||||
return Response(supported.bytes.as_unicode(), status=200, headers={
|
return Response(manifest_bytes.as_unicode(), status=200, headers={
|
||||||
'Content-Type': '%s; charset=utf-8' % supported.media_type,
|
'Content-Type': '%s; charset=utf-8' % manifest_media_type,
|
||||||
'Docker-Content-Digest': supported.digest,
|
'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
|
# 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
|
# 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.
|
# the amd64+linux platform, if any, or None if none.
|
||||||
# See: https://docs.docker.com/registry/spec/manifest-v2-2
|
# See: https://docs.docker.com/registry/spec/manifest-v2-2
|
||||||
mimetypes = [mimetype for mimetype, _ in request.accept_mimetypes]
|
mimetypes = [mimetype for mimetype, _ in request.accept_mimetypes]
|
||||||
if parsed.media_type in mimetypes:
|
if manifest.media_type in mimetypes:
|
||||||
return parsed
|
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,
|
converted = registry_model.convert_manifest(manifest, namespace_name, repo_name, tag_name,
|
||||||
mimetypes, storage)
|
mimetypes, storage)
|
||||||
if converted is not None:
|
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.
|
# 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,
|
schema1 = registry_model.get_schema1_parsed_manifest(manifest, namespace_name, repo_name,
|
||||||
storage)
|
tag_name, storage)
|
||||||
|
if schema1 is None:
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
return schema1.bytes, schema1.digest, schema1.media_type
|
||||||
|
|
||||||
|
|
||||||
def _reject_manifest2_schema2(func):
|
def _reject_manifest2_schema2(func):
|
||||||
|
|
Reference in a new issue