1
0
mirror of https://github.com/quay/quay.git synced 2026-01-26 06:21:37 +03:00
Files
quay/data/model/oci/retriever.py
Kenny Lee Sin Cheong 4546163e83 registry: implements the OCI 1.1 referrers API (PROJQUAY-7280) (#2597)
* registry: implements the OCI 1.1 referrers API

Migrations:
- Adds a subject column for lookup
- Adds a subject_backfilled column to track status of the backfilling
of existing manifests
- Adds a manifest_json column making use of postgres' JSONB support,
for future use.

Manifestsubjectbackfillworker: Indexes existing manifests for possible
existing subject field.

* Deprecate IGNORE_UNKNOWN_MEDIATYPES

* Cleanup
2024-06-07 13:28:13 -04:00

73 lines
2.3 KiB
Python

import time
from data.database import Manifest
from data.model.oci.blob import get_repository_blob_by_digest
from data.model.storage import get_layer_path
from image.shared.interfaces import ContentRetriever
from util.bytes import Bytes
RETRY_COUNT = 5
RETRY_DELAY = 0.3 # seconds
class RepositoryContentRetriever(ContentRetriever):
"""
Implementation of the ContentRetriever interface for manifests that retrieves config blobs and
child manifests for the specified repository.
"""
def __init__(self, repository_id, storage):
self.repository_id = repository_id
self.storage = storage
@classmethod
def for_repository(cls, repository_id, storage):
return RepositoryContentRetriever(repository_id, storage)
def get_manifest_with_digest(self, digest):
query = (
Manifest.select()
.where(Manifest.repository == self.repository_id)
.where(Manifest.digest == digest)
)
try:
return query.get()
except Manifest.DoesNotExist:
return None
def get_manifest_bytes_with_digest(self, digest):
"""
Returns the bytes of the manifest with the given digest or None if none found.
"""
query = (
Manifest.select()
.where(Manifest.repository == self.repository_id)
.where(Manifest.digest == digest)
)
try:
return Bytes.for_string_or_unicode(query.get().manifest_bytes).as_encoded_str()
except Manifest.DoesNotExist:
return None
def get_blob_bytes_with_digest(self, digest):
"""
Returns the bytes of the blob with the given digest or None if none found.
"""
blob = get_repository_blob_by_digest(self.repository_id, digest)
if blob is None:
return None
assert blob.locations is not None
# NOTE: Some storage engines are eventually consistent, and so we add a small
# retry here for retrieving the blobs from storage, as they may just have been
# written as part of the push process.
for retry in range(0, RETRY_COUNT):
try:
return self.storage.get_content(blob.locations, get_layer_path(blob))
except IOError:
time.sleep(RETRY_DELAY)
return None