Create V9 Role Driver
In preparation for new role driver methods for implied roles, this patch creates a new version of the role driver. Partially Implements@ blueprint implied-roles Change-Id: I00cc57a77a23ed30d86fce8e309f6b27c4ae26a1
This commit is contained in:
parent
8913cd8299
commit
3f888260a7
0
keystone/assignment/V8_role_backends/__init__.py
Normal file
0
keystone/assignment/V8_role_backends/__init__.py
Normal file
80
keystone/assignment/V8_role_backends/sql.py
Normal file
80
keystone/assignment/V8_role_backends/sql.py
Normal file
@ -0,0 +1,80 @@
|
||||
# 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.
|
||||
|
||||
from keystone import assignment
|
||||
from keystone.common import sql
|
||||
from keystone import exception
|
||||
|
||||
|
||||
class Role(assignment.RoleDriverV8):
|
||||
|
||||
@sql.handle_conflicts(conflict_type='role')
|
||||
def create_role(self, role_id, role):
|
||||
with sql.transaction() as session:
|
||||
ref = RoleTable.from_dict(role)
|
||||
session.add(ref)
|
||||
return ref.to_dict()
|
||||
|
||||
@sql.truncated
|
||||
def list_roles(self, hints):
|
||||
with sql.transaction() as session:
|
||||
query = session.query(RoleTable)
|
||||
refs = sql.filter_limit_query(RoleTable, query, hints)
|
||||
return [ref.to_dict() for ref in refs]
|
||||
|
||||
def list_roles_from_ids(self, ids):
|
||||
if not ids:
|
||||
return []
|
||||
else:
|
||||
with sql.transaction() as session:
|
||||
query = session.query(RoleTable)
|
||||
query = query.filter(RoleTable.id.in_(ids))
|
||||
role_refs = query.all()
|
||||
return [role_ref.to_dict() for role_ref in role_refs]
|
||||
|
||||
def _get_role(self, session, role_id):
|
||||
ref = session.query(RoleTable).get(role_id)
|
||||
if ref is None:
|
||||
raise exception.RoleNotFound(role_id=role_id)
|
||||
return ref
|
||||
|
||||
def get_role(self, role_id):
|
||||
with sql.transaction() as session:
|
||||
return self._get_role(session, role_id).to_dict()
|
||||
|
||||
@sql.handle_conflicts(conflict_type='role')
|
||||
def update_role(self, role_id, role):
|
||||
with sql.transaction() as session:
|
||||
ref = self._get_role(session, role_id)
|
||||
old_dict = ref.to_dict()
|
||||
for k in role:
|
||||
old_dict[k] = role[k]
|
||||
new_role = RoleTable.from_dict(old_dict)
|
||||
for attr in RoleTable.attributes:
|
||||
if attr != 'id':
|
||||
setattr(ref, attr, getattr(new_role, attr))
|
||||
ref.extra = new_role.extra
|
||||
return ref.to_dict()
|
||||
|
||||
def delete_role(self, role_id):
|
||||
with sql.transaction() as session:
|
||||
ref = self._get_role(session, role_id)
|
||||
session.delete(ref)
|
||||
|
||||
|
||||
class RoleTable(sql.ModelBase, sql.DictBase):
|
||||
__tablename__ = 'role'
|
||||
attributes = ['id', 'name']
|
||||
id = sql.Column(sql.String(64), primary_key=True)
|
||||
name = sql.Column(sql.String(255), unique=True, nullable=False)
|
||||
extra = sql.Column(sql.JsonBlob())
|
||||
__table_args__ = (sql.UniqueConstraint('name'), {})
|
@ -1329,6 +1329,13 @@ class RoleManager(manager.Manager):
|
||||
|
||||
super(RoleManager, self).__init__(role_driver)
|
||||
|
||||
# Make sure it is a driver version we support, and if it is a legacy
|
||||
# driver, then wrap it.
|
||||
if isinstance(self.driver, RoleDriverV8):
|
||||
self.driver = V9RoleWrapperForV8Driver(self.driver)
|
||||
elif not isinstance(self.driver, RoleDriverV9):
|
||||
raise exception.UnsupportedDriverVersion(driver=role_driver)
|
||||
|
||||
@MEMOIZE
|
||||
def get_role(self, role_id):
|
||||
return self.driver.get_role(role_id)
|
||||
@ -1358,8 +1365,15 @@ class RoleManager(manager.Manager):
|
||||
self.get_role.invalidate(self, role_id)
|
||||
|
||||
|
||||
# The RoleDriverBase class is the set of driver methods from earlier
|
||||
# drivers that we still support, that have not been removed or modified. This
|
||||
# class is then used to created the augmented V8 and V9 version abstract driver
|
||||
# classes, without having to duplicate a lot of abstract method signatures.
|
||||
# If you remove a method from V9, then move the abstact methods from this Base
|
||||
# class to the V8 class. Do not modify any of the method signatures in the Base
|
||||
# class - changes should only be made in the V8 and subsequent classes.
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class RoleDriverV8(object):
|
||||
class RoleDriverBase(object):
|
||||
|
||||
def _get_list_limit(self):
|
||||
return CONF.role.list_limit or CONF.list_limit
|
||||
@ -1429,4 +1443,77 @@ class RoleDriverV8(object):
|
||||
raise exception.NotImplemented() # pragma: no cover
|
||||
|
||||
|
||||
class RoleDriverV8(RoleDriverBase):
|
||||
"""Removed or redefined methods from V8.
|
||||
|
||||
Move the abstract methods of any methods removed or modified in later
|
||||
versions of the driver from RoleDriverBase to here. We maintain this
|
||||
so that legacy drivers, which will be a subclass of RoleDriverV8, can
|
||||
still reference them.
|
||||
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class RoleDriverV9(RoleDriverBase):
|
||||
"""New or redefined methods from V8.
|
||||
|
||||
Add any new V9 abstract methods (or those with modified signatures) to
|
||||
this class.
|
||||
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class V9RoleWrapperForV8Driver(RoleDriverV9):
|
||||
"""Wrapper class to supported a V8 legacy driver.
|
||||
|
||||
In order to support legacy drivers without having to make the manager code
|
||||
driver-version aware, we wrap legacy drivers so that they look like the
|
||||
latest version. For the various changes made in a new driver, here are the
|
||||
actions needed in this wrapper:
|
||||
|
||||
Method removed from new driver - remove the call-through method from this
|
||||
class, since the manager will no longer be
|
||||
calling it.
|
||||
Method signature (or meaning) changed - wrap the old method in a new
|
||||
signature here, and munge the input
|
||||
and output parameters accordingly.
|
||||
New method added to new driver - add a method to implement the new
|
||||
functionality here if possible. If that is
|
||||
not possible, then return NotImplemented,
|
||||
since we do not guarantee to support new
|
||||
functionality with legacy drivers.
|
||||
|
||||
"""
|
||||
|
||||
@versionutils.deprecated(
|
||||
as_of=versionutils.deprecated.MITAKA,
|
||||
what='keystone.assignment.RoleDriverV8',
|
||||
in_favor_of='keystone.assignment.RoleDriverV9',
|
||||
remove_in=+2)
|
||||
def __init__(self, wrapped_driver):
|
||||
self.driver = wrapped_driver
|
||||
|
||||
def create_role(self, role_id, role):
|
||||
return self.driver.create_role(role_id, role)
|
||||
|
||||
def list_roles(self, hints):
|
||||
return self.driver.list_roles(hints)
|
||||
|
||||
def list_roles_from_ids(self, role_ids):
|
||||
return self.driver.list_roles_from_ids(role_ids)
|
||||
|
||||
def get_role(self, role_id):
|
||||
return self.driver.get_role(role_id)
|
||||
|
||||
def update_role(self, role_id, role):
|
||||
return self.driver.update_role(role_id, role)
|
||||
|
||||
def delete_role(self, role_id):
|
||||
self.driver.delete_role(role_id)
|
||||
|
||||
|
||||
RoleDriver = manager.create_legacy_driver(RoleDriverV8)
|
||||
|
@ -15,7 +15,7 @@ from keystone.common import sql
|
||||
from keystone import exception
|
||||
|
||||
|
||||
class Role(assignment.RoleDriverV8):
|
||||
class Role(assignment.RoleDriverV9):
|
||||
|
||||
@sql.handle_conflicts(conflict_type='role')
|
||||
def create_role(self, role_id, role):
|
||||
|
30
keystone/tests/unit/backend/legacy_drivers/role/V8/sql.py
Normal file
30
keystone/tests/unit/backend/legacy_drivers/role/V8/sql.py
Normal file
@ -0,0 +1,30 @@
|
||||
# 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.
|
||||
|
||||
from keystone.tests.unit import test_backend_sql
|
||||
|
||||
|
||||
class SqlIdentityV8(test_backend_sql.SqlIdentity):
|
||||
"""Test that a V8 driver still passes the same tests.
|
||||
|
||||
We use the SQL driver as an example of a V8 legacy driver.
|
||||
|
||||
"""
|
||||
|
||||
def config_overrides(self):
|
||||
super(SqlIdentityV8, self).config_overrides()
|
||||
# V8 SQL specific driver overrides
|
||||
self.config_fixture.config(
|
||||
group='role',
|
||||
driver='keystone.assignment.V8_role_backends.sql.Role')
|
||||
self.use_specific_sql_driver_version(
|
||||
'keystone.assignment', 'role_backends', 'V8_')
|
10
releasenotes/notes/Role_V9_driver-971c3aae14d9963d.yaml
Normal file
10
releasenotes/notes/Role_V9_driver-971c3aae14d9963d.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
prelude: >
|
||||
New Role driver (V9)
|
||||
upgrade:
|
||||
- The V8 Role driver interface is deprecated, but still supported in
|
||||
this release, so any custom drivers based on the V8 interface should still
|
||||
work.
|
||||
other:
|
||||
- Support for the V8 Role driver interface is planned to be removed in
|
||||
the 'O' release of OpenStack.
|
3
tox.ini
3
tox.ini
@ -75,8 +75,11 @@ deps = -r{toxinidir}/test-requirements.txt
|
||||
nose
|
||||
.[ldap,memcache,mongodb]
|
||||
commands =
|
||||
# Run each legacy test separately, to avoid SQL model redefinitions
|
||||
nosetests -v \
|
||||
keystone/tests/unit/backend/legacy_drivers/assignment/V8/sql.py
|
||||
nosetests -v \
|
||||
keystone/tests/unit/backend/legacy_drivers/role/V8/sql.py
|
||||
|
||||
[testenv:pep8]
|
||||
commands =
|
||||
|
Loading…
x
Reference in New Issue
Block a user