2018-11-12 21:27:01 +00:00
|
|
|
from abc import ABCMeta, abstractproperty, abstractmethod
|
2018-07-31 19:41:30 +00:00
|
|
|
from six import add_metaclass
|
|
|
|
|
|
|
|
@add_metaclass(ABCMeta)
|
|
|
|
class ManifestInterface(object):
|
|
|
|
""" Defines the interface for the various manifests types supported. """
|
2018-11-15 11:51:48 +00:00
|
|
|
@abstractproperty
|
|
|
|
def is_manifest_list(self):
|
|
|
|
""" Returns whether this manifest is a list. """
|
|
|
|
|
2018-11-13 17:05:45 +00:00
|
|
|
@abstractproperty
|
|
|
|
def schema_version(self):
|
2018-11-15 11:51:48 +00:00
|
|
|
""" The version of the schema. """
|
2018-11-13 17:05:45 +00:00
|
|
|
|
2018-07-31 19:41:30 +00:00
|
|
|
@abstractproperty
|
|
|
|
def digest(self):
|
|
|
|
""" The digest of the manifest, including type prefix. """
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractproperty
|
|
|
|
def media_type(self):
|
|
|
|
""" The media type of the schema. """
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractproperty
|
|
|
|
def manifest_dict(self):
|
|
|
|
""" Returns the manifest as a dictionary ready to be serialized to JSON. """
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractproperty
|
|
|
|
def bytes(self):
|
|
|
|
""" Returns the bytes of the manifest. """
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractproperty
|
2018-11-21 15:23:52 +00:00
|
|
|
def layers_compressed_size(self):
|
|
|
|
""" Returns the total compressed size of all the layers in this manifest. Returns None if this
|
|
|
|
cannot be computed locally.
|
|
|
|
"""
|
|
|
|
|
2018-11-26 15:58:48 +00:00
|
|
|
@abstractmethod
|
|
|
|
def get_layers(self, content_retriever):
|
|
|
|
""" Returns the layers of this manifest, from base to leaf or None if this kind of manifest
|
|
|
|
does not support layers. The layer must be of type ManifestImageLayer. """
|
|
|
|
pass
|
|
|
|
|
2018-11-21 15:23:52 +00:00
|
|
|
@abstractmethod
|
|
|
|
def get_leaf_layer_v1_image_id(self, content_retriever):
|
2018-11-14 07:15:58 +00:00
|
|
|
""" Returns the Docker V1 image ID for the leaf (top) layer, if any, or None if
|
|
|
|
not applicable. """
|
2018-07-31 19:41:30 +00:00
|
|
|
pass
|
|
|
|
|
2018-11-21 15:23:52 +00:00
|
|
|
@abstractmethod
|
|
|
|
def get_legacy_image_ids(self, content_retriever):
|
2018-09-20 21:49:00 +00:00
|
|
|
""" Returns the Docker V1 image IDs for the layers of this manifest or None if not applicable.
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
2018-07-31 19:41:30 +00:00
|
|
|
@abstractproperty
|
|
|
|
def blob_digests(self):
|
|
|
|
""" Returns an iterator over all the blob digests referenced by this manifest,
|
2018-11-12 21:27:01 +00:00
|
|
|
from base to leaf. The blob digests are strings with prefixes. For manifests that reference
|
2018-11-28 10:56:16 +00:00
|
|
|
config as a blob, the blob will be included here as the last entry.
|
2018-11-12 21:27:01 +00:00
|
|
|
"""
|
|
|
|
|
2018-11-14 11:21:50 +00:00
|
|
|
@abstractproperty
|
|
|
|
def local_blob_digests(self):
|
|
|
|
""" Returns an iterator over all the *non-remote* blob digests referenced by this manifest,
|
|
|
|
from base to leaf. The blob digests are strings with prefixes. For manifests that reference
|
2018-11-28 10:56:16 +00:00
|
|
|
config as a blob, the blob will be included here as the last entry.
|
2018-11-14 11:21:50 +00:00
|
|
|
"""
|
|
|
|
|
2018-11-12 21:27:01 +00:00
|
|
|
@abstractmethod
|
2018-11-19 09:55:52 +00:00
|
|
|
def child_manifests(self, content_retriever):
|
2018-11-14 07:15:58 +00:00
|
|
|
""" Returns an iterator of all manifests that live under this manifest, if any or None if not
|
2018-11-19 09:55:52 +00:00
|
|
|
applicable.
|
2018-11-12 21:27:01 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
2018-11-19 09:55:52 +00:00
|
|
|
def get_manifest_labels(self, content_retriever):
|
2018-11-14 07:15:58 +00:00
|
|
|
""" Returns a dictionary of all the labels defined inside this manifest or None if this kind
|
|
|
|
of manifest does not support labels. """
|
2018-11-12 21:27:01 +00:00
|
|
|
pass
|
|
|
|
|
2018-11-25 14:16:59 +00:00
|
|
|
@abstractmethod
|
|
|
|
def get_requires_empty_layer_blob(self, content_retriever):
|
|
|
|
""" Whether this schema requires the special empty layer blob. """
|
|
|
|
pass
|
|
|
|
|
2018-11-12 21:27:01 +00:00
|
|
|
@abstractmethod
|
|
|
|
def unsigned(self):
|
|
|
|
""" Returns an unsigned version of this manifest. """
|
|
|
|
|
2018-11-21 15:23:52 +00:00
|
|
|
@abstractproperty
|
|
|
|
def has_legacy_image(self):
|
|
|
|
""" Returns True if this manifest has a legacy V1 image, or False if not. """
|
|
|
|
|
2018-11-12 21:27:01 +00:00
|
|
|
@abstractmethod
|
2018-11-19 09:55:52 +00:00
|
|
|
def generate_legacy_layers(self, images_map, content_retriever):
|
2018-11-12 21:27:01 +00:00
|
|
|
"""
|
2018-11-21 15:23:52 +00:00
|
|
|
Rewrites Docker v1 image IDs and returns a generator of DockerV1Metadata, starting
|
|
|
|
at the base layer and working towards the leaf.
|
2018-11-12 21:27:01 +00:00
|
|
|
|
|
|
|
If Docker gives us a layer with a v1 image ID that already points to existing
|
|
|
|
content, but the checksums don't match, then we need to rewrite the image ID
|
|
|
|
to something new in order to ensure consistency.
|
|
|
|
|
|
|
|
Returns None if there are no legacy images associated with the manifest.
|
2018-07-31 19:41:30 +00:00
|
|
|
"""
|
2018-11-13 08:40:57 +00:00
|
|
|
|
|
|
|
@abstractmethod
|
2018-11-21 15:23:52 +00:00
|
|
|
def get_schema1_manifest(self, namespace_name, repo_name, tag_name, content_retriever):
|
|
|
|
""" Returns a schema1 version of the manifest. If this is a mainfest list, should return the
|
|
|
|
manifest that is compatible with V1, by virtue of being `amd64` and `linux`.
|
2018-11-13 08:40:57 +00:00
|
|
|
If none, returns None.
|
|
|
|
"""
|
2018-11-19 09:55:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
@add_metaclass(ABCMeta)
|
|
|
|
class ContentRetriever(object):
|
2018-11-21 15:23:52 +00:00
|
|
|
""" Defines the interface for retrieval of various content referenced by a manifest. """
|
2018-11-19 09:55:52 +00:00
|
|
|
@abstractmethod
|
|
|
|
def get_manifest_bytes_with_digest(self, digest):
|
|
|
|
""" Returns the bytes of the manifest with the given digest or None if none found. """
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_blob_bytes_with_digest(self, digest):
|
|
|
|
""" Returns the bytes of the blob with the given digest or None if none found. """
|