Merge "Make use of Dict-base including extras explicit"
This commit is contained in:
commit
39c6b0ff53
@ -87,7 +87,7 @@ Changing the SQL Model and Driver
|
|||||||
First, you need to change the role model to include the description attribute.
|
First, you need to change the role model to include the description attribute.
|
||||||
Go to `keystone/assignment/role_backends/sql.py` and update it like::
|
Go to `keystone/assignment/role_backends/sql.py` and update it like::
|
||||||
|
|
||||||
class RoleTable(sql.ModelBase, sql.DictBase):
|
class RoleTable(sql.ModelBase, sql.ModelDictMixin):
|
||||||
|
|
||||||
attributes = ['id', 'name', 'domain_id', 'description']
|
attributes = ['id', 'name', 'domain_id', 'description']
|
||||||
description = sql.Column(sql.String(255), nullable=True)
|
description = sql.Column(sql.String(255), nullable=True)
|
||||||
|
@ -288,7 +288,7 @@ class Assignment(base.AssignmentDriverBase):
|
|||||||
q.delete(False)
|
q.delete(False)
|
||||||
|
|
||||||
|
|
||||||
class RoleAssignment(sql.ModelBase, sql.DictBase):
|
class RoleAssignment(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'assignment'
|
__tablename__ = 'assignment'
|
||||||
attributes = ['type', 'actor_id', 'target_id', 'role_id', 'inherited']
|
attributes = ['type', 'actor_id', 'target_id', 'role_id', 'inherited']
|
||||||
# NOTE(henry-nash): Postgres requires a name to be defined for an Enum
|
# NOTE(henry-nash): Postgres requires a name to be defined for an Enum
|
||||||
|
@ -145,7 +145,7 @@ class Role(base.RoleDriverBase):
|
|||||||
return ref.to_dict()
|
return ref.to_dict()
|
||||||
|
|
||||||
|
|
||||||
class ImpliedRoleTable(sql.ModelBase, sql.DictBase):
|
class ImpliedRoleTable(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'implied_role'
|
__tablename__ = 'implied_role'
|
||||||
attributes = ['prior_role_id', 'implied_role_id']
|
attributes = ['prior_role_id', 'implied_role_id']
|
||||||
prior_role_id = sql.Column(
|
prior_role_id = sql.Column(
|
||||||
@ -174,7 +174,7 @@ class ImpliedRoleTable(sql.ModelBase, sql.DictBase):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class RoleTable(sql.ModelBase, sql.DictBase):
|
class RoleTable(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
|
|
||||||
def to_dict(self, include_extra_dict=False):
|
def to_dict(self, include_extra_dict=False):
|
||||||
d = super(RoleTable, self).to_dict(
|
d = super(RoleTable, self).to_dict(
|
||||||
|
@ -31,7 +31,7 @@ from keystone.i18n import _
|
|||||||
CONF = keystone.conf.CONF
|
CONF = keystone.conf.CONF
|
||||||
|
|
||||||
|
|
||||||
class Region(sql.ModelBase, sql.DictBase):
|
class Region(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
__tablename__ = 'region'
|
__tablename__ = 'region'
|
||||||
attributes = ['id', 'description', 'parent_region_id']
|
attributes = ['id', 'description', 'parent_region_id']
|
||||||
id = sql.Column(sql.String(255), primary_key=True)
|
id = sql.Column(sql.String(255), primary_key=True)
|
||||||
@ -50,7 +50,7 @@ class Region(sql.ModelBase, sql.DictBase):
|
|||||||
endpoints = sqlalchemy.orm.relationship("Endpoint", backref="region")
|
endpoints = sqlalchemy.orm.relationship("Endpoint", backref="region")
|
||||||
|
|
||||||
|
|
||||||
class Service(sql.ModelBase, sql.DictBase):
|
class Service(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
__tablename__ = 'service'
|
__tablename__ = 'service'
|
||||||
attributes = ['id', 'type', 'enabled']
|
attributes = ['id', 'type', 'enabled']
|
||||||
id = sql.Column(sql.String(64), primary_key=True)
|
id = sql.Column(sql.String(64), primary_key=True)
|
||||||
@ -61,7 +61,7 @@ class Service(sql.ModelBase, sql.DictBase):
|
|||||||
endpoints = sqlalchemy.orm.relationship("Endpoint", backref="service")
|
endpoints = sqlalchemy.orm.relationship("Endpoint", backref="service")
|
||||||
|
|
||||||
|
|
||||||
class Endpoint(sql.ModelBase, sql.DictBase):
|
class Endpoint(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
__tablename__ = 'endpoint'
|
__tablename__ = 'endpoint'
|
||||||
attributes = ['id', 'interface', 'region_id', 'service_id', 'url',
|
attributes = ['id', 'interface', 'region_id', 'service_id', 'url',
|
||||||
'legacy_endpoint_id', 'enabled']
|
'legacy_endpoint_id', 'enabled']
|
||||||
|
@ -123,13 +123,31 @@ class JsonBlob(sql_types.TypeDecorator):
|
|||||||
return jsonutils.loads(value)
|
return jsonutils.loads(value)
|
||||||
|
|
||||||
|
|
||||||
class DictBase(models.ModelBase):
|
class ModelDictMixinWithExtras(models.ModelBase):
|
||||||
|
"""Mixin making model behave with dict-like interfaces includes extras.
|
||||||
|
|
||||||
|
NOTE: DO NOT USE THIS FOR FUTURE SQL MODELS. "Extra" column is a legacy
|
||||||
|
concept that should not be carried forward with new SQL models
|
||||||
|
as the concept of "arbitrary" properties is not in line with
|
||||||
|
the design philosophy of Keystone.
|
||||||
|
"""
|
||||||
|
|
||||||
attributes = []
|
attributes = []
|
||||||
|
_msg = ('Programming Error: Model does not have an "extra" column. '
|
||||||
|
'Unless the model already has an "extra" column and has '
|
||||||
|
'existed in a previous released version of keystone with '
|
||||||
|
'the extra column included, the model should use '
|
||||||
|
'"ModelDictMixin" instead.')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, d):
|
def from_dict(cls, d):
|
||||||
new_d = d.copy()
|
new_d = d.copy()
|
||||||
|
|
||||||
|
if not hasattr(cls, 'extra'):
|
||||||
|
# NOTE(notmorgan): No translation here, This is an error for
|
||||||
|
# programmers NOT end users.
|
||||||
|
raise AttributeError(cls._msg) # no qa
|
||||||
|
|
||||||
new_d['extra'] = {k: new_d.pop(k) for k in d.keys()
|
new_d['extra'] = {k: new_d.pop(k) for k in d.keys()
|
||||||
if k not in cls.attributes and k != 'extra'}
|
if k not in cls.attributes and k != 'extra'}
|
||||||
|
|
||||||
@ -143,6 +161,11 @@ class DictBase(models.ModelBase):
|
|||||||
with a broken implementation.
|
with a broken implementation.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if not hasattr(self, 'extra'):
|
||||||
|
# NOTE(notmorgan): No translation here, This is an error for
|
||||||
|
# programmers NOT end users.
|
||||||
|
raise AttributeError(self._msg) # no qa
|
||||||
|
|
||||||
d = self.extra.copy()
|
d = self.extra.copy()
|
||||||
for attr in self.__class__.attributes:
|
for attr in self.__class__.attributes:
|
||||||
d[attr] = getattr(self, attr)
|
d[attr] = getattr(self, attr)
|
||||||
@ -159,7 +182,7 @@ class DictBase(models.ModelBase):
|
|||||||
return getattr(self, key)
|
return getattr(self, key)
|
||||||
|
|
||||||
|
|
||||||
class ModelDictMixin(object):
|
class ModelDictMixin(models.ModelBase):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, d):
|
def from_dict(cls, d):
|
||||||
|
@ -18,7 +18,7 @@ from keystone.credential.backends import base
|
|||||||
from keystone import exception
|
from keystone import exception
|
||||||
|
|
||||||
|
|
||||||
class CredentialModel(sql.ModelBase, sql.DictBase):
|
class CredentialModel(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
__tablename__ = 'credential'
|
__tablename__ = 'credential'
|
||||||
attributes = [
|
attributes = [
|
||||||
'id', 'user_id', 'project_id', 'encrypted_blob', 'type', 'key_hash'
|
'id', 'user_id', 'project_id', 'encrypted_blob', 'type', 'key_hash'
|
||||||
|
@ -26,7 +26,7 @@ from keystone.i18n import _
|
|||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class FederationProtocolModel(sql.ModelBase, sql.DictBase):
|
class FederationProtocolModel(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'federation_protocol'
|
__tablename__ = 'federation_protocol'
|
||||||
attributes = ['id', 'idp_id', 'mapping_id']
|
attributes = ['id', 'idp_id', 'mapping_id']
|
||||||
mutable_attributes = frozenset(['mapping_id'])
|
mutable_attributes = frozenset(['mapping_id'])
|
||||||
@ -49,7 +49,7 @@ class FederationProtocolModel(sql.ModelBase, sql.DictBase):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class IdentityProviderModel(sql.ModelBase, sql.DictBase):
|
class IdentityProviderModel(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'identity_provider'
|
__tablename__ = 'identity_provider'
|
||||||
attributes = ['id', 'domain_id', 'enabled', 'description', 'remote_ids']
|
attributes = ['id', 'domain_id', 'enabled', 'description', 'remote_ids']
|
||||||
mutable_attributes = frozenset(['description', 'enabled', 'remote_ids'])
|
mutable_attributes = frozenset(['description', 'enabled', 'remote_ids'])
|
||||||
@ -89,7 +89,7 @@ class IdentityProviderModel(sql.ModelBase, sql.DictBase):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class IdPRemoteIdsModel(sql.ModelBase, sql.DictBase):
|
class IdPRemoteIdsModel(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'idp_remote_ids'
|
__tablename__ = 'idp_remote_ids'
|
||||||
attributes = ['idp_id', 'remote_id']
|
attributes = ['idp_id', 'remote_id']
|
||||||
mutable_attributes = frozenset(['idp_id', 'remote_id'])
|
mutable_attributes = frozenset(['idp_id', 'remote_id'])
|
||||||
@ -113,7 +113,7 @@ class IdPRemoteIdsModel(sql.ModelBase, sql.DictBase):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class MappingModel(sql.ModelBase, sql.DictBase):
|
class MappingModel(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'mapping'
|
__tablename__ = 'mapping'
|
||||||
attributes = ['id', 'rules']
|
attributes = ['id', 'rules']
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ class MappingModel(sql.ModelBase, sql.DictBase):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class ServiceProviderModel(sql.ModelBase, sql.DictBase):
|
class ServiceProviderModel(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'service_provider'
|
__tablename__ = 'service_provider'
|
||||||
attributes = ['auth_url', 'id', 'enabled', 'description',
|
attributes = ['auth_url', 'id', 'enabled', 'description',
|
||||||
'relay_state_prefix', 'sp_url']
|
'relay_state_prefix', 'sp_url']
|
||||||
|
@ -28,7 +28,7 @@ from keystone.identity.backends import resource_options as iro
|
|||||||
CONF = keystone.conf.CONF
|
CONF = keystone.conf.CONF
|
||||||
|
|
||||||
|
|
||||||
class User(sql.ModelBase, sql.DictBase):
|
class User(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
__tablename__ = 'user'
|
__tablename__ = 'user'
|
||||||
attributes = ['id', 'name', 'domain_id', 'password', 'enabled',
|
attributes = ['id', 'name', 'domain_id', 'password', 'enabled',
|
||||||
'default_project_id', 'password_expires_at']
|
'default_project_id', 'password_expires_at']
|
||||||
@ -241,7 +241,7 @@ class User(sql.ModelBase, sql.DictBase):
|
|||||||
return user_obj
|
return user_obj
|
||||||
|
|
||||||
|
|
||||||
class LocalUser(sql.ModelBase, sql.DictBase):
|
class LocalUser(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'local_user'
|
__tablename__ = 'local_user'
|
||||||
attributes = ['id', 'user_id', 'domain_id', 'name']
|
attributes = ['id', 'user_id', 'domain_id', 'name']
|
||||||
id = sql.Column(sql.Integer, primary_key=True)
|
id = sql.Column(sql.Integer, primary_key=True)
|
||||||
@ -265,7 +265,7 @@ class LocalUser(sql.ModelBase, sql.DictBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Password(sql.ModelBase, sql.DictBase):
|
class Password(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'password'
|
__tablename__ = 'password'
|
||||||
attributes = ['id', 'local_user_id', 'password', 'created_at',
|
attributes = ['id', 'local_user_id', 'password', 'created_at',
|
||||||
'expires_at']
|
'expires_at']
|
||||||
@ -316,7 +316,7 @@ class NonLocalUser(sql.ModelBase, sql.ModelDictMixin):
|
|||||||
onupdate='CASCADE', ondelete='CASCADE'),)
|
onupdate='CASCADE', ondelete='CASCADE'),)
|
||||||
|
|
||||||
|
|
||||||
class Group(sql.ModelBase, sql.DictBase):
|
class Group(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
__tablename__ = 'group'
|
__tablename__ = 'group'
|
||||||
attributes = ['id', 'name', 'domain_id', 'description']
|
attributes = ['id', 'name', 'domain_id', 'description']
|
||||||
id = sql.Column(sql.String(64), primary_key=True)
|
id = sql.Column(sql.String(64), primary_key=True)
|
||||||
@ -329,7 +329,7 @@ class Group(sql.ModelBase, sql.DictBase):
|
|||||||
__table_args__ = (sql.UniqueConstraint('domain_id', 'name'),)
|
__table_args__ = (sql.UniqueConstraint('domain_id', 'name'),)
|
||||||
|
|
||||||
|
|
||||||
class UserGroupMembership(sql.ModelBase, sql.DictBase):
|
class UserGroupMembership(sql.ModelBase, sql.ModelDictMixin):
|
||||||
"""Group membership join table."""
|
"""Group membership join table."""
|
||||||
|
|
||||||
__tablename__ = 'user_group_membership'
|
__tablename__ = 'user_group_membership'
|
||||||
|
@ -29,7 +29,7 @@ from keystone.oauth1.backends import base
|
|||||||
random = _random.SystemRandom()
|
random = _random.SystemRandom()
|
||||||
|
|
||||||
|
|
||||||
class Consumer(sql.ModelBase, sql.DictBase):
|
class Consumer(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
__tablename__ = 'consumer'
|
__tablename__ = 'consumer'
|
||||||
attributes = ['id', 'description', 'secret']
|
attributes = ['id', 'description', 'secret']
|
||||||
id = sql.Column(sql.String(64), primary_key=True, nullable=False)
|
id = sql.Column(sql.String(64), primary_key=True, nullable=False)
|
||||||
@ -38,7 +38,7 @@ class Consumer(sql.ModelBase, sql.DictBase):
|
|||||||
extra = sql.Column(sql.JsonBlob(), nullable=False)
|
extra = sql.Column(sql.JsonBlob(), nullable=False)
|
||||||
|
|
||||||
|
|
||||||
class RequestToken(sql.ModelBase, sql.DictBase):
|
class RequestToken(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'request_token'
|
__tablename__ = 'request_token'
|
||||||
attributes = ['id', 'request_secret',
|
attributes = ['id', 'request_secret',
|
||||||
'verifier', 'authorizing_user_id', 'requested_project_id',
|
'verifier', 'authorizing_user_id', 'requested_project_id',
|
||||||
@ -61,7 +61,7 @@ class RequestToken(sql.ModelBase, sql.DictBase):
|
|||||||
return dict(self.items())
|
return dict(self.items())
|
||||||
|
|
||||||
|
|
||||||
class AccessToken(sql.ModelBase, sql.DictBase):
|
class AccessToken(sql.ModelBase, sql.ModelDictMixin):
|
||||||
__tablename__ = 'access_token'
|
__tablename__ = 'access_token'
|
||||||
attributes = ['id', 'access_secret', 'authorizing_user_id',
|
attributes = ['id', 'access_secret', 'authorizing_user_id',
|
||||||
'project_id', 'role_ids', 'consumer_id',
|
'project_id', 'role_ids', 'consumer_id',
|
||||||
|
@ -17,7 +17,7 @@ from keystone import exception
|
|||||||
from keystone.policy.backends import rules
|
from keystone.policy.backends import rules
|
||||||
|
|
||||||
|
|
||||||
class PolicyModel(sql.ModelBase, sql.DictBase):
|
class PolicyModel(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
__tablename__ = 'policy'
|
__tablename__ = 'policy'
|
||||||
attributes = ['id', 'blob', 'type']
|
attributes = ['id', 'blob', 'type']
|
||||||
id = sql.Column(sql.String(64), primary_key=True)
|
id = sql.Column(sql.String(64), primary_key=True)
|
||||||
|
@ -218,7 +218,7 @@ class Resource(base.ResourceDriverBase):
|
|||||||
query.delete(synchronize_session=False)
|
query.delete(synchronize_session=False)
|
||||||
|
|
||||||
|
|
||||||
class Project(sql.ModelBase, sql.DictBase):
|
class Project(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
# NOTE(henry-nash): From the manager and above perspective, the domain_id
|
# NOTE(henry-nash): From the manager and above perspective, the domain_id
|
||||||
# is nullable. However, to ensure uniqueness in multi-process
|
# is nullable. However, to ensure uniqueness in multi-process
|
||||||
# configurations, it is better to still use the sql uniqueness constraint.
|
# configurations, it is better to still use the sql uniqueness constraint.
|
||||||
|
@ -30,7 +30,7 @@ CONF = keystone.conf.CONF
|
|||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class TokenModel(sql.ModelBase, sql.DictBase):
|
class TokenModel(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
__tablename__ = 'token'
|
__tablename__ = 'token'
|
||||||
attributes = ['id', 'expires', 'user_id', 'trust_id']
|
attributes = ['id', 'expires', 'user_id', 'trust_id']
|
||||||
id = sql.Column(sql.String(64), primary_key=True)
|
id = sql.Column(sql.String(64), primary_key=True)
|
||||||
|
@ -25,7 +25,7 @@ from keystone.trust.backends import base
|
|||||||
MAXIMUM_CONSUME_ATTEMPTS = 10
|
MAXIMUM_CONSUME_ATTEMPTS = 10
|
||||||
|
|
||||||
|
|
||||||
class TrustModel(sql.ModelBase, sql.DictBase):
|
class TrustModel(sql.ModelBase, sql.ModelDictMixinWithExtras):
|
||||||
__tablename__ = 'trust'
|
__tablename__ = 'trust'
|
||||||
attributes = ['id', 'trustor_user_id', 'trustee_user_id',
|
attributes = ['id', 'trustor_user_id', 'trustee_user_id',
|
||||||
'project_id', 'impersonation', 'expires_at',
|
'project_id', 'impersonation', 'expires_at',
|
||||||
|
Loading…
Reference in New Issue
Block a user