Revise trust middleware

This patch revises the trust middleware to use the engine RPC interface
instead of the DB APIs.

Change-Id: I7838b68ef87ad5d470727586f4cf2b1edb7069ed
This commit is contained in:
tengqm 2016-03-12 06:52:23 -05:00
parent 043b53735b
commit 2b9f9141c7
2 changed files with 189 additions and 58 deletions

View File

@ -13,30 +13,31 @@
from senlin.api.common import wsgi
from senlin.common import context
from senlin.common import exception
from senlin.db import api as db_api
from senlin.drivers import base as driver_base
from senlin.rpc import client as rpc
class TrustMiddleware(wsgi.Middleware):
'''Extract trust info from request.
"""Extract trust info from request.
The extracted information is filled into the request context.
Senlin engine will use this information for access control.
'''
"""
def _get_trust(self, ctx):
'''List trusts with current user as the trustor.'''
"""List trusts with current user as the trustor.
:param ctx: The requesting context.
:return: ID of the trust or exception of InternalError.
"""
rpcc = rpc.EngineClient()
# DB table is used as a cache for the trusts.
cred_exists = False
res = db_api.cred_get(ctx, ctx.user, ctx.project)
if res is not None:
try:
trust_id = res.cred['openstack']['trust']
res = rpcc.credential_get(ctx)
if res:
trust_id = res.get('trust', None)
if trust_id:
return trust_id
except KeyError:
# Garbage in the store, ignore it
cred_exists = True
pass
cred_exists = True
params = {
'auth_url': ctx.auth_url,
@ -60,15 +61,9 @@ class TrustMiddleware(wsgi.Middleware):
# update cache
if cred_exists:
db_api.cred_update(ctx.user, ctx.project,
{'cred': {'openstack': {'trust': trust.id}}})
rpcc.credential_update(ctx, trust.id)
else:
values = {
'user': ctx.user,
'project': ctx.project,
'cred': {'openstack': {'trust': trust.id}}
}
db_api.cred_create(ctx, values)
rpcc.credential_create(ctx, trust.id)
return trust.id

View File

@ -11,12 +11,11 @@
# under the License.
import mock
import six
from senlin.api.middleware import trust
from senlin.common import context
from senlin.common import exception
from senlin.db import api as db_api
from senlin.drivers import base as driver_base
from senlin.tests.unit.common import base
from senlin.tests.unit.common import utils
@ -28,40 +27,177 @@ class TestTrustMiddleware(base.SenlinTestCase):
self.context = utils.dummy_context()
self.middleware = trust.TrustMiddleware(None)
@mock.patch('senlin.db.api')
def test_get_trust_already_exists(self, mock_db_api):
res = mock.MagicMock()
res.cred = {}
res.cred['openstack'] = {}
res.cred['openstack']['trust'] = 'FAKE_TRUST_ID'
db_api.cred_get = mock.MagicMock(return_value=res)
trust_id = self.middleware._get_trust(self.context)
self.assertEqual(res.cred['openstack']['trust'], trust_id)
self.assertTrue(db_api.cred_get.called)
@mock.patch("senlin.rpc.client.EngineClient")
def test__get_trust_already_exists(self, mock_rpc):
x_cred = {'trust': 'FAKE_TRUST_ID'}
x_rpc = mock.Mock()
x_rpc.credential_get.return_value = x_cred
mock_rpc.return_value = x_rpc
@mock.patch.object(context, 'get_service_context')
@mock.patch.object(db_api, 'cred_get')
@mock.patch.object(db_api, 'cred_create')
@mock.patch.object(driver_base, 'SenlinDriver')
def test_get_trust_not_exists(self, mock_senlindriver, mock_cred_create,
mock_cred_get, mock_get_service_context):
mock_cred_get.return_value = None
mock_get_service_context.return_value = {'k1': 'v1', 'k2': 'v2'}
sd = mock.Mock()
kc = mock.Mock()
sd.identity.return_value = kc
mock_senlindriver.return_value = sd
kc.get_user_id.return_value = 'FAKE_ADMIN_ID'
kc.trust_get_by_trustor.side_effect = exception.InternalError(
code=400, message='Bad request')
trust = mock.Mock()
kc.trust_create.return_value = trust
trust.id = 'FAKE_TRUST_ID'
result = self.middleware._get_trust(self.context)
trust_id = self.middleware._get_trust(self.context)
self.assertEqual(trust_id, 'FAKE_TRUST_ID')
self.assertTrue(db_api.cred_get.called)
self.assertTrue(kc.get_user_id.called)
self.assertTrue(kc.trust_get_by_trustor.called)
self.assertTrue(kc.trust_create.called)
self.assertTrue(db_api.cred_create.called)
self.assertEqual('FAKE_TRUST_ID', result)
mock_rpc.assert_called_once_with()
x_rpc.credential_get.assert_called_once_with(self.context)
@mock.patch.object(context, "get_service_context")
@mock.patch("senlin.drivers.base.SenlinDriver")
@mock.patch("senlin.rpc.client.EngineClient")
def test__get_trust_bad(self, mock_rpc, mock_driver, mock_context):
x_cred = {'foo': 'bar'}
x_rpc = mock.Mock()
x_rpc.credential_get.return_value = x_cred
mock_rpc.return_value = x_rpc
x_svc_cred = {'uid': 'FAKE_ID', 'passwd': 'FAKE_PASS'}
mock_context.return_value = x_svc_cred
x_admin_id = 'FAKE_ADMIN_ID'
x_trust = mock.Mock(id='FAKE_TRUST_ID')
mock_keystone = mock.Mock()
mock_keystone.get_user_id.return_value = x_admin_id
mock_keystone.trust_get_by_trustor.return_value = x_trust
x_driver = mock.Mock()
x_driver.identity.return_value = mock_keystone
mock_driver.return_value = x_driver
result = self.middleware._get_trust(self.context)
self.assertEqual('FAKE_TRUST_ID', result)
mock_rpc.assert_called_once_with()
x_rpc.credential_get.assert_called_once_with(self.context)
mock_driver.assert_called_once_with()
x_driver.identity.assert_called_once_with({
'auth_url': self.context.auth_url,
'project_id': self.context.project,
'user_id': self.context.user,
'token': self.context.auth_token,
})
mock_context.assert_called_once_with()
mock_keystone.get_user_id.assert_called_once_with(
uid='FAKE_ID', passwd='FAKE_PASS')
mock_keystone.trust_get_by_trustor.assert_called_once_with(
self.context.user, 'FAKE_ADMIN_ID', self.context.project)
x_rpc.credential_update.assert_called_once_with(
self.context, 'FAKE_TRUST_ID')
@mock.patch.object(context, "get_service_context")
@mock.patch("senlin.drivers.base.SenlinDriver")
@mock.patch("senlin.rpc.client.EngineClient")
def test__get_trust_not_found(self, mock_rpc, mock_driver, mock_context):
x_rpc = mock.Mock()
x_rpc.credential_get.return_value = None
mock_rpc.return_value = x_rpc
x_svc_cred = {'uid': 'FAKE_ID', 'passwd': 'FAKE_PASS'}
mock_context.return_value = x_svc_cred
x_admin_id = 'FAKE_ADMIN_ID'
x_trust = mock.Mock(id='FAKE_TRUST_ID')
mock_keystone = mock.Mock()
mock_keystone.get_user_id.return_value = x_admin_id
mock_keystone.trust_get_by_trustor.return_value = x_trust
x_driver = mock.Mock()
x_driver.identity.return_value = mock_keystone
mock_driver.return_value = x_driver
result = self.middleware._get_trust(self.context)
self.assertEqual('FAKE_TRUST_ID', result)
mock_rpc.assert_called_once_with()
x_rpc.credential_get.assert_called_once_with(self.context)
mock_driver.assert_called_once_with()
x_driver.identity.assert_called_once_with({
'auth_url': self.context.auth_url,
'project_id': self.context.project,
'user_id': self.context.user,
'token': self.context.auth_token,
})
mock_context.assert_called_once_with()
mock_keystone.get_user_id.assert_called_once_with(
uid='FAKE_ID', passwd='FAKE_PASS')
mock_keystone.trust_get_by_trustor.assert_called_once_with(
self.context.user, 'FAKE_ADMIN_ID', self.context.project)
x_rpc.credential_create.assert_called_once_with(
self.context, 'FAKE_TRUST_ID')
@mock.patch.object(context, "get_service_context")
@mock.patch("senlin.drivers.base.SenlinDriver")
@mock.patch("senlin.rpc.client.EngineClient")
def test__get_trust_do_create(self, mock_rpc, mock_driver, mock_context):
x_rpc = mock.Mock()
x_rpc.credential_get.return_value = None
mock_rpc.return_value = x_rpc
x_svc_cred = {'uid': 'FAKE_ID', 'passwd': 'FAKE_PASS'}
mock_context.return_value = x_svc_cred
x_admin_id = 'FAKE_ADMIN_ID'
mock_keystone = mock.Mock()
mock_keystone.get_user_id.return_value = x_admin_id
x_trust = mock.Mock(id='FAKE_TRUST_ID')
mock_keystone.trust_create.return_value = x_trust
err = exception.InternalError(code=400, message='Boom')
mock_keystone.trust_get_by_trustor.side_effect = err
x_driver = mock.Mock()
x_driver.identity.return_value = mock_keystone
mock_driver.return_value = x_driver
result = self.middleware._get_trust(self.context)
self.assertEqual('FAKE_TRUST_ID', result)
mock_rpc.assert_called_once_with()
x_rpc.credential_get.assert_called_once_with(self.context)
mock_driver.assert_called_once_with()
x_driver.identity.assert_called_once_with({
'auth_url': self.context.auth_url,
'project_id': self.context.project,
'user_id': self.context.user,
'token': self.context.auth_token,
})
mock_context.assert_called_once_with()
mock_keystone.get_user_id.assert_called_once_with(
uid='FAKE_ID', passwd='FAKE_PASS')
mock_keystone.trust_get_by_trustor.assert_called_once_with(
self.context.user, 'FAKE_ADMIN_ID', self.context.project)
mock_keystone.trust_create.assert_called_once_with(
self.context.user, 'FAKE_ADMIN_ID', self.context.project,
self.context.roles)
x_rpc.credential_create.assert_called_once_with(
self.context, 'FAKE_TRUST_ID')
@mock.patch.object(context, "get_service_context")
@mock.patch("senlin.drivers.base.SenlinDriver")
@mock.patch("senlin.rpc.client.EngineClient")
def test__get_trust_fatal(self, mock_rpc, mock_driver, mock_context):
x_rpc = mock.Mock()
x_rpc.credential_get.return_value = None
mock_rpc.return_value = x_rpc
x_svc_cred = {'uid': 'FAKE_ID', 'passwd': 'FAKE_PASS'}
mock_context.return_value = x_svc_cred
x_admin_id = 'FAKE_ADMIN_ID'
mock_keystone = mock.Mock()
mock_keystone.get_user_id.return_value = x_admin_id
err = exception.InternalError(code=500, message='Boom')
mock_keystone.trust_get_by_trustor.side_effect = err
x_driver = mock.Mock()
x_driver.identity.return_value = mock_keystone
mock_driver.return_value = x_driver
ex = self.assertRaises(exception.InternalError,
self.middleware._get_trust,
self.context)
self.assertEqual('Boom', six.text_type(ex))
mock_rpc.assert_called_once_with()
x_rpc.credential_get.assert_called_once_with(self.context)
mock_driver.assert_called_once_with()
x_driver.identity.assert_called_once_with({
'auth_url': self.context.auth_url,
'project_id': self.context.project,
'user_id': self.context.user,
'token': self.context.auth_token,
})
mock_context.assert_called_once_with()
mock_keystone.get_user_id.assert_called_once_with(
uid='FAKE_ID', passwd='FAKE_PASS')
mock_keystone.trust_get_by_trustor.assert_called_once_with(
self.context.user, 'FAKE_ADMIN_ID', self.context.project)