]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Rajaram/Vinkesh | Plugins advertise which extensions it supports.
authorRajaram Mallya <rajarammallya@gmail.com>
Fri, 22 Jul 2011 07:21:38 +0000 (12:51 +0530)
committerRajaram Mallya <rajarammallya@gmail.com>
Fri, 22 Jul 2011 07:21:38 +0000 (12:51 +0530)
quantum/common/extensions.py
quantum/plugins/SamplePlugin.py
quantum/quantum_plugin_base.py
tests/unit/test_extensions.py

index 772beaaafe250a25adb383027aaf110006d12eea..80d43fd085244141680ce96f2906b203a75fd86d 100644 (file)
@@ -212,6 +212,46 @@ class ExtensionController(wsgi.Controller):
 
 class ExtensionMiddleware(wsgi.Middleware):
     """Extensions middleware for WSGI."""
+    def __init__(self, application, config_params,
+                 ext_mgr=None):
+
+        self.ext_mgr = (ext_mgr
+                        or PluginAwareExtensionManager(
+                config_params.get('api_extensions_path', '')))
+
+        mapper = routes.Mapper()
+
+        # extended resources
+        for resource in self.ext_mgr.get_resources():
+            LOG.debug(_('Extended resource: %s'),
+                        resource.collection)
+            mapper.resource(resource.collection, resource.collection,
+                            controller=resource.controller,
+                            collection=resource.collection_actions,
+                            member=resource.member_actions,
+                            parent_resource=resource.parent)
+
+        # extended actions
+        action_controllers = self._action_ext_controllers(application,
+                                                          self.ext_mgr, mapper)
+        for action in self.ext_mgr.get_actions():
+            LOG.debug(_('Extended action: %s'), action.action_name)
+            controller = action_controllers[action.collection]
+            controller.add_action(action.action_name, action.handler)
+
+        # extended requests
+        req_controllers = self._request_ext_controllers(application,
+                                                        self.ext_mgr, mapper)
+        for request_ext in self.ext_mgr.get_request_extensions():
+            LOG.debug(_('Extended request: %s'), request_ext.key)
+            controller = req_controllers[request_ext.key]
+            controller.add_handler(request_ext.handler)
+
+        self._router = routes.middleware.RoutesMiddleware(self._dispatch,
+                                                          mapper)
+
+        super(ExtensionMiddleware, self).__init__(application)
+
     @classmethod
     def factory(cls, global_config, **local_config):
         """Paste factory."""
@@ -257,46 +297,6 @@ class ExtensionMiddleware(wsgi.Middleware):
 
         return request_ext_controllers
 
-    def __init__(self, application, config_params,
-                 ext_mgr=None):
-
-        self.ext_mgr = (ext_mgr
-                        or PluginAwareExtensionManager(
-                config_params.get('api_extensions_path', '')))
-
-        mapper = routes.Mapper()
-
-        # extended resources
-        for resource in self.ext_mgr.get_resources():
-            LOG.debug(_('Extended resource: %s'),
-                        resource.collection)
-            mapper.resource(resource.collection, resource.collection,
-                            controller=resource.controller,
-                            collection=resource.collection_actions,
-                            member=resource.member_actions,
-                            parent_resource=resource.parent)
-
-        # extended actions
-        action_controllers = self._action_ext_controllers(application,
-                                                          self.ext_mgr, mapper)
-        for action in self.ext_mgr.get_actions():
-            LOG.debug(_('Extended action: %s'), action.action_name)
-            controller = action_controllers[action.collection]
-            controller.add_action(action.action_name, action.handler)
-
-        # extended requests
-        req_controllers = self._request_ext_controllers(application,
-                                                        self.ext_mgr, mapper)
-        for request_ext in self.ext_mgr.get_request_extensions():
-            LOG.debug(_('Extended request: %s'), request_ext.key)
-            controller = req_controllers[request_ext.key]
-            controller.add_handler(request_ext.handler)
-
-        self._router = routes.middleware.RoutesMiddleware(self._dispatch,
-                                                          mapper)
-
-        super(ExtensionMiddleware, self).__init__(application)
-
     @webob.dec.wsgify(RequestClass=wsgi.Request)
     def __call__(self, req):
         """Route the incoming request with router."""
@@ -451,8 +451,9 @@ class PluginAwareExtensionManager(ExtensionManager):
                 self._plugin_implements_interface(extension))
 
     def _plugin_supports(self, extension):
-        return (hasattr(self.plugin, "supports_extension") and
-                self.plugin.supports_extension(extension))
+        alias = extension.get_alias()
+        return (hasattr(self.plugin, "supported_extension_aliases") and
+                alias in self.plugin.supported_extension_aliases)
 
     def _plugin_implements_interface(self, extension):
         if(not hasattr(extension, "get_plugin_interface") or
index fa8da29d95dc562e4d54570448917ddb547d30a9..5b4e9c12655e8901c6c82283ea79d4f50887ec05 100644 (file)
@@ -253,6 +253,8 @@ class FakePlugin(object):
                     'net-name': 'cicciotest',
                     'net-ports': _port_dict_2}}
 
+    supported_extension_aliases = ["FOXNSOX"]
+
     def __init__(self):
         FakePlugin._net_counter = len(FakePlugin._networks)
 
@@ -434,6 +436,3 @@ class FakePlugin(object):
         # TODO(salvatore-orlando):
         # Should unplug on port without attachment raise an Error?
         port['attachment'] = None
-
-    def supports_extension(self, extension):
-        return True
index a43b8c0cc51ab504903796cc64fc2f2804084031..8e3f1f8e152b0ce0d8ec359a41373c67514009b5 100644 (file)
@@ -230,15 +230,6 @@ class QuantumPluginBase(object):
         """
         pass
 
-    def supports_extension(self, extension):
-        """
-        Returns if the extension is supported.
-        If this method is not implemented, extensions will not be loaded.
-
-        :returns: True or False
-        """
-        pass
-
     @classmethod
     def __subclasshook__(cls, klass):
         """
index 2e9bd05ce24efb97f54171b1afd58b68405780a0..8511a13a144a93a41147377fa6f03389e7cdf53b 100644 (file)
@@ -27,74 +27,10 @@ from quantum.common import config
 from quantum.common.extensions import (ExtensionManager,
                                        PluginAwareExtensionManager)
 
-extension_index_response = "Try to say this Mr. Knox, sir..."
 test_conf_file = os.path.join(os.path.dirname(__file__), os.pardir,
                               os.pardir, 'etc', 'quantum.conf.test')
 
 
-class ExtensionControllerTest(unittest.TestCase):
-
-    def setUp(self):
-        super(ExtensionControllerTest, self).setUp()
-        self.test_app = setup_extensions_test_app()
-
-    def test_index_gets_all_registerd_extensions(self):
-        response = self.test_app.get("/extensions")
-        foxnsox = response.json["extensions"][0]
-
-        self.assertEqual(foxnsox["alias"], "FOXNSOX")
-        self.assertEqual(foxnsox["namespace"],
-                         "http://www.fox.in.socks/api/ext/pie/v1.0")
-
-    def test_extension_can_be_accessed_by_alias(self):
-        foxnsox_extension = self.test_app.get("/extensions/FOXNSOX").json
-
-        self.assertEqual(foxnsox_extension["alias"], "FOXNSOX")
-        self.assertEqual(foxnsox_extension["namespace"],
-                         "http://www.fox.in.socks/api/ext/pie/v1.0")
-
-
-class ResourceExtensionTest(unittest.TestCase):
-
-    def test_resource_extension(self):
-        res_ext = extensions.ResourceExtension('tweedles', StubController(
-                                                  extension_index_response))
-        test_app = setup_extensions_test_app(StubExtensionManager(res_ext))
-
-        response = test_app.get("/tweedles")
-        self.assertEqual(200, response.status_int)
-        self.assertEqual(extension_index_response, response.body)
-
-    def test_resource_extension_with_custom_member_action(self):
-        controller = StubController(extension_index_response)
-        member = {'custom_member_action': "GET"}
-        res_ext = extensions.ResourceExtension('tweedles', controller,
-                                               member_actions=member)
-        test_app = setup_extensions_test_app(StubExtensionManager(res_ext))
-
-        response = test_app.get("/tweedles/some_id/custom_member_action")
-        self.assertEqual(200, response.status_int)
-        self.assertEqual(json.loads(response.body)['member_action'], "value")
-
-    def test_resource_extension_with_custom_collection_action(self):
-        controller = StubController(extension_index_response)
-        collections = {'custom_collection_action': "GET"}
-        res_ext = extensions.ResourceExtension('tweedles', controller,
-                                               collection_actions=collections)
-        test_app = setup_extensions_test_app(StubExtensionManager(res_ext))
-
-        response = test_app.get("/tweedles/custom_collection_action")
-        self.assertEqual(200, response.status_int)
-        self.assertEqual(json.loads(response.body)['collection'], "value")
-
-    def test_returns_404_for_non_existant_extension(self):
-        test_app = setup_extensions_test_app(StubExtensionManager(None))
-
-        response = test_app.get("/non_extistant_extension", status='*')
-
-        self.assertEqual(404, response.status_int)
-
-
 class StubExtension(object):
 
     def __init__(self, alias="stub_extension"):
@@ -119,10 +55,7 @@ class StubExtension(object):
 class StubPlugin(object):
 
     def __init__(self, supported_extensions=[]):
-        self.supported_extensions = supported_extensions
-
-    def supports_extension(self, extension):
-        return extension.get_alias() in self.supported_extensions
+        self.supported_extension_aliases = supported_extensions
 
 
 class ExtensionExpectingPluginInterface(StubExtension):
@@ -142,112 +75,84 @@ class StubPluginInterface(extensions.PluginInterface):
         pass
 
 
-class ExtensionManagerTest(unittest.TestCase):
-
-    def test_invalid_extensions_are_not_registered(self):
+class StubBaseAppController(wsgi.Controller):
 
-        class InvalidExtension(object):
-            """
-            This Extension doesn't implement extension methods :
-            get_name, get_description, get_namespace and get_updated
-            """
-            def get_alias(self):
-                return "invalid_extension"
-
-        ext_mgr = ExtensionManager('')
-        ext_mgr.add_extension(InvalidExtension())
-        ext_mgr.add_extension(StubExtension("valid_extension"))
-
-        self.assertTrue('valid_extension' in ext_mgr.extensions)
-        self.assertFalse('invalid_extension' in ext_mgr.extensions)
-
-
-class PluginAwareExtensionManagerTest(unittest.TestCase):
+    def index(self, request):
+        return "base app index"
 
-    def setUp(self):
-        self.ext_mgr = PluginAwareExtensionManager('')
+    def show(self, request, id):
+        return {'fort': 'knox'}
 
-    def test_unsupported_extensions_are_not_loaded(self):
-        self.ext_mgr.plugin = StubPlugin(supported_extensions=["e1", "e3"])
+    def update(self, request, id):
+        return {'uneditable': 'original_value'}
 
-        self.ext_mgr.add_extension(StubExtension("e1"))
-        self.ext_mgr.add_extension(StubExtension("e2"))
-        self.ext_mgr.add_extension(StubExtension("e3"))
 
-        self.assertTrue("e1" in self.ext_mgr.extensions)
-        self.assertFalse("e2" in self.ext_mgr.extensions)
-        self.assertTrue("e3" in self.ext_mgr.extensions)
+class ExtensionsTestApp(wsgi.Router):
 
-    def test_extensions_are_not_loaded_for_plugins_unaware_of_extensions(self):
-        class ExtensionUnawarePlugin(object):
-            """
-            This plugin does not implement supports_extension method.
-            Extensions will not be loaded when this plugin is used.
-            """
-            pass
+    def __init__(self, options={}):
+        mapper = routes.Mapper()
+        controller = StubBaseAppController()
+        mapper.resource("dummy_resource", "/dummy_resources",
+                        controller=controller)
+        super(ExtensionsTestApp, self).__init__(mapper)
 
-        self.ext_mgr.plugin = ExtensionUnawarePlugin()
-        self.ext_mgr.add_extension(StubExtension("e1"))
 
-        self.assertFalse("e1" in self.ext_mgr.extensions)
+class ResourceExtensionTest(unittest.TestCase):
 
-    def test_extensions_not_loaded_for_plugin_without_expected_interface(self):
+    class ResourceExtensionController(wsgi.Controller):
 
-        class PluginWithoutExpectedInterface(object):
-            """
-            Plugin does not implement get_foo method as expected by extension
-            """
-            def supports_extension(self, true):
-                return true
+        def index(self, request):
+            return "resource index"
 
-        self.ext_mgr.plugin = PluginWithoutExpectedInterface()
-        self.ext_mgr.add_extension(ExtensionExpectingPluginInterface("e1"))
+        def show(self, request, id):
+            return {'data': {'id': id}}
 
-        self.assertFalse("e1" in self.ext_mgr.extensions)
+        def custom_member_action(self, request, id):
+            return {'member_action': 'value'}
 
-    def test_extensions_are_loaded_for_plugin_with_expected_interface(self):
+        def custom_collection_action(self, request):
+            return {'collection': 'value'}
 
-        class PluginWithExpectedInterface(object):
-            """
-            This Plugin implements get_foo method as expected by extension
-            """
-            def supports_extension(self, true):
-                return true
+    def test_resource_can_be_added_as_extension(self):
+        res_ext = extensions.ResourceExtension('tweedles',
+                                            self.ResourceExtensionController())
+        test_app = setup_extensions_test_app(SimpleExtensionManager(res_ext))
 
-            def get_foo(self, bar=None):
-                pass
+        index_response = test_app.get("/tweedles")
+        self.assertEqual(200, index_response.status_int)
+        self.assertEqual("resource index", index_response.body)
 
-        self.ext_mgr.plugin = PluginWithExpectedInterface()
-        self.ext_mgr.add_extension(ExtensionExpectingPluginInterface("e1"))
+        show_response = test_app.get("/tweedles/25266")
+        self.assertEqual({'data': {'id': "25266"}}, show_response.json)
 
-        self.assertTrue("e1" in self.ext_mgr.extensions)
+    def test_resource_extension_with_custom_member_action(self):
+        controller = self.ResourceExtensionController()
+        member = {'custom_member_action': "GET"}
+        res_ext = extensions.ResourceExtension('tweedles', controller,
+                                               member_actions=member)
+        test_app = setup_extensions_test_app(SimpleExtensionManager(res_ext))
 
-    def test_extensions_expecting_quantum_plugin_interface_are_loaded(self):
-        class ExtensionForQuamtumPluginInterface(StubExtension):
-            """
-            This Extension does not implement get_plugin_interface method.
-            This will work with any plugin implementing QuantumPluginBase
-            """
-            pass
+        response = test_app.get("/tweedles/some_id/custom_member_action")
+        self.assertEqual(200, response.status_int)
+        self.assertEqual(json.loads(response.body)['member_action'], "value")
 
-        self.ext_mgr.plugin = StubPlugin(supported_extensions=["e1"])
-        self.ext_mgr.add_extension(ExtensionForQuamtumPluginInterface("e1"))
+    def test_resource_extension_with_custom_collection_action(self):
+        controller = self.ResourceExtensionController()
+        collections = {'custom_collection_action': "GET"}
+        res_ext = extensions.ResourceExtension('tweedles', controller,
+                                               collection_actions=collections)
+        test_app = setup_extensions_test_app(SimpleExtensionManager(res_ext))
 
-        self.assertTrue("e1" in self.ext_mgr.extensions)
+        response = test_app.get("/tweedles/custom_collection_action")
+        self.assertEqual(200, response.status_int)
+        self.assertEqual(json.loads(response.body)['collection'], "value")
 
-    def test_extensions_without_need_for__plugin_interface_are_loaded(self):
-        class ExtensionWithNoNeedForPluginInterface(StubExtension):
-            """
-            This Extension does not need any plugin interface.
-            This will work with any plugin implementing QuantumPluginBase
-            """
-            def get_plugin_interface(self):
-                return None
+    def test_returns_404_for_non_existant_extension(self):
+        test_app = setup_extensions_test_app(SimpleExtensionManager(None))
 
-        self.ext_mgr.plugin = StubPlugin(supported_extensions=["e1"])
-        self.ext_mgr.add_extension(ExtensionWithNoNeedForPluginInterface("e1"))
+        response = test_app.get("/non_extistant_extension", status='*')
 
-        self.assertTrue("e1" in self.ext_mgr.extensions)
+        self.assertEqual(404, response.status_int)
 
 
 class ActionExtensionTest(unittest.TestCase):
@@ -354,49 +259,148 @@ class RequestExtensionTest(BaseTest):
     def _setup_app_with_request_handler(self, handler, verb):
         req_ext = extensions.RequestExtension(verb,
                                    '/dummy_resources/:(id)', handler)
-        manager = StubExtensionManager(None, None, req_ext)
+        manager = SimpleExtensionManager(None, None, req_ext)
         return setup_extensions_test_app(manager)
 
 
-class TestExtensionMiddlewareFactory(unittest.TestCase):
+class ExtensionManagerTest(unittest.TestCase):
 
-    def test_app_configured_with_extensions_as_filter(self):
-        conf, quantum_app = config.load_paste_app('extensions_app_with_filter',
-                                        {"config_file": test_conf_file}, None)
+    def test_invalid_extensions_are_not_registered(self):
 
-        response = TestApp(quantum_app).get("/extensions")
-        self.assertEqual(response.status_int, 200)
+        class InvalidExtension(object):
+            """
+            This Extension doesn't implement extension methods :
+            get_name, get_description, get_namespace and get_updated
+            """
+            def get_alias(self):
+                return "invalid_extension"
 
+        ext_mgr = ExtensionManager('')
+        ext_mgr.add_extension(InvalidExtension())
+        ext_mgr.add_extension(StubExtension("valid_extension"))
 
-class ExtensionsTestApp(wsgi.Router):
+        self.assertTrue('valid_extension' in ext_mgr.extensions)
+        self.assertFalse('invalid_extension' in ext_mgr.extensions)
 
-    def __init__(self, options={}):
-        mapper = routes.Mapper()
-        controller = StubController(extension_index_response)
-        mapper.resource("dummy_resource", "/dummy_resources",
-                        controller=controller)
-        super(ExtensionsTestApp, self).__init__(mapper)
 
+class PluginAwareExtensionManagerTest(unittest.TestCase):
 
-class StubController(wsgi.Controller):
+    def setUp(self):
+        self.ext_mgr = PluginAwareExtensionManager('')
 
-    def __init__(self, body):
-        self.body = body
+    def test_unsupported_extensions_are_not_loaded(self):
+        self.ext_mgr.plugin = StubPlugin(supported_extensions=["e1", "e3"])
 
-    def index(self, request):
-        return self.body
+        self.ext_mgr.add_extension(StubExtension("e1"))
+        self.ext_mgr.add_extension(StubExtension("e2"))
+        self.ext_mgr.add_extension(StubExtension("e3"))
 
-    def show(self, request, id):
-        return {'fort': 'knox'}
+        self.assertTrue("e1" in self.ext_mgr.extensions)
+        self.assertFalse("e2" in self.ext_mgr.extensions)
+        self.assertTrue("e3" in self.ext_mgr.extensions)
 
-    def update(self, request, id):
-        return {'uneditable': 'original_value'}
+    def test_extensions_are_not_loaded_for_plugins_unaware_of_extensions(self):
+        class ExtensionUnawarePlugin(object):
+            """
+            This plugin does not implement supports_extension method.
+            Extensions will not be loaded when this plugin is used.
+            """
+            pass
+
+        self.ext_mgr.plugin = ExtensionUnawarePlugin()
+        self.ext_mgr.add_extension(StubExtension("e1"))
+
+        self.assertFalse("e1" in self.ext_mgr.extensions)
+
+    def test_extensions_not_loaded_for_plugin_without_expected_interface(self):
+
+        class PluginWithoutExpectedInterface(object):
+            """
+            Plugin does not implement get_foo method as expected by extension
+            """
+            supported_extension_aliases = ["supported_extension"]
+
+        self.ext_mgr.plugin = PluginWithoutExpectedInterface()
+        self.ext_mgr.add_extension(
+            ExtensionExpectingPluginInterface("supported_extension"))
+
+        self.assertFalse("e1" in self.ext_mgr.extensions)
+
+    def test_extensions_are_loaded_for_plugin_with_expected_interface(self):
+
+        class PluginWithExpectedInterface(object):
+            """
+            This Plugin implements get_foo method as expected by extension
+            """
+            supported_extension_aliases = ["supported_extension"]
+
+            def get_foo(self, bar=None):
+                pass
+
+        self.ext_mgr.plugin = PluginWithExpectedInterface()
+        self.ext_mgr.add_extension(
+                ExtensionExpectingPluginInterface("supported_extension"))
+
+        self.assertTrue("supported_extension" in self.ext_mgr.extensions)
+
+    def test_extensions_expecting_quantum_plugin_interface_are_loaded(self):
+        class ExtensionForQuamtumPluginInterface(StubExtension):
+            """
+            This Extension does not implement get_plugin_interface method.
+            This will work with any plugin implementing QuantumPluginBase
+            """
+            pass
 
-    def custom_member_action(self, request, id):
-        return {'member_action': 'value'}
+        self.ext_mgr.plugin = StubPlugin(supported_extensions=["e1"])
+        self.ext_mgr.add_extension(ExtensionForQuamtumPluginInterface("e1"))
 
-    def custom_collection_action(self, request):
-        return {'collection': 'value'}
+        self.assertTrue("e1" in self.ext_mgr.extensions)
+
+    def test_extensions_without_need_for__plugin_interface_are_loaded(self):
+        class ExtensionWithNoNeedForPluginInterface(StubExtension):
+            """
+            This Extension does not need any plugin interface.
+            This will work with any plugin implementing QuantumPluginBase
+            """
+            def get_plugin_interface(self):
+                return None
+
+        self.ext_mgr.plugin = StubPlugin(supported_extensions=["e1"])
+        self.ext_mgr.add_extension(ExtensionWithNoNeedForPluginInterface("e1"))
+
+        self.assertTrue("e1" in self.ext_mgr.extensions)
+
+
+class ExtensionControllerTest(unittest.TestCase):
+
+    def setUp(self):
+        super(ExtensionControllerTest, self).setUp()
+        self.test_app = setup_extensions_test_app()
+
+    def test_index_gets_all_registerd_extensions(self):
+        response = self.test_app.get("/extensions")
+        foxnsox = response.json["extensions"][0]
+
+        self.assertEqual(foxnsox["alias"], "FOXNSOX")
+        self.assertEqual(foxnsox["namespace"],
+                         "http://www.fox.in.socks/api/ext/pie/v1.0")
+
+    def test_extension_can_be_accessed_by_alias(self):
+        foxnsox_extension = self.test_app.get("/extensions/FOXNSOX").json
+
+        self.assertEqual(foxnsox_extension["alias"], "FOXNSOX")
+        self.assertEqual(foxnsox_extension["namespace"],
+                         "http://www.fox.in.socks/api/ext/pie/v1.0")
+
+
+class TestExtensionMiddlewareFactory(unittest.TestCase):
+
+    def test_app_configured_with_extensions_as_filter(self):
+        conf, quantum_app = config.load_paste_app('extensions_app_with_filter',
+                                        {"config_file": test_conf_file}, None)
+
+        response = TestApp(quantum_app).get("/extensions")
+        self.assertEqual(response.status_int, 200)
 
 
 def app_factory(global_conf, **local_conf):
@@ -421,22 +425,13 @@ def setup_extensions_test_app(extension_manager=None):
     return TestApp(setup_extensions_middleware(extension_manager))
 
 
-class StubExtensionManager(object):
+class SimpleExtensionManager(object):
 
     def __init__(self, resource_ext=None, action_ext=None, request_ext=None):
         self.resource_ext = resource_ext
         self.action_ext = action_ext
         self.request_ext = request_ext
 
-    def get_name(self):
-        return "Tweedle Beetle Extension"
-
-    def get_alias(self):
-        return "TWDLBETL"
-
-    def get_description(self):
-        return "Provides access to Tweedle Beetles"
-
     def get_resources(self):
         resource_exts = []
         if self.resource_ext: