This repository has been archived on 2020-03-24. You can view files and clone it, but cannot push or open issues or pull requests.
quay/data/registry_model/modelsplitter.py
Joseph Schorr d59bea3569 Enable a configurable whitelist of namespaces for V22
If a namespace is present in the whitelist, all calls are sent to the OCI model instead of the Pre OCI model

Note that this does increase overhead for registry calls (since we need to lookup the namespace for every single call), but it should only be temporary until we've migrated all users over to the OCI data model
2018-12-03 17:37:28 -05:00

82 lines
3.1 KiB
Python

import inspect
import logging
from data.database import DerivedStorageForImage, TagManifest, Manifest, Image
from data.registry_model.registry_oci_model import oci_model
from data.registry_model.registry_pre_oci_model import pre_oci_model
from data.registry_model.datatypes import LegacyImage, Manifest as ManifestDataType
logger = logging.getLogger(__name__)
class SplitModel(object):
def __init__(self, v22_namespace_whitelist):
self.v22_namespace_whitelist = set(v22_namespace_whitelist)
def supports_schema2(self, namespace_name):
""" Returns whether the implementation of the data interface supports schema 2 format
manifests. """
return namespace_name in self.v22_namespace_whitelist
def _namespace_from_kwargs(self, args_dict):
if 'namespace_name' in args_dict:
return args_dict['namespace_name']
if 'repository_ref' in args_dict:
return args_dict['repository_ref'].namespace_name
if 'tag' in args_dict:
return args_dict['tag'].repository.namespace_name
if 'manifest' in args_dict:
manifest = args_dict['manifest']
if manifest._is_tag_manifest:
return TagManifest.get(id=manifest._db_id).tag.repository.namespace_user.username
else:
return Manifest.get(id=manifest._db_id).repository.namespace_user.username
if 'manifest_or_legacy_image' in args_dict:
manifest_or_legacy_image = args_dict['manifest_or_legacy_image']
if isinstance(manifest_or_legacy_image, LegacyImage):
return Image.get(id=manifest_or_legacy_image._db_id).repository.namespace_user.username
else:
manifest = manifest_or_legacy_image
if manifest._is_tag_manifest:
return TagManifest.get(id=manifest._db_id).tag.repository.namespace_user.username
else:
return Manifest.get(id=manifest._db_id).repository.namespace_user.username
if 'derived_image' in args_dict:
return (DerivedStorageForImage
.get(id=args_dict['derived_image']._db_id)
.source_image
.repository
.namespace_user
.username)
if 'blob' in args_dict:
return '' # Blob functions are shared, so no need to do anything.
if 'blob_upload' in args_dict:
return '' # Blob functions are shared, so no need to do anything.
raise Exception('Unknown namespace for dict `%s`' % args_dict)
def __getattr__(self, attr):
def method(*args, **kwargs):
argnames = inspect.getargspec(getattr(oci_model, attr))[0]
if not argnames and isinstance(args[0], ManifestDataType):
args_dict = dict(manifest=args[0])
else:
args_dict = {argnames[index + 1]: value for index, value in enumerate(args)}
namespace_name = self._namespace_from_kwargs(args_dict)
if namespace_name in self.v22_namespace_whitelist:
logger.debug('Calling method `%s` under OCI data model for namespace `%s`',
attr, namespace_name)
return getattr(oci_model, attr)(*args, **kwargs)
else:
return getattr(pre_oci_model, attr)(*args, **kwargs)
return method