Switch the registry data model types to our own class constructor

This allows us to hide the DB ID from external-to-the-package users of the types and will allow us to add model-level caching as well
This commit is contained in:
Joseph Schorr 2018-08-17 17:57:27 -04:00
parent 9f96e595ac
commit 8aafbf8b8c
2 changed files with 35 additions and 15 deletions

View file

@ -1,33 +1,51 @@
from collections import namedtuple def datatype(name, static_fields):
""" Defines a base class for a datatype that will represent a row from the database,
in an abstracted form.
"""
class DataType(object):
__name__ = name
class RepositoryReference(object): def __init__(self, *args, **kwargs):
self._db_id = kwargs.pop('db_id', None)
self._fields = kwargs
for name in static_fields:
assert name in self._fields, 'Missing field %s' % name
def __getattr__(self, name):
if name in static_fields:
return self._fields[name]
return None
return DataType
class RepositoryReference(datatype('Repository', [])):
""" RepositoryReference is a reference to a repository, passed to registry interface methods. """ """ RepositoryReference is a reference to a repository, passed to registry interface methods. """
def __init__(self, repo_id):
self.repo_id = repo_id
@classmethod @classmethod
def for_repo_obj(cls, repo_obj): def for_repo_obj(cls, repo_obj):
if repo_obj is None: if repo_obj is None:
return None return None
return RepositoryReference(repo_obj.id) return RepositoryReference(db_id=repo_obj.id)
class Tag(namedtuple('Tag', ['id', 'name'])): class Tag(datatype('Tag', ['name'])):
""" Tag represents a tag in a repository, which points to a manifest or image. """ """ Tag represents a tag in a repository, which points to a manifest or image. """
@classmethod @classmethod
def for_repository_tag(cls, repository_tag): def for_repository_tag(cls, repository_tag):
if repository_tag is None: if repository_tag is None:
return None return None
return Tag(id=repository_tag.id, name=repository_tag.name) return Tag(db_id=repository_tag.id, name=repository_tag.name)
class Manifest(namedtuple('Manifest', ['id', 'digest'])): class Manifest(datatype('Manifest', ['digest'])):
""" Manifest represents a manifest in a repository. """ """ Manifest represents a manifest in a repository. """
@classmethod @classmethod
def for_tag_manifest(cls, tag_manifest): def for_tag_manifest(cls, tag_manifest):
if tag_manifest is None: if tag_manifest is None:
return None return None
return Manifest(id=tag_manifest.id, digest=tag_manifest.digest) return Manifest(db_id=tag_manifest.id, digest=tag_manifest.digest)

View file

@ -1,3 +1,5 @@
# pylint: disable=protected-access
from data import database from data import database
from data import model from data import model
from data.registry_model.interface import RegistryDataInterface from data.registry_model.interface import RegistryDataInterface
@ -14,14 +16,14 @@ class PreOCIModel(RegistryDataInterface):
""" Finds an alive tag in the repository matching one of the given tag names and returns it """ Finds an alive tag in the repository matching one of the given tag names and returns it
or None if none. or None if none.
""" """
found_tag = model.tag.find_matching_tag(repository_ref.repo_id, tag_names) found_tag = model.tag.find_matching_tag(repository_ref._db_id, tag_names)
return Tag.for_repository_tag(found_tag) return Tag.for_repository_tag(found_tag)
def get_most_recent_tag(self, repository_ref): def get_most_recent_tag(self, repository_ref):
""" Returns the most recently pushed alive tag in the repository, if any. If none, returns """ Returns the most recently pushed alive tag in the repository, if any. If none, returns
None. None.
""" """
found_tag = model.tag.get_most_recent_tag(repository_ref.repo_id) found_tag = model.tag.get_most_recent_tag(repository_ref._db_id)
return Tag.for_repository_tag(found_tag) return Tag.for_repository_tag(found_tag)
def lookup_repository(self, namespace_name, repo_name, kind_filter=None): def lookup_repository(self, namespace_name, repo_name, kind_filter=None):
@ -33,7 +35,7 @@ class PreOCIModel(RegistryDataInterface):
def get_manifest_for_tag(self, tag): def get_manifest_for_tag(self, tag):
""" Returns the manifest associated with the given tag. """ """ Returns the manifest associated with the given tag. """
try: try:
tag_manifest = database.TagManifest.get(tag_id=tag.id) tag_manifest = database.TagManifest.get(tag_id=tag._db_id)
except database.TagManifest.DoesNotExist: except database.TagManifest.DoesNotExist:
return return
@ -42,7 +44,7 @@ class PreOCIModel(RegistryDataInterface):
def lookup_manifest_by_digest(self, repository_ref, manifest_digest, allow_dead=False): def lookup_manifest_by_digest(self, repository_ref, manifest_digest, allow_dead=False):
""" Looks up the manifest with the given digest under the given repository and returns it """ Looks up the manifest with the given digest under the given repository and returns it
or None if none. """ or None if none. """
repo = model.repository.lookup_repository(repository_ref.repo_id) repo = model.repository.lookup_repository(repository_ref._db_id)
if repo is None: if repo is None:
return None return None
@ -54,7 +56,7 @@ class PreOCIModel(RegistryDataInterface):
def create_manifest_label(self, manifest, key, value, source_type_name, media_type_name=None): 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. """ """ Creates a label on the manifest with the given key and value. """
try: try:
tag_manifest = database.TagManifest.get(id=manifest.id) tag_manifest = database.TagManifest.get(id=manifest._db_id)
except database.TagManifest.DoesNotExist: except database.TagManifest.DoesNotExist:
return return