Return support status in profile/policy type list

This patch enables senlin engine/api to return support status of profile
and policy types. This feature needs to be enabled by API micro-version
1.5.

Change-Id: I2f84d5292e7625affe060e8e4e20d821cde7e417
This commit is contained in:
tengqm 2017-01-08 20:31:53 -05:00
parent c28cfcc3df
commit c17500ace7
7 changed files with 186 additions and 32 deletions

View File

@ -15,6 +15,7 @@ Policy type endpoint for Senlin v1 ReST API.
"""
from senlin.api.common import util
from senlin.api.common import version_request as vr
from senlin.api.common import wsgi
@ -30,7 +31,12 @@ class PolicyTypeController(wsgi.Controller):
obj = util.parse_request('PolicyTypeListRequest', req, {})
types = self.rpc_client.call(req.context, 'policy_type_list', obj)
return {'policy_types': types}
result = types
if req.version_request <= vr.APIVersionRequest("1.4"):
# we return only policy name before microversion 1.5
result = [{'name': '-'.join((t['name'], t['version']))}
for t in types]
return {'policy_types': result}
@util.policy_enforce
def get(self, req, type_name):

View File

@ -15,6 +15,7 @@ Profile type endpoint for Senlin v1 ReST API.
"""
from senlin.api.common import util
from senlin.api.common import version_request as vr
from senlin.api.common import wsgi
@ -29,7 +30,12 @@ class ProfileTypeController(wsgi.Controller):
obj = util.parse_request('ProfileTypeListRequest', req, {})
types = self.rpc_client.call(req.context, 'profile_type_list', obj)
return {'profile_types': types}
result = types
if req.version_request <= vr.APIVersionRequest("1.4"):
# We return only profile type name before 1.5
result = [{'name': '-'.join((t['name'], t['version']))}
for t in types]
return {'profile_types': result}
@util.policy_enforce
def get(self, req, type_name):

View File

@ -133,4 +133,11 @@ class Registry(object):
def get_types(self):
'''Return a list of valid plugin types.'''
return [{'name': name} for name in self._registry.keys()]
return [
{
'name': name.split('-')[0] if '-' in name else name,
'version': name.split('-')[1] if '-' in name else '',
'support_status': pi.plugin.VERSIONS
}
for name, pi in self._registry.items()
]

View File

@ -37,12 +37,72 @@ class PolicyTypeControllerTest(shared.ControllerTest, base.SenlinTestCase):
@mock.patch.object(util, 'parse_request')
@mock.patch.object(rpc_client.EngineClient, 'call')
def test_policy_type_list(self, mock_call, mock_parse, mock_enforce):
def test_list(self, mock_call, mock_parse, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
req = self._get('/policy_types')
engine_response = [{'name': 'os.heat.stack'},
{'name': 'os.nova.server'}]
engine_response = [
{'name': 'senlin.policy.p1', 'version': '1.0', 'attr': 'v1'},
{'name': 'senlin.policy.p2', 'version': '1.0', 'attr': 'v2'}
]
mock_call.return_value = engine_response
obj = mock.Mock()
mock_parse.return_value = obj
response = self.controller.index(req)
self.assertEqual(
[
{'name': 'senlin.policy.p1-1.0'},
{'name': 'senlin.policy.p2-1.0'},
],
response['policy_types']
)
mock_parse.assert_called_once_with(
'PolicyTypeListRequest', req, {})
mock_call.assert_called_once_with(
req.context, 'policy_type_list', mock.ANY)
@mock.patch.object(util, 'parse_request')
@mock.patch.object(rpc_client.EngineClient, 'call')
def test_list_old_version(self, mock_call, mock_parse, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
req = self._get('/policy_types', version='1.3')
engine_response = [
{'name': 'senlin.policy.p1', 'version': '1.0'},
{'name': 'senlin.policy.p2', 'version': '1.1'}
]
mock_call.return_value = engine_response
obj = mock.Mock()
mock_parse.return_value = obj
response = self.controller.index(req)
self.assertEqual(
[
{'name': 'senlin.policy.p1-1.0'},
{'name': 'senlin.policy.p2-1.1'}
],
response['policy_types']
)
mock_parse.assert_called_once_with(
'PolicyTypeListRequest', req, {})
mock_call.assert_called_once_with(
req.context, 'policy_type_list', mock.ANY)
@mock.patch.object(util, 'parse_request')
@mock.patch.object(rpc_client.EngineClient, 'call')
def test_list_new_version(self, mock_call, mock_parse, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
req = self._get('/policy_types', version='1.5')
engine_response = [
{'name': 'senlin.policy.p1', 'version': '1.0', 'a1': 'v1'},
{'name': 'senlin.policy.p2', 'version': '1.1', 'a2': 'v2'}
]
mock_call.return_value = engine_response
obj = mock.Mock()
@ -56,7 +116,7 @@ class PolicyTypeControllerTest(shared.ControllerTest, base.SenlinTestCase):
mock_call.assert_called_once_with(
req.context, 'policy_type_list', mock.ANY)
def test_policy_type_list_err_denied_policy(self, mock_enforce):
def test_list_err_denied_policy(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', False)
req = self._get('/policy_types')
resp = shared.request_with_middleware(fault.FaultWrapper,

View File

@ -37,12 +37,63 @@ class ProfileTypeControllerTest(shared.ControllerTest, base.SenlinTestCase):
@mock.patch.object(util, 'parse_request')
@mock.patch.object(rpc_client.EngineClient, 'call')
def test_profile_type_list(self, mock_call, mock_parse, mock_enforce):
def test_list(self, mock_call, mock_parse, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
req = self._get('/profile_types')
engine_response = [{'name': 'os.heat.stack'},
{'name': 'os.nova.server'}]
engine_response = [
{'name': 'os.heat.stack', 'version': '1.0'},
{'name': 'os.nova.server', 'version': '1.0'}
]
mock_call.return_value = engine_response
obj = mock.Mock()
mock_parse.return_value = obj
response = self.controller.index(req)
self.assertEqual(
[{'name': 'os.heat.stack-1.0'}, {'name': 'os.nova.server-1.0'}],
response['profile_types'])
mock_parse.assert_called_once_with('ProfileTypeListRequest', req, {})
mock_call.assert_called_once_with(
req.context, 'profile_type_list', mock.ANY)
@mock.patch.object(util, 'parse_request')
@mock.patch.object(rpc_client.EngineClient, 'call')
def test_list_old_version(self, mock_call, mock_parse, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
req = self._get('/profile_types', version='1.3')
engine_response = [
{'name': 'os.heat.stack', 'version': '1.0', 'attr': 'bar'},
{'name': 'os.nova.server', 'version': '1.0', 'attr': 'foo'},
]
mock_call.return_value = engine_response
obj = mock.Mock()
mock_parse.return_value = obj
response = self.controller.index(req)
self.assertEqual(
[{'name': 'os.heat.stack-1.0'}, {'name': 'os.nova.server-1.0'}],
response['profile_types']
)
mock_parse.assert_called_once_with('ProfileTypeListRequest', req, {})
mock_call.assert_called_once_with(
req.context, 'profile_type_list', mock.ANY)
@mock.patch.object(util, 'parse_request')
@mock.patch.object(rpc_client.EngineClient, 'call')
def test_list_new_version(self, mock_call, mock_parse, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
req = self._get('/profile_types', version='1.5')
engine_response = [
{'name': 'os.heat.stack', 'version': '1.0', 'attr': 'bar'},
{'name': 'os.nova.server', 'version': '1.0', 'attr': 'foo'},
]
mock_call.return_value = engine_response
obj = mock.Mock()

View File

@ -177,14 +177,18 @@ class TestEnvironment(base.SenlinTestCase):
def test_get_profile_types(self):
env = environment.Environment()
plugin1 = mock.Mock()
env.register_profile('foo', plugin1)
plugin2 = mock.Mock()
env.register_profile('bar', plugin2)
plugin1 = mock.Mock(VERSIONS={'k': 'v'})
env.register_profile('foo-1.0', plugin1)
plugin2 = mock.Mock(VERSIONS={'k': 'v1'})
env.register_profile('bar-1.2', plugin2)
actual = env.get_profile_types()
self.assertIn({'name': 'foo'}, actual)
self.assertIn({'name': 'bar'}, actual)
self.assertIn(
{'name': 'foo', 'version': '1.0', 'support_status': {'k': 'v'}},
actual)
self.assertIn(
{'name': 'bar', 'version': '1.2', 'support_status': {'k': 'v1'}},
actual)
def test_register_and_get_policy(self):
plugin = mock.Mock()
@ -200,14 +204,18 @@ class TestEnvironment(base.SenlinTestCase):
def test_get_policy_types(self):
env = environment.Environment()
plugin1 = mock.Mock()
env.register_policy('foo', plugin1)
plugin2 = mock.Mock()
env.register_policy('bar', plugin2)
plugin1 = mock.Mock(VERSIONS={'k': 'v'})
env.register_policy('foo-0.1', plugin1)
plugin2 = mock.Mock(VERSIONS={'k': 'v1'})
env.register_policy('bar-0.2', plugin2)
actual = env.get_policy_types()
self.assertIn({'name': 'foo'}, actual)
self.assertIn({'name': 'bar'}, actual)
self.assertIn(
{'name': 'foo', 'version': '0.1', 'support_status': {'k': 'v'}},
actual)
self.assertIn(
{'name': 'bar', 'version': '0.2', 'support_status': {'k': 'v1'}},
actual)
def test_register_and_get_driver_types(self):
plugin = mock.Mock()
@ -223,14 +231,18 @@ class TestEnvironment(base.SenlinTestCase):
def test_get_driver_types(self):
env = environment.Environment()
plugin1 = mock.Mock()
plugin1 = mock.Mock(VERSIONS={})
env.register_driver('foo', plugin1)
plugin2 = mock.Mock()
plugin2 = mock.Mock(VERSIONS={})
env.register_driver('bar', plugin2)
actual = env.get_driver_types()
self.assertIn({'name': 'foo'}, actual)
self.assertIn({'name': 'bar'}, actual)
self.assertIn(
{'name': 'foo', 'version': '', 'support_status': {}},
actual)
self.assertIn(
{'name': 'bar', 'version': '', 'support_status': {}},
actual)
def test_read_global_environment(self):
mock_dir = self.patchobject(glob, 'glob')

View File

@ -200,10 +200,22 @@ class RegistryTest(base.SenlinTestCase):
def test_get_types(self):
reg = registry.Registry('GLOBAL', None)
plugin1 = mock.Mock()
reg.register_plugin('FOO', plugin1)
plugin2 = mock.Mock()
reg.register_plugin('BAR', plugin2)
plugin1 = mock.Mock(VERSIONS={'foo': 'bar'})
reg.register_plugin('FOO-1.0', plugin1)
plugin2 = mock.Mock(VERSIONS={'zoo': 'car'})
reg.register_plugin('BAR-1.1', plugin2)
self.assertIn({'name': 'FOO'}, reg.get_types())
self.assertIn({'name': 'BAR'}, reg.get_types())
self.assertIn(
{
'name': 'FOO',
'version': '1.0',
'support_status': {'foo': 'bar'}
},
reg.get_types())
self.assertIn(
{
'name': 'BAR',
'version': '1.1',
'support_status': {'zoo': 'car'}
},
reg.get_types())