From 1cb1c00fb636c89fbefcc56e60ed9fcbd25810e6 Mon Sep 17 00:00:00 2001 From: Julia Varlamova Date: Wed, 20 Nov 2013 17:27:42 +0400 Subject: [PATCH] Filter resource types by support status Now heat resources haven't support status. We want service providers to have a way to assign support status metadata to resources. And then user should be able to filter resource types by support status when quering the api for resource types. Add processing of query parameter support_status to list_resource_types function in heat/api to filter resources by. List_resource_types returns a list of resources with a certain status or a list of all resource types by default. Add filtering on the server. Add changes to tests: - test_rpc_client.py - test_api_openstack_v1.py - test_engine_service.py Implements bp filter-resources-by-support Change-Id: I719c0d690886153adb698aea4695ddd526e7a4af --- heat/api/openstack/v1/stacks.py | 5 ++++- heat/engine/environment.py | 19 ++++++++++++------- heat/engine/resource.py | 6 +++--- heat/engine/service.py | 7 +++++-- heat/rpc/client.py | 7 +++++-- heat/tests/test_api_openstack_v1.py | 8 ++++---- heat/tests/test_engine_service.py | 9 +++++++++ heat/tests/test_rpc_client.py | 3 ++- 8 files changed, 44 insertions(+), 20 deletions(-) diff --git a/heat/api/openstack/v1/stacks.py b/heat/api/openstack/v1/stacks.py index ab856a25a2..0cb7f8000d 100644 --- a/heat/api/openstack/v1/stacks.py +++ b/heat/api/openstack/v1/stacks.py @@ -324,7 +324,10 @@ class StackController(object): """ Returns a list of valid resource types that may be used in a template. """ - return {'resource_types': self.engine.list_resource_types(req.context)} + support_status = req.params.get('support_status', None) + return { + 'resource_types': + self.engine.list_resource_types(req.context, support_status)} @util.tenant_local def resource_schema(self, req, type_name): diff --git a/heat/engine/environment.py b/heat/engine/environment.py index 5331bf89e2..d6ac29bcfe 100644 --- a/heat/engine/environment.py +++ b/heat/engine/environment.py @@ -303,13 +303,18 @@ class ResourceRegistry(object): return _as_dict(self._registry) - def get_types(self): + def get_types(self, support_status): '''Return a list of valid resource types.''' + def is_plugin(key): - if isinstance(self._registry[key], ClassResourceInfo): - return True - return False - return [k for k in self._registry if is_plugin(k)] + return isinstance(self._registry[key], ClassResourceInfo) + + def status_matches(cls): + return support_status is None or \ + cls.value.support_status.status == support_status.encode() + + return [name for name, cls in self._registry.iteritems() + if is_plugin(name) and status_matches(cls)] SECTIONS = (PARAMETERS, RESOURCE_REGISTRY) = \ @@ -358,8 +363,8 @@ class Environment(object): def get_class(self, resource_type, resource_name=None): return self.registry.get_class(resource_type, resource_name) - def get_types(self): - return self.registry.get_types() + def get_types(self, support_status=None): + return self.registry.get_types(support_status) def get_resource_info(self, resource_type, resource_name=None, registry_type=None): diff --git a/heat/engine/resource.py b/heat/engine/resource.py index 9ec3c519ad..6684570380 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -37,9 +37,9 @@ logger = logging.getLogger(__name__) DELETION_POLICY = (DELETE, RETAIN, SNAPSHOT) = ('Delete', 'Retain', 'Snapshot') -def get_types(): - '''Return an iterator over the list of valid resource types.''' - return iter(resources.global_env().get_types()) +def get_types(support_status): + '''Return a list of valid resource types.''' + return resources.global_env().get_types(support_status) def get_class(resource_type, resource_name=None): diff --git a/heat/engine/service.py b/heat/engine/service.py index acc124cd54..f2c398ffe1 100644 --- a/heat/engine/service.py +++ b/heat/engine/service.py @@ -86,6 +86,9 @@ class EngineService(service.Service): are also dynamically added and will be named as keyword arguments by the RPC caller. """ + + RPC_API_VERSION = '1.1' + def __init__(self, host, topic, manager=None): super(EngineService, self).__init__(host, topic) # stg == "Stack Thread Groups" @@ -529,13 +532,13 @@ class EngineService(service.Service): self._start_thread_with_lock(cnxt, stack, stack.delete) return stack_info - def list_resource_types(self, cnxt): + def list_resource_types(self, cnxt, support_status=None): """ Get a list of supported resource types. :param cnxt: RPC context. """ - return list(resource.get_types()) + return resource.get_types(support_status) def resource_schema(self, cnxt, type_name): """ diff --git a/heat/rpc/client.py b/heat/rpc/client.py index beadf97ef1..7ab8e05677 100644 --- a/heat/rpc/client.py +++ b/heat/rpc/client.py @@ -29,6 +29,7 @@ class EngineClient(heat.openstack.common.rpc.proxy.RpcProxy): API version history:: 1.0 - Initial version. + 1.1 - Add support_status argument to list_resource_types() ''' BASE_RPC_API_VERSION = '1.0' @@ -185,13 +186,15 @@ class EngineClient(heat.openstack.common.rpc.proxy.RpcProxy): self.make_msg('abandon_stack', stack_identity=stack_identity)) - def list_resource_types(self, ctxt): + def list_resource_types(self, ctxt, support_status=None): """ Get a list of valid resource types. :param ctxt: RPC context. """ - return self.call(ctxt, self.make_msg('list_resource_types')) + return self.call(ctxt, self.make_msg('list_resource_types', + support_status=support_status), + version='1.1') def resource_schema(self, ctxt, type_name): """ diff --git a/heat/tests/test_api_openstack_v1.py b/heat/tests/test_api_openstack_v1.py index 4fdb9a1607..0b125255ed 100644 --- a/heat/tests/test_api_openstack_v1.py +++ b/heat/tests/test_api_openstack_v1.py @@ -1272,8 +1272,8 @@ class StackControllerTest(ControllerTest, HeatTestCase): rpc.call(req.context, self.topic, {'namespace': None, 'method': 'list_resource_types', - 'args': {}, - 'version': self.api_version}, + 'args': {'support_status': None}, + 'version': '1.1'}, None).AndReturn(engine_response) self.m.ReplayAll() response = self.controller.list_resource_types(req, @@ -1289,8 +1289,8 @@ class StackControllerTest(ControllerTest, HeatTestCase): rpc.call(req.context, self.topic, {'namespace': None, 'method': 'list_resource_types', - 'args': {}, - 'version': self.api_version}, + 'args': {'support_status': None}, + 'version': '1.1'}, None).AndRaise(to_remote_error(error)) self.m.ReplayAll() diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py index 99eec74af6..b18023a78d 100644 --- a/heat/tests/test_engine_service.py +++ b/heat/tests/test_engine_service.py @@ -1296,6 +1296,15 @@ class StackServiceTest(HeatTestCase): self.assertTrue(isinstance(resources, list)) self.assertIn('AWS::EC2::Instance', resources) + def test_list_resource_types_deprecated(self): + resources = self.eng.list_resource_types(self.ctx, "DEPRECATED") + self.assertEqual(['OS::Neutron::RouterGateway'], resources) + + def test_list_resource_types_supported(self): + resources = self.eng.list_resource_types(self.ctx, "SUPPORTED") + self.assertNotIn(['OS::Neutron::RouterGateway'], resources) + self.assertIn('AWS::EC2::Instance', resources) + def test_resource_schema(self): type_name = 'ResourceWithPropsType' expected = { diff --git a/heat/tests/test_rpc_client.py b/heat/tests/test_rpc_client.py index 8e99f91230..c8fef7cd43 100644 --- a/heat/tests/test_rpc_client.py +++ b/heat/tests/test_rpc_client.py @@ -131,7 +131,8 @@ class EngineRpcAPITestCase(testtools.TestCase): template={u'Foo': u'bar'}) def test_list_resource_types(self): - self._test_engine_api('list_resource_types', 'call') + self._test_engine_api('list_resource_types', 'call', + support_status=None, version='1.1') def test_resource_schema(self): self._test_engine_api('resource_schema', 'call', type_name="TYPE")