Merge "Pecan: /v2.0/ views response with resources"
This commit is contained in:
commit
79bf76d73c
|
@ -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
|
||||
|
|
|
@ -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']
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue