2018-08-13 22:09:05 +00:00
|
|
|
from abc import ABCMeta, abstractmethod
|
|
|
|
from six import add_metaclass
|
|
|
|
|
|
|
|
@add_metaclass(ABCMeta)
|
|
|
|
class RegistryDataInterface(object):
|
|
|
|
""" Interface for code to work with the registry data model. The registry data model consists
|
|
|
|
of all tables that store registry-specific information, such as Manifests, Blobs, Images,
|
|
|
|
and Labels.
|
|
|
|
"""
|
2018-11-13 09:49:12 +00:00
|
|
|
@abstractmethod
|
|
|
|
def supports_schema2(self, namespace_name):
|
|
|
|
""" Returns whether the implementation of the data interface supports schema 2 format
|
|
|
|
manifests. """
|
2018-08-13 22:09:05 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def find_matching_tag(self, repository_ref, tag_names):
|
|
|
|
""" Finds an alive tag in the repository matching one of the given tag names and returns it
|
|
|
|
or None if none.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_most_recent_tag(self, repository_ref):
|
|
|
|
""" Returns the most recently pushed alive tag in the repository, if any. If none, returns
|
|
|
|
None.
|
|
|
|
"""
|
2018-08-17 20:45:27 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def lookup_repository(self, namespace_name, repo_name, kind_filter=None):
|
|
|
|
""" Looks up and returns a reference to the repository with the given namespace and name,
|
|
|
|
or None if none. """
|
|
|
|
|
|
|
|
@abstractmethod
|
2018-08-28 17:02:26 +00:00
|
|
|
def get_manifest_for_tag(self, tag, backfill_if_necessary=False):
|
2018-08-17 20:45:27 +00:00
|
|
|
""" Returns the manifest associated with the given tag. """
|
|
|
|
|
|
|
|
@abstractmethod
|
2018-08-28 17:02:26 +00:00
|
|
|
def lookup_manifest_by_digest(self, repository_ref, manifest_digest, allow_dead=False,
|
|
|
|
include_legacy_image=False):
|
2018-08-17 20:45:27 +00:00
|
|
|
""" Looks up the manifest with the given digest under the given repository and returns it
|
|
|
|
or None if none. """
|
|
|
|
|
2018-09-20 21:49:00 +00:00
|
|
|
@abstractmethod
|
2018-11-12 21:27:49 +00:00
|
|
|
def create_manifest_and_retarget_tag(self, repository_ref, manifest_interface_instance, tag_name,
|
|
|
|
storage):
|
2018-09-20 21:49:00 +00:00
|
|
|
""" Creates a manifest in a repository, adding all of the necessary data in the model.
|
|
|
|
|
|
|
|
The `manifest_interface_instance` parameter must be an instance of the manifest
|
|
|
|
interface as returned by the image/docker package.
|
|
|
|
|
|
|
|
Note that all blobs referenced by the manifest must exist under the repository or this
|
|
|
|
method will fail and return None.
|
|
|
|
|
|
|
|
Returns a reference to the (created manifest, tag) or (None, None) on error.
|
|
|
|
"""
|
|
|
|
|
2018-08-17 22:34:10 +00:00
|
|
|
@abstractmethod
|
|
|
|
def get_legacy_images(self, repository_ref):
|
|
|
|
"""
|
|
|
|
Returns an iterator of all the LegacyImage's defined in the matching repository.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
2018-09-13 19:51:14 +00:00
|
|
|
def get_legacy_image(self, repository_ref, docker_image_id, include_parents=False,
|
|
|
|
include_blob=False):
|
2018-08-17 22:34:10 +00:00
|
|
|
"""
|
|
|
|
Returns the matching LegacyImages under the matching repository, if any. If none,
|
|
|
|
returns None.
|
|
|
|
"""
|
2018-08-21 21:26:32 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def create_manifest_label(self, manifest, key, value, source_type_name, media_type_name=None):
|
|
|
|
""" Creates a label on the manifest with the given key and value.
|
|
|
|
|
|
|
|
Can raise InvalidLabelKeyException or InvalidMediaTypeException depending
|
|
|
|
on the validation errors.
|
|
|
|
"""
|
|
|
|
|
2018-09-20 20:00:02 +00:00
|
|
|
@abstractmethod
|
|
|
|
def batch_create_manifest_labels(self, manifest):
|
|
|
|
""" Returns a context manager for batch creation of labels on a manifest.
|
|
|
|
|
|
|
|
Can raise InvalidLabelKeyException or InvalidMediaTypeException depending
|
|
|
|
on the validation errors.
|
|
|
|
"""
|
|
|
|
|
2018-08-21 21:26:32 +00:00
|
|
|
@abstractmethod
|
|
|
|
def list_manifest_labels(self, manifest, key_prefix=None):
|
|
|
|
""" Returns all labels found on the manifest. If specified, the key_prefix will filter the
|
|
|
|
labels returned to those keys that start with the given prefix.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_manifest_label(self, manifest, label_uuid):
|
|
|
|
""" Returns the label with the specified UUID on the manifest or None if none. """
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def delete_manifest_label(self, manifest, label_uuid):
|
|
|
|
""" Delete the label with the specified UUID on the manifest. Returns the label deleted
|
|
|
|
or None if none.
|
|
|
|
"""
|
2018-08-22 19:06:11 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
2018-10-08 12:13:31 +00:00
|
|
|
def list_repository_tags(self, repository_ref, include_legacy_images=False,
|
|
|
|
start_pagination_id=None,
|
|
|
|
limit=None):
|
2018-08-22 19:06:11 +00:00
|
|
|
"""
|
|
|
|
Returns a list of all the active tags in the repository. Note that this can be a *heavy*
|
|
|
|
operation on repositories with a lot of tags, and should be avoided for more targetted
|
|
|
|
operations wherever possible.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
2018-09-20 19:49:20 +00:00
|
|
|
def list_repository_tag_history(self, repository_ref, page=1, size=100, specific_tag_name=None,
|
|
|
|
active_tags_only=False):
|
2018-08-22 19:06:11 +00:00
|
|
|
"""
|
|
|
|
Returns the history of all tags in the repository (unless filtered). This includes tags that
|
|
|
|
have been made in-active due to newer versions of those tags coming into service.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_repo_tag(self, repository_ref, tag_name, include_legacy_image=False):
|
|
|
|
"""
|
|
|
|
Returns the latest, *active* tag found in the repository, with the matching name
|
|
|
|
or None if none.
|
|
|
|
"""
|
|
|
|
|
2018-10-05 21:30:47 +00:00
|
|
|
@abstractmethod
|
|
|
|
def has_expired_tag(self, repository_ref, tag_name):
|
|
|
|
"""
|
|
|
|
Returns true if and only if the repository contains a tag with the given name that is expired.
|
|
|
|
"""
|
|
|
|
|
2018-08-22 19:06:11 +00:00
|
|
|
@abstractmethod
|
|
|
|
def retarget_tag(self, repository_ref, tag_name, manifest_or_legacy_image,
|
2018-11-12 21:27:49 +00:00
|
|
|
storage, is_reversion=False):
|
2018-08-22 19:06:11 +00:00
|
|
|
"""
|
|
|
|
Creates, updates or moves a tag to a new entry in history, pointing to the manifest or
|
|
|
|
legacy image specified. If is_reversion is set to True, this operation is considered a
|
|
|
|
reversion over a previous tag move operation. Returns the updated Tag or None on error.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def delete_tag(self, repository_ref, tag_name):
|
|
|
|
"""
|
|
|
|
Deletes the latest, *active* tag with the given name in the repository.
|
|
|
|
"""
|
|
|
|
|
2018-09-20 19:49:20 +00:00
|
|
|
@abstractmethod
|
|
|
|
def delete_tags_for_manifest(self, manifest):
|
|
|
|
"""
|
|
|
|
Deletes all tags pointing to the given manifest, making the manifest inaccessible for pulling.
|
|
|
|
Returns the tags deleted, if any. Returns None on error.
|
|
|
|
"""
|
|
|
|
|
2018-08-22 19:06:11 +00:00
|
|
|
@abstractmethod
|
|
|
|
def change_repository_tag_expiration(self, tag, expiration_date):
|
|
|
|
""" Sets the expiration date of the tag under the matching repository to that given. If the
|
|
|
|
expiration date is None, then the tag will not expire. Returns a tuple of the previous
|
|
|
|
expiration timestamp in seconds (if any), and whether the operation succeeded.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_legacy_images_owned_by_tag(self, tag):
|
|
|
|
""" Returns all legacy images *solely owned and used* by the given tag. """
|
2018-08-23 20:36:04 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_security_status(self, manifest_or_legacy_image):
|
|
|
|
""" Returns the security status for the given manifest or legacy image or None if none. """
|
2018-08-27 19:01:27 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def backfill_manifest_for_tag(self, tag):
|
|
|
|
""" Backfills a manifest for the V1 tag specified.
|
|
|
|
If a manifest already exists for the tag, returns that manifest.
|
|
|
|
|
|
|
|
NOTE: This method will only be necessary until we've completed the backfill, at which point
|
|
|
|
it should be removed.
|
|
|
|
"""
|
2018-08-28 17:02:26 +00:00
|
|
|
|
2018-10-08 15:32:09 +00:00
|
|
|
@abstractmethod
|
|
|
|
def is_existing_disabled_namespace(self, namespace_name):
|
|
|
|
""" Returns whether the given namespace exists and is disabled. """
|
|
|
|
|
2018-08-28 17:02:26 +00:00
|
|
|
@abstractmethod
|
|
|
|
def is_namespace_enabled(self, namespace_name):
|
|
|
|
""" Returns whether the given namespace exists and is enabled. """
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def list_manifest_layers(self, manifest, include_placements=False):
|
|
|
|
""" Returns an *ordered list* of the layers found in the manifest, starting at the base and
|
|
|
|
working towards the leaf, including the associated Blob and its placements (if specified).
|
|
|
|
Returns None if the manifest could not be parsed and validated.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def lookup_derived_image(self, manifest, verb, varying_metadata=None, include_placements=False):
|
|
|
|
"""
|
|
|
|
Looks up the derived image for the given manifest, verb and optional varying metadata and
|
|
|
|
returns it or None if none.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def lookup_or_create_derived_image(self, manifest, verb, storage_location, varying_metadata=None,
|
|
|
|
include_placements=False):
|
|
|
|
"""
|
|
|
|
Looks up the derived image for the given maniest, verb and optional varying metadata
|
|
|
|
and returns it. If none exists, a new derived image is created.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_derived_image_signature(self, derived_image, signer_name):
|
|
|
|
"""
|
|
|
|
Returns the signature associated with the derived image and a specific signer or None if none.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def set_derived_image_signature(self, derived_image, signer_name, signature):
|
|
|
|
"""
|
|
|
|
Sets the calculated signature for the given derived image and signer to that specified.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def delete_derived_image(self, derived_image):
|
|
|
|
"""
|
|
|
|
Deletes a derived image and all of its storage.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def set_derived_image_size(self, derived_image, compressed_size):
|
|
|
|
"""
|
|
|
|
Sets the compressed size on the given derived image.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_torrent_info(self, blob):
|
|
|
|
"""
|
|
|
|
Returns the torrent information associated with the given blob or None if none.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def set_torrent_info(self, blob, piece_length, pieces):
|
|
|
|
"""
|
|
|
|
Sets the torrent infomation associated with the given blob to that specified.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
2018-09-14 17:35:14 +00:00
|
|
|
def get_repo_blob_by_digest(self, repository_ref, blob_digest, include_placements=False):
|
2018-08-28 17:02:26 +00:00
|
|
|
"""
|
|
|
|
Returns the blob in the repository with the given digest, if any or None if none. Note that
|
|
|
|
there may be multiple records in the same repository for the same blob digest, so the return
|
|
|
|
value of this function may change.
|
|
|
|
"""
|
2018-09-14 17:35:14 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def create_blob_upload(self, repository_ref, upload_id, location_name, storage_metadata):
|
|
|
|
""" Creates a new blob upload and returns a reference. If the blob upload could not be
|
|
|
|
created, returns None. """
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def lookup_blob_upload(self, repository_ref, blob_upload_id):
|
|
|
|
""" Looks up the blob upload withn the given ID under the specified repository and returns it
|
|
|
|
or None if none.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def update_blob_upload(self, blob_upload, uncompressed_byte_count, piece_hashes, piece_sha_state,
|
|
|
|
storage_metadata, byte_count, chunk_count, sha_state):
|
|
|
|
""" Updates the fields of the blob upload to match those given. Returns the updated blob upload
|
|
|
|
or None if the record does not exists.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def delete_blob_upload(self, blob_upload):
|
|
|
|
""" Deletes a blob upload record. """
|
2018-09-14 18:08:23 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def commit_blob_upload(self, blob_upload, blob_digest_str, blob_expiration_seconds):
|
|
|
|
""" Commits the blob upload into a blob and sets an expiration before that blob will be GCed.
|
|
|
|
"""
|
2018-09-20 20:11:20 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def mount_blob_into_repository(self, blob, target_repository_ref, expiration_sec):
|
|
|
|
"""
|
|
|
|
Mounts the blob from another repository into the specified target repository, and adds an
|
|
|
|
expiration before that blob is automatically GCed. This function is useful during push
|
2018-11-13 15:13:51 +00:00
|
|
|
operations if an existing blob from another repository is being pushed. Returns False if
|
2018-10-08 15:32:09 +00:00
|
|
|
the mounting fails. Note that this function does *not* check security for mounting the blob
|
|
|
|
and the caller is responsible for doing this check (an example can be found in
|
|
|
|
endpoints/v2/blob.py).
|
2018-09-20 20:11:20 +00:00
|
|
|
"""
|
2018-09-20 21:49:00 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def set_tags_expiration_for_manifest(self, manifest, expiration_sec):
|
|
|
|
"""
|
|
|
|
Sets the expiration on all tags that point to the given manifest to that specified.
|
|
|
|
"""
|
2018-11-13 15:13:51 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_schema1_parsed_manifest(self, manifest, namespace_name, repo_name, tag_name, storage):
|
|
|
|
""" Returns the schema 1 version of this manifest, or None if none. """
|