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
This commit is contained in:
parent
50dc57acdf
commit
d59bea3569
7 changed files with 115 additions and 12 deletions
82
data/registry_model/modelsplitter.py
Normal file
82
data/registry_model/modelsplitter.py
Normal file
|
@ -0,0 +1,82 @@
|
|||
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
|
Reference in a new issue