From 5da865c1a89f1496c210ae2fc947c3e53612a37f Mon Sep 17 00:00:00 2001 From: tonytan4ever Date: Thu, 1 Sep 2016 10:52:40 -0400 Subject: [PATCH] Pecan: /v2.0/ views response with resources The legacy framework return a list of resources as the response to: GET /v2.0/ Current pecan 2.0 controller seems return the same as root controller content. This patch will make it return the same response as legacy framework Change-Id: Icae8c1b417d4d5a65a98eeafe80a26886aa254a3 --- neutron/api/v2/attributes.py | 4 ++++ neutron/api/v2/router.py | 5 +---- neutron/pecan_wsgi/controllers/root.py | 17 +++++++++++++++-- .../functional/pecan_wsgi/test_controllers.py | 19 ++++++++++++++----- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/neutron/api/v2/attributes.py b/neutron/api/v2/attributes.py index 86363c2878a..40b3ec856a9 100644 --- a/neutron/api/v2/attributes.py +++ b/neutron/api/v2/attributes.py @@ -35,6 +35,10 @@ SUBNET = 'subnet' SUBNETS = '%ss' % SUBNET SUBNETPOOL = 'subnetpool' SUBNETPOOLS = '%ss' % SUBNETPOOL +CORE_RESOURCES = {'network': 'networks', + 'subnet': 'subnets', + 'subnetpool': 'subnetpools', + 'port': 'ports'} # Note: a default of ATTR_NOT_SPECIFIED indicates that an # attribute is not required, but will be generated by the plugin # if it is not specified. Particularly, a value of ATTR_NOT_SPECIFIED diff --git a/neutron/api/v2/router.py b/neutron/api/v2/router.py index 64516a02b4d..0c2ec2fd1b2 100644 --- a/neutron/api/v2/router.py +++ b/neutron/api/v2/router.py @@ -34,10 +34,7 @@ from neutron.quota import resource_registry from neutron import wsgi -RESOURCES = {'network': 'networks', - 'subnet': 'subnets', - 'subnetpool': 'subnetpools', - 'port': 'ports'} +RESOURCES = attributes.CORE_RESOURCES SUB_RESOURCES = {} COLLECTION_ACTIONS = ['index', 'create'] MEMBER_ACTIONS = ['show', 'update', 'delete'] diff --git a/neutron/pecan_wsgi/controllers/root.py b/neutron/pecan_wsgi/controllers/root.py index 5793f12c467..44e714beef5 100644 --- a/neutron/pecan_wsgi/controllers/root.py +++ b/neutron/pecan_wsgi/controllers/root.py @@ -18,8 +18,11 @@ from oslo_config import cfg from oslo_log import log import pecan from pecan import request +import six +import six.moves.urllib.parse as urlparse from neutron._i18n import _LW +from neutron.api.v2 import attributes from neutron.api.views import versions as versions_view from neutron import manager from neutron.pecan_wsgi.controllers import extensions as ext_ctrl @@ -83,8 +86,18 @@ class V2Controller(object): @utils.expose(generic=True) def index(self): - builder = versions_view.get_view_builder(pecan.request) - return dict(version=builder.build(self.version_info)) + if not pecan.request.path_url.endswith('/'): + pecan.abort(404) + + layout = [] + for name, collection in six.iteritems(attributes.CORE_RESOURCES): + href = urlparse.urljoin(pecan.request.path_url, collection) + resource = {'name': name, + 'collection': collection, + 'links': [{'rel': 'self', + 'href': href}]} + layout.append(resource) + return {'resources': layout} @utils.when(index, method='HEAD') @utils.when(index, method='POST') diff --git a/neutron/tests/functional/pecan_wsgi/test_controllers.py b/neutron/tests/functional/pecan_wsgi/test_controllers.py index 01f9e45bdcc..02fdb0fbc1a 100644 --- a/neutron/tests/functional/pecan_wsgi/test_controllers.py +++ b/neutron/tests/functional/pecan_wsgi/test_controllers.py @@ -90,24 +90,33 @@ class TestRootController(test_functional.PecanFunctionalTest): class TestV2Controller(TestRootController): - base_url = '/v2.0' + base_url = '/v2.0/' def test_get(self): """Verify current version info are returned.""" response = self.app.get(self.base_url) self.assertEqual(response.status_int, 200) json_body = jsonutils.loads(response.body) - self.assertEqual('v2.0', json_body['version']['id']) - self.assertEqual('CURRENT', json_body['version']['status']) + self.assertIn('resources', json_body) + self.assertIsInstance(json_body['resources'], list) + for r in json_body['resources']: + self.assertIn("links", r) + self.assertIn("name", r) + self.assertIn("collection", r) + self.assertIn(self.base_url, r['links'][0]['href']) + + def test_get_no_trailing_slash(self): + response = self.app.get(self.base_url[:-1], expect_errors=True) + self.assertEqual(response.status_int, 404) def test_routing_successs(self): """Test dispatch to controller for existing resource.""" - response = self.app.get('%s/ports.json' % self.base_url) + response = self.app.get('%sports.json' % self.base_url) self.assertEqual(response.status_int, 200) def test_routing_failure(self): """Test dispatch to controller for non-existing resource.""" - response = self.app.get('%s/idonotexist.json' % self.base_url, + response = self.app.get('%sidonotexist.json' % self.base_url, expect_errors=True) self.assertEqual(response.status_int, 404)