Implement the "check_exc" parameter for OVO

This patch set is to implement "check_exc" parameter. It will
be used during converting model to OVO.

Moreover, this patch will create some usefull functions.

Partial Implements: blueprint rolling-upgrade

Change-Id: Ie4a0a47e14346ba81c15c80928a485e55c2c83ee
This commit is contained in:
Nam Nguyen Hoai 2018-06-20 14:05:35 +07:00
parent f2816271e0
commit 74da6f0e4b
10 changed files with 120 additions and 121 deletions

View File

@ -162,6 +162,27 @@ def get_secret_id_from_ref(secret_ref):
return secret_id
def get_secrets_id_from_refs(secret_refs):
"""Parse a secret reference and return the list of secret ID
:param secret_refs: a list of HTTP reference of secret
:return: a string containing the ID of the secret
"""
if secret_refs is None:
return None
secret_ids = []
for secret_ref in secret_refs:
secret_id = secret_ref.get('secret_ref')
if secret_id.endswith('/'):
secret_id = secret_id.rsplit('/', 2)[1]
elif '/' in secret_id:
secret_id = secret_id.rsplit('/', 1)[1]
else:
secret_id = secret_id
secret_ids.append(secret_id)
return secret_ids
def get_ca_id_from_ref(ca_ref):
"""Parse a ca_ref and return the CA ID

View File

@ -125,6 +125,9 @@ class ModelBase(object):
self._do_delete_children(session)
session.delete(self)
def get(self, key, default=None):
return getattr(self, key, default)
def _do_delete_children(self, session):
"""Sub-class hook: delete children relationships."""
pass
@ -240,6 +243,9 @@ class ContainerSecret(BASE, SoftDeleteMixIn, ModelBase):
__table_args__ = (sa.UniqueConstraint('container_id', 'secret_id', 'name',
name='_container_secret_name_uc'),)
def __init__(self, check_exc=True):
super(ContainerSecret, self).__init__()
class Project(BASE, SoftDeleteMixIn, ModelBase):
"""Represents a Project in the datastore.
@ -258,6 +264,9 @@ class Project(BASE, SoftDeleteMixIn, ModelBase):
cas = orm.relationship("ProjectCertificateAuthority", backref="project")
project_quotas = orm.relationship("ProjectQuotas", backref="project")
def __init__(self, check_exc=True):
super(Project, self).__init__()
def _do_extra_dict_fields(self):
"""Sub-class hook method: return dict of fields."""
return {'external_id': self.external_id}
@ -307,7 +316,7 @@ class Secret(BASE, SoftDeleteMixIn, ModelBase):
backref="secret",
cascade="all, delete-orphan")
def __init__(self, parsed_request=None):
def __init__(self, parsed_request=None, check_exc=True):
"""Creates secret from a dict."""
super(Secret, self).__init__()
@ -373,17 +382,17 @@ class SecretStoreMetadatum(BASE, SoftDeleteMixIn, ModelBase):
secret_id = sa.Column(
sa.String(36), sa.ForeignKey('secrets.id'), index=True, nullable=False)
def __init__(self, key, value):
def __init__(self, key=None, value=None, check_exc=True):
super(SecretStoreMetadatum, self).__init__()
msg = u._("Must supply non-None {0} argument "
"for SecretStoreMetadatum entry.")
if key is None:
if key is None and check_exc:
raise exception.MissingArgumentError(msg.format("key"))
self.key = key
if value is None:
if value is None and check_exc:
raise exception.MissingArgumentError(msg.format("value"))
self.value = value
@ -408,17 +417,17 @@ class SecretUserMetadatum(BASE, SoftDeleteMixIn, ModelBase):
__table_args__ = (sa.UniqueConstraint('secret_id', 'key',
name='_secret_key_uc'),)
def __init__(self, key, value):
def __init__(self, key=None, value=None, check_exc=True):
super(SecretUserMetadatum, self).__init__()
msg = u._("Must supply non-None {0} argument "
"for SecretUserMetadatum entry.")
if key is None:
if key is None and check_exc:
raise exception.MissingArgumentError(msg.format("key"))
self.key = key
if value is None:
if value is None and check_exc:
raise exception.MissingArgumentError(msg.format("value"))
self.value = value
@ -449,7 +458,7 @@ class EncryptedDatum(BASE, SoftDeleteMixIn, ModelBase):
# Eager load this relationship via 'lazy=False'.
kek_meta_project = orm.relationship("KEKDatum", lazy=False)
def __init__(self, secret=None, kek_datum=None):
def __init__(self, secret=None, kek_datum=None, check_exc=True):
"""Creates encrypted datum from a secret and KEK metadata."""
super(EncryptedDatum, self).__init__()
@ -509,6 +518,9 @@ class KEKDatum(BASE, SoftDeleteMixIn, ModelBase):
mode = sa.Column(sa.String(255))
plugin_meta = sa.Column(sa.Text)
def __index__(self, check_exc=True):
super(KEKDatum, self).__init__()
def _do_extra_dict_fields(self):
"""Sub-class hook method: return dict of fields."""
return {'algorithm': self.algorithm}
@ -558,7 +570,7 @@ class Order(BASE, SoftDeleteMixIn, ModelBase):
backref="order",
cascade="all, delete-orphan")
def __init__(self, parsed_request=None):
def __init__(self, parsed_request=None, check_exc=True):
"""Creates a Order entity from a dict."""
super(Order, self).__init__()
if parsed_request:
@ -629,17 +641,17 @@ class OrderPluginMetadatum(BASE, SoftDeleteMixIn, ModelBase):
key = sa.Column(sa.String(255), nullable=False)
value = sa.Column(sa.String(255), nullable=False)
def __init__(self, key, value):
def __init__(self, key=None, value=None, check_exc=True):
super(OrderPluginMetadatum, self).__init__()
msg = u._("Must supply non-None {0} argument "
"for OrderPluginMetadatum entry.")
if key is None:
if key is None and check_exc:
raise exception.MissingArgumentError(msg.format("key"))
self.key = key
if value is None:
if value is None and check_exc:
raise exception.MissingArgumentError(msg.format("value"))
self.value = value
@ -665,17 +677,17 @@ class OrderBarbicanMetadatum(BASE, SoftDeleteMixIn, ModelBase):
key = sa.Column(sa.String(255), nullable=False)
value = sa.Column(sa.Text, nullable=False)
def __init__(self, key, value):
def __init__(self, key=None, value=None, check_exc=True):
super(OrderBarbicanMetadatum, self).__init__()
msg = u._("Must supply non-None {0} argument "
"for OrderBarbicanMetadatum entry.")
if key is None:
if key is None and check_exc:
raise exception.MissingArgumentError(msg.format("key"))
self.key = key
if value is None:
if value is None and check_exc:
raise exception.MissingArgumentError(msg.format("value"))
self.value = value
@ -703,6 +715,9 @@ class OrderRetryTask(BASE, SoftDeleteMixIn, ModelBase):
retry_kwargs = sa.Column(JsonBlob(), nullable=False)
retry_count = sa.Column(sa.Integer, nullable=False, default=0)
def __index__(self, check_exc):
super(OrderRetryTask, self).__init__()
class Container(BASE, SoftDeleteMixIn, ModelBase):
"""Represents a Container for Secrets in the datastore.
@ -726,7 +741,7 @@ class Container(BASE, SoftDeleteMixIn, ModelBase):
consumers = sa.orm.relationship("ContainerConsumerMetadatum")
creator_id = sa.Column(sa.String(255))
def __init__(self, parsed_request=None):
def __init__(self, parsed_request=None, check_exc=True):
"""Creates a Container entity from a dict."""
super(Container, self).__init__()
@ -805,7 +820,8 @@ class ContainerConsumerMetadatum(BASE, SoftDeleteMixIn, ModelBase):
sa.Index('values_index', 'container_id', 'name', 'URL')
)
def __init__(self, container_id, project_id, parsed_request):
def __init__(self, container_id=None, project_id=None,
parsed_request=None, check_exc=True):
"""Registers a Consumer to a Container."""
super(ContainerConsumerMetadatum, self).__init__()
@ -839,18 +855,18 @@ class TransportKey(BASE, SoftDeleteMixIn, ModelBase):
plugin_name = sa.Column(sa.String(255), nullable=False)
transport_key = sa.Column(sa.Text, nullable=False)
def __init__(self, plugin_name, transport_key):
def __init__(self, plugin_name=None, transport_key=None, check_exc=True):
"""Creates transport key entity."""
super(TransportKey, self).__init__()
msg = u._("Must supply non-None {0} argument for TransportKey entry.")
if plugin_name is None:
if plugin_name is None and check_exc:
raise exception.MissingArgumentError(msg.format("plugin_name"))
self.plugin_name = plugin_name
if transport_key is None:
if transport_key is None and check_exc:
raise exception.MissingArgumentError(msg.format("transport_key"))
self.transport_key = transport_key
@ -886,7 +902,7 @@ class CertificateAuthority(BASE, ModelBase):
cascade="all, delete-orphan"
)
def __init__(self, parsed_ca_in):
def __init__(self, parsed_ca_in=None, check_exc=True):
"""Creates certificate authority entity."""
super(CertificateAuthority, self).__init__()
@ -961,17 +977,17 @@ class CertificateAuthorityMetadatum(BASE, ModelBase):
__table_args__ = (sa.UniqueConstraint(
'ca_id', 'key', name='_certificate_authority_metadatum_uc'),)
def __init__(self, key, value):
def __init__(self, key=None, value=None, check_exc=True):
super(CertificateAuthorityMetadatum, self).__init__()
msg = u._("Must supply non-None {0} argument "
"for CertificateAuthorityMetadatum entry.")
if key is None:
if key is None and check_exc:
raise exception.MissingArgumentError(msg.format("key"))
self.key = key
if value is None:
if value is None and check_exc:
raise exception.MissingArgumentError(msg.format("value"))
self.value = value
@ -1007,18 +1023,18 @@ class ProjectCertificateAuthority(BASE, ModelBase):
__table_args__ = (sa.UniqueConstraint(
'project_id', 'ca_id', name='_project_certificate_authority_uc'),)
def __init__(self, project_id, ca_id):
def __init__(self, project_id=None, ca_id=None, check_exc=True):
"""Registers a Consumer to a Container."""
super(ProjectCertificateAuthority, self).__init__()
msg = u._("Must supply non-None {0} argument "
"for ProjectCertificateAuthority entry.")
if project_id is None:
if project_id is None and check_exc:
raise exception.MissingArgumentError(msg.format("project_id"))
self.project_id = project_id
if ca_id is None:
if ca_id is None and check_exc:
raise exception.MissingArgumentError(msg.format("ca_id"))
self.ca_id = ca_id
@ -1059,18 +1075,18 @@ class PreferredCertificateAuthority(BASE, ModelBase):
ca = orm.relationship('CertificateAuthority',
backref=orm.backref('preferred_ca'))
def __init__(self, project_id, ca_id):
def __init__(self, project_id=None, ca_id=None, check_exc=True):
"""Registers a Consumer to a Container."""
super(PreferredCertificateAuthority, self).__init__()
msg = u._("Must supply non-None {0} argument "
"for PreferredCertificateAuthority entry.")
if project_id is None:
if project_id is None and check_exc:
raise exception.MissingArgumentError(msg.format("project_id"))
self.project_id = project_id
if ca_id is None:
if ca_id is None and check_exc:
raise exception.MissingArgumentError(msg.format("ca_id"))
self.ca_id = ca_id
@ -1113,18 +1129,18 @@ class SecretACL(BASE, ModelBase):
__table_args__ = (sa.UniqueConstraint(
'secret_id', 'operation', name='_secret_acl_operation_uc'),)
def __init__(self, secret_id, operation, project_access=None,
user_ids=None):
def __init__(self, secret_id=None, operation=None, project_access=None,
user_ids=None, check_exc=True):
"""Creates secret ACL entity."""
super(SecretACL, self).__init__()
msg = u._("Must supply non-None {0} argument for SecretACL entry.")
if secret_id is None:
if secret_id is None and check_exc:
raise exception.MissingArgumentError(msg.format("secret_id"))
self.secret_id = secret_id
if operation is None:
if operation is None and check_exc:
raise exception.MissingArgumentError(msg.format("operation"))
self.operation = operation
@ -1189,18 +1205,18 @@ class ContainerACL(BASE, ModelBase):
__table_args__ = (sa.UniqueConstraint(
'container_id', 'operation', name='_container_acl_operation_uc'),)
def __init__(self, container_id, operation, project_access=None,
user_ids=None):
def __init__(self, container_id=None, operation=None, project_access=None,
user_ids=None, check_exc=True):
"""Creates container ACL entity."""
super(ContainerACL, self).__init__()
msg = u._("Must supply non-None {0} argument for ContainerACL entry.")
if container_id is None:
if container_id is None and check_exc:
raise exception.MissingArgumentError(msg.format("container_id"))
self.container_id = container_id
if operation is None:
if operation is None and check_exc:
raise exception.MissingArgumentError(msg.format("operation"))
self.operation = operation
@ -1254,14 +1270,14 @@ class SecretACLUser(BASE, ModelBase):
__table_args__ = (sa.UniqueConstraint(
'acl_id', 'user_id', name='_secret_acl_user_uc'),)
def __init__(self, acl_id, user_id):
def __init__(self, acl_id=None, user_id=None, check_exc=True):
"""Creates secret ACL user entity."""
super(SecretACLUser, self).__init__()
msg = u._("Must supply non-None {0} argument for SecretACLUser entry.")
self.acl_id = acl_id
if user_id is None:
if user_id is None and check_exc:
raise exception.MissingArgumentError(msg.format("user_id"))
self.user_id = user_id
self.status = States.ACTIVE
@ -1291,7 +1307,7 @@ class ContainerACLUser(BASE, ModelBase):
__table_args__ = (sa.UniqueConstraint(
'acl_id', 'user_id', name='_container_acl_user_uc'),)
def __init__(self, acl_id, user_id):
def __init__(self, acl_id=None, user_id=None, check_exc=True):
"""Creates container ACL user entity."""
super(ContainerACLUser, self).__init__()
@ -1299,7 +1315,7 @@ class ContainerACLUser(BASE, ModelBase):
"entry.")
self.acl_id = acl_id
if user_id is None:
if user_id is None and check_exc:
raise exception.MissingArgumentError(msg.format("user_id"))
self.user_id = user_id
self.status = States.ACTIVE
@ -1331,7 +1347,8 @@ class ProjectQuotas(BASE, ModelBase):
consumers = sa.Column(sa.Integer, nullable=True)
cas = sa.Column(sa.Integer, nullable=True)
def __init__(self, project_id=None, parsed_project_quotas=None):
def __init__(self, project_id=None, parsed_project_quotas=None,
check_exc=True):
"""Creates Project Quotas entity from a project and a dict.
:param project_id: the internal id of the project with quotas
@ -1344,7 +1361,7 @@ class ProjectQuotas(BASE, ModelBase):
msg = u._("Must supply non-None {0} argument for ProjectQuotas entry.")
if project_id is None:
if project_id is None and check_exc:
raise exception.MissingArgumentError(msg.format("project_id"))
self.project_id = project_id
@ -1400,16 +1417,16 @@ class SecretStores(BASE, ModelBase):
name='_secret_stores_plugin_names_uc'),
sa.UniqueConstraint('name', name='_secret_stores_name_uc'),)
def __init__(self, name, store_plugin, crypto_plugin=None,
global_default=None):
def __init__(self, name=None, store_plugin=None, crypto_plugin=None,
global_default=None, check_exc=True):
"""Creates secret store entity."""
super(SecretStores, self).__init__()
msg = u._("Must supply non-Blank {0} argument for SecretStores entry.")
if not name:
if not name and check_exc:
raise exception.MissingArgumentError(msg.format("name"))
if not store_plugin:
if not store_plugin and check_exc:
raise exception.MissingArgumentError(msg.format("store_plugin"))
self.store_plugin = store_plugin
@ -1456,17 +1473,17 @@ class ProjectSecretStore(BASE, ModelBase):
__table_args__ = (sa.UniqueConstraint(
'project_id', name='_project_secret_store_project_uc'),)
def __init__(self, project_id, secret_store_id):
def __init__(self, project_id=None, secret_store_id=None, check_exc=True):
"""Creates project secret store mapping entity."""
super(ProjectSecretStore, self).__init__()
msg = u._("Must supply non-None {0} argument for ProjectSecretStore "
" entry.")
if not project_id:
if not project_id and check_exc:
raise exception.MissingArgumentError(msg.format("project_id"))
self.project_id = project_id
if not secret_store_id:
if not secret_store_id and check_exc:
raise exception.MissingArgumentError(msg.format("secret_store_id"))
self.secret_store_id = secret_store_id

View File

@ -206,6 +206,13 @@ def _get_engine(engine):
return engine
def model_query(model, *args, **kwargs):
"""Query helper for simpler session usage."""
session = kwargs.get('session')
query = session.query(model, *args)
return query
def _initialize_secret_stores_data():
"""Initializes secret stores data in database.
@ -420,6 +427,23 @@ class BaseRepo(object):
return entity
def update_from(self, model_class, entity_id, values, session=None):
if id in values:
raise Exception('Cannot update id')
LOG.debug('Begin update from ...')
session = self.get_session(session=session)
query = session.query(model_class)
query = query.filter_by(id=entity_id)
try:
LOG.debug('Updating value ...')
entity = query.one()
except sa_orm.exc.NoResultFound:
raise exception.NotFound('DB Entity with id {0} not '
'found'.format(entity_id))
self._update_values(entity, values)
entity.save(session)
def save(self, entity):
"""Saves the state of the entity."""
entity.updated_at = timeutils.utcnow()

View File

@ -65,7 +65,7 @@ class BarbicanObject(object_base.VersionedObject):
setattr(self, name_attr, value_attr)
def _get_db_entity(self):
return self.db_model()
return self.db_model(check_exc=False)
def _get_changed_persistent_fields(self):
change_fields = self.obj_get_changes()
@ -174,7 +174,7 @@ class BarbicanObject(object_base.VersionedObject):
@classmethod
def get_session(cls, session=None):
return cls.db_repo.get_session(session)
return session or repos.get_session()
@classmethod
def delete_entity_by_id(cls, entity_id, external_project_id,

View File

@ -68,7 +68,7 @@ class Container(base.BarbicanObject, base.BarbicanPersistentObject,
self.container_secrets.append(container_secret)
def _get_db_entity(self, data=None):
return self.db_model(parsed_request=data)
return self.db_model(parsed_request=data, check_exc=False)
def _attach_container_secret(self, container_secrets, container_id,
session):

View File

@ -50,7 +50,7 @@ class ContainerACL(base.BarbicanObject, base.BarbicanPersistentObject,
raise exception.MissingArgumentError(msg.format("operation"))
def _get_db_entity(self, user_ids=None):
return self.db_model(user_ids=user_ids)
return self.db_model(user_ids=user_ids, check_exc=False)
def create(self, session=None, user_ids=None):
change_fields = self._get_changed_persistent_fields()

View File

@ -45,7 +45,8 @@ class ProjectQuotas(base.BarbicanObject, base.BarbicanPersistentObject,
raise exception.MissingArgumentError(msg.format("project_id"))
def _get_db_entity(self, parsed_project_quotas=None):
return self.db_model(parsed_project_quotas=parsed_project_quotas)
return self.db_model(parsed_project_quotas=parsed_project_quotas,
check_exc=False)
def create(self, session=None, parsed_project_quotas=None):
change_fields = self._get_changed_persistent_fields()

View File

@ -49,7 +49,7 @@ class SecretACL(base.BarbicanObject, base.BarbicanPersistentObject,
raise exception.MissingArgumentError(msg.format("operation"))
def _get_db_entity(self, user_ids=None):
return self.db_model(user_ids=user_ids)
return self.db_model(user_ids=user_ids, check_exc=False)
def create(self, session=None, user_ids=None):
change_fields = self._get_changed_persistent_fields()

View File

@ -1,64 +0,0 @@
# Copyright 2018 Fujitsu.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
class MockObjectMixin(object):
"""Class for setting up the objects factory mocks"""
def _setup_object_fuction_mock(self, object_name, function_name,
return_value, side_effect):
path_function = 'barbican.objects.{}.{}'.format(object_name,
function_name)
patcher_obj = mock.patch(path_function,
return_value=return_value,
side_effect=side_effect)
patcher_obj.start()
self.addCleanup(patcher_obj.stop)
def mock_container_obj_function(self, func_name,
return_value=None, side_effect=None):
self._setup_object_fuction_mock(object_name='Container',
function_name=func_name,
return_value=return_value,
side_effect=side_effect)
def mock_secret_obj_function(self, func_name,
return_value=None, side_effect=None):
self._setup_object_fuction_mock(object_name='Secret',
function_name=func_name,
return_value=return_value,
side_effect=side_effect)
def mock_container_acl_obj_function(self, func_name,
return_value=None, side_effect=None):
self._setup_object_fuction_mock(object_name='ContainerACL',
function_name=func_name,
return_value=return_value,
side_effect=side_effect)
def mock_order_obj_function(self, func_name,
return_value=None, side_effect=None):
self._setup_object_fuction_mock(object_name='Order',
function_name=func_name,
return_value=return_value,
side_effect=side_effect)
def mock_con_con_obj_function(self, func_name,
return_value=None, side_effect=None):
self._setup_object_fuction_mock(
object_name='ContainerConsumerMetadatum',
function_name=func_name,
return_value=return_value,
side_effect=side_effect)