import tarfile from collections import namedtuple from util.registry.gzipwrap import GzipWrap class ManifestJSON(namedtuple('ManifestJSON', ['digest', 'json', 'media_type'])): """ ManifestJSON represents a Manifest of any format. """ class Repository(namedtuple('Repository', ['id', 'name', 'namespace_name'])): """ Repository represents a collection of tags. """ class Tag(namedtuple('Tag', ['name', 'repository'])): """ Tag represents a user-facing alias for referencing a set of Manifests. """ class BlobUpload(namedtuple('BlobUpload', ['uuid', 'byte_count', 'uncompressed_byte_count', 'chunk_count', 'sha_state', 'location_name', 'storage_metadata', 'piece_sha_state', 'piece_hashes'])): """ BlobUpload represents the current state of an Blob being uploaded. """ class Blob(namedtuple('Blob', ['digest', 'size', 'locations'])): """ Blob represents an opaque binary blob saved to the storage system. """ class TarImageFormatter(object): """ Base class for classes which produce a tar containing image and layer data. """ def build_stream(self, namespace, repository, tag, synthetic_image_id, layer_json, get_image_iterator, get_layer_iterator, get_image_json): """ Builds and streams a synthetic .tar.gz that represents the formatted tar created by this class's implementation. """ return GzipWrap(self.stream_generator(namespace, repository, tag, synthetic_image_id, layer_json, get_image_iterator, get_layer_iterator, get_image_json)) def stream_generator(self, namespace, repository, tag, synthetic_image_id, layer_json, get_image_iterator, get_layer_iterator, get_image_json): raise NotImplementedError def tar_file(self, name, contents, mtime=None): """ Returns the tar binary representation for a file with the given name and file contents. """ length = len(contents) tar_data = self.tar_file_header(name, length, mtime=mtime) tar_data += contents tar_data += self.tar_file_padding(length) return tar_data def tar_file_padding(self, length): """ Returns tar file padding for file data of the given length. """ if length % 512 != 0: return '\0' * (512 - (length % 512)) return '' def tar_file_header(self, name, file_size, mtime=None): """ Returns tar file header data for a file with the given name and size. """ info = tarfile.TarInfo(name=name) info.type = tarfile.REGTYPE info.size = file_size if mtime is not None: info.mtime = mtime return info.tobuf() def tar_folder(self, name, mtime=None): """ Returns tar file header data for a folder with the given name. """ info = tarfile.TarInfo(name=name) info.type = tarfile.DIRTYPE if mtime is not None: info.mtime = mtime # allow the directory to be readable by non-root users info.mode = 0755 return info.tobuf()