Make Keystone return v3 as part of the version api
The keystone "get version" api currently fails to list v3 as a supported api. It should now do this, along with v2 (which is, of course, still supported) Fixes Bug #1148186 Change-Id: Ie88bf941123702d2f7e2ecf6cecb1fa937ca1e52
This commit is contained in:
parent
756cd5a297
commit
2dd6481a20
@ -23,6 +23,9 @@ from keystone import exception
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = config.CONF
|
||||
|
||||
MEDIA_TYPE_JSON = 'application/vnd.openstack.identity-%s+json'
|
||||
MEDIA_TYPE_XML = 'application/vnd.openstack.identity-%s+xml'
|
||||
|
||||
|
||||
class Extensions(wsgi.Application):
|
||||
"""Base extensions controller to be extended by public and admin API's."""
|
||||
@ -113,12 +116,30 @@ class Version(wsgi.Application):
|
||||
'media-types': [
|
||||
{
|
||||
'base': 'application/json',
|
||||
'type': 'application/vnd.openstack.identity-v2.0'
|
||||
'+json'
|
||||
'type': MEDIA_TYPE_JSON % 'v2.0'
|
||||
}, {
|
||||
'base': 'application/xml',
|
||||
'type': 'application/vnd.openstack.identity-v2.0'
|
||||
'+xml'
|
||||
'type': MEDIA_TYPE_XML % 'v2.0'
|
||||
}
|
||||
]
|
||||
}
|
||||
versions['v3'] = {
|
||||
'id': 'v3.0',
|
||||
'status': 'stable',
|
||||
'updated': '2013-03-06T00:00:00Z',
|
||||
'links': [
|
||||
{
|
||||
'rel': 'self',
|
||||
'href': self._get_identity_url(version='v3'),
|
||||
}
|
||||
],
|
||||
'media-types': [
|
||||
{
|
||||
'base': 'application/json',
|
||||
'type': MEDIA_TYPE_JSON % 'v3'
|
||||
}, {
|
||||
'base': 'application/xml',
|
||||
'type': MEDIA_TYPE_XML % 'v3'
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -133,8 +154,14 @@ class Version(wsgi.Application):
|
||||
}
|
||||
})
|
||||
|
||||
def get_version(self, context):
|
||||
def get_version_v2(self, context):
|
||||
versions = self._get_versions_list(context)
|
||||
return wsgi.render_response(body={
|
||||
'version': versions['v2.0']
|
||||
})
|
||||
|
||||
def get_version_v3(self, context):
|
||||
versions = self._get_versions_list(context)
|
||||
return wsgi.render_response(body={
|
||||
'version': versions['v3']
|
||||
})
|
||||
|
@ -47,7 +47,7 @@ class Extension(wsgi.ComposableRouter):
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
|
||||
class Version(wsgi.ComposableRouter):
|
||||
class VersionV2(wsgi.ComposableRouter):
|
||||
def __init__(self, description):
|
||||
self.description = description
|
||||
|
||||
@ -55,7 +55,18 @@ class Version(wsgi.ComposableRouter):
|
||||
version_controller = controllers.Version(self.description)
|
||||
mapper.connect('/',
|
||||
controller=version_controller,
|
||||
action='get_version')
|
||||
action='get_version_v2')
|
||||
|
||||
|
||||
class VersionV3(wsgi.ComposableRouter):
|
||||
def __init__(self, description):
|
||||
self.description = description
|
||||
|
||||
def add_routes(self, mapper):
|
||||
version_controller = controllers.Version(self.description)
|
||||
mapper.connect('/',
|
||||
controller=version_controller,
|
||||
action='get_version_v3')
|
||||
|
||||
|
||||
class Versions(wsgi.ComposableRouter):
|
||||
|
@ -46,7 +46,7 @@ def public_app_factory(global_conf, **local_conf):
|
||||
return wsgi.ComposingRouter(routes.Mapper(),
|
||||
[identity.routers.Public(),
|
||||
token.routers.Router(),
|
||||
routers.Version('public'),
|
||||
routers.VersionV2('public'),
|
||||
routers.Extension(False)])
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ def admin_app_factory(global_conf, **local_conf):
|
||||
return wsgi.ComposingRouter(routes.Mapper(),
|
||||
[identity.routers.Admin(),
|
||||
token.routers.Router(),
|
||||
routers.Version('admin'),
|
||||
routers.VersionV2('admin'),
|
||||
routers.Extension()])
|
||||
|
||||
|
||||
@ -85,5 +85,8 @@ def v3_app_factory(global_conf, **local_conf):
|
||||
v3routers = []
|
||||
for module in [auth, catalog, identity, policy, trust]:
|
||||
module.routers.append_v3_routers(mapper, v3routers)
|
||||
# Add in the v3 version api
|
||||
v3routers.append(routers.VersionV3('admin'))
|
||||
v3routers.append(routers.VersionV3('public'))
|
||||
# TODO(ayoung): put token routes here
|
||||
return wsgi.ComposingRouter(mapper, v3routers)
|
||||
|
@ -22,6 +22,91 @@ from keystone import test
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
v2_MEDIA_TYPES = [
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/"
|
||||
"vnd.openstack.identity-v2.0+json"
|
||||
}, {
|
||||
"base": "application/xml",
|
||||
"type": "application/"
|
||||
"vnd.openstack.identity-v2.0+xml"
|
||||
}
|
||||
]
|
||||
|
||||
v2_HTML_DESCRIPTION = {
|
||||
"rel": "describedby",
|
||||
"type": "text/html",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/2.0/"
|
||||
"content/"
|
||||
}
|
||||
|
||||
v2_PDF_DESCRIPTION = {
|
||||
"rel": "describedby",
|
||||
"type": "application/pdf",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/2.0/"
|
||||
"identity-dev-guide-2.0.pdf"
|
||||
}
|
||||
|
||||
v2_EXPECTED_RESPONSE = {
|
||||
"id": "v2.0",
|
||||
"status": "stable",
|
||||
"updated": "2013-03-06T00:00:00Z",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "", # Will get filled in after initialization
|
||||
},
|
||||
v2_HTML_DESCRIPTION,
|
||||
v2_PDF_DESCRIPTION
|
||||
],
|
||||
"media-types": v2_MEDIA_TYPES
|
||||
}
|
||||
|
||||
v2_VERSION_RESPONSE = {
|
||||
"version": v2_EXPECTED_RESPONSE
|
||||
}
|
||||
|
||||
v3_MEDIA_TYPES = [
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/"
|
||||
"vnd.openstack.identity-v3+json"
|
||||
}, {
|
||||
"base": "application/xml",
|
||||
"type": "application/"
|
||||
"vnd.openstack.identity-v3+xml"
|
||||
}
|
||||
]
|
||||
|
||||
v3_EXPECTED_RESPONSE = {
|
||||
"id": "v3.0",
|
||||
"status": "stable",
|
||||
"updated": "2013-03-06T00:00:00Z",
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "", # Will get filled in after initialization
|
||||
}
|
||||
],
|
||||
"media-types": v3_MEDIA_TYPES
|
||||
}
|
||||
|
||||
v3_VERSION_RESPONSE = {
|
||||
"version": v3_EXPECTED_RESPONSE
|
||||
}
|
||||
|
||||
VERSIONS_RESPONSE = {
|
||||
"versions": {
|
||||
"values": [
|
||||
v3_EXPECTED_RESPONSE,
|
||||
v2_EXPECTED_RESPONSE
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class VersionTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
@ -33,52 +118,24 @@ class VersionTestCase(test.TestCase):
|
||||
self.public_server = self.serveapp('keystone', name='main')
|
||||
self.admin_server = self.serveapp('keystone', name='admin')
|
||||
|
||||
def _paste_in_port(self, response, port):
|
||||
for link in response['links']:
|
||||
if link['rel'] == 'self':
|
||||
link['href'] = port
|
||||
|
||||
def test_public_versions(self):
|
||||
client = self.client(self.public_app)
|
||||
resp = client.get('/')
|
||||
self.assertEqual(resp.status_int, 300)
|
||||
data = jsonutils.loads(resp.body)
|
||||
expected = {
|
||||
"versions": {
|
||||
"values": [
|
||||
{
|
||||
"id": "v2.0",
|
||||
"status": "stable",
|
||||
"updated": '2013-03-06T00:00:00Z',
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://localhost:%s/v2.0/" %
|
||||
CONF.public_port,
|
||||
}, {
|
||||
"rel": "describedby",
|
||||
"type": "text/html",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/2.0/"
|
||||
"content/"
|
||||
}, {
|
||||
"rel": "describedby",
|
||||
"type": "application/pdf",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/2.0/"
|
||||
"identity-dev-guide-2.0.pdf"
|
||||
}
|
||||
],
|
||||
"media-types": [
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/"
|
||||
"vnd.openstack.identity-v2.0+json"
|
||||
}, {
|
||||
"base": "application/xml",
|
||||
"type": "application/"
|
||||
"vnd.openstack.identity-v2.0+xml"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
expected = VERSIONS_RESPONSE
|
||||
for version in expected['versions']['values']:
|
||||
if version['id'] == 'v3.0':
|
||||
self._paste_in_port(
|
||||
version, 'http://localhost:%s/v3/' % CONF.public_port)
|
||||
elif version['id'] == 'v2.0':
|
||||
self._paste_in_port(
|
||||
version, 'http://localhost:%s/v2.0/' % CONF.public_port)
|
||||
self.assertEqual(data, expected)
|
||||
|
||||
def test_admin_versions(self):
|
||||
@ -86,45 +143,53 @@ class VersionTestCase(test.TestCase):
|
||||
resp = client.get('/')
|
||||
self.assertEqual(resp.status_int, 300)
|
||||
data = jsonutils.loads(resp.body)
|
||||
expected = {
|
||||
"versions": {
|
||||
"values": [
|
||||
{
|
||||
"id": "v2.0",
|
||||
"status": "stable",
|
||||
"updated": '2013-03-06T00:00:00Z',
|
||||
"links": [
|
||||
{
|
||||
"rel": "self",
|
||||
"href": "http://localhost:%s/v2.0/" %
|
||||
CONF.admin_port,
|
||||
}, {
|
||||
"rel": "describedby",
|
||||
"type": "text/html",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/2.0/"
|
||||
"content/"
|
||||
}, {
|
||||
"rel": "describedby",
|
||||
"type": "application/pdf",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/2.0/"
|
||||
"identity-dev-guide-2.0.pdf"
|
||||
}
|
||||
],
|
||||
"media-types": [
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/"
|
||||
"vnd.openstack.identity-v2.0+json"
|
||||
}, {
|
||||
"base": "application/xml",
|
||||
"type": "application/"
|
||||
"vnd.openstack.identity-v2.0+xml"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
expected = VERSIONS_RESPONSE
|
||||
for version in expected['versions']['values']:
|
||||
if version['id'] == 'v3.0':
|
||||
self._paste_in_port(
|
||||
version, 'http://localhost:%s/v3/' % CONF.admin_port)
|
||||
elif version['id'] == 'v2.0':
|
||||
self._paste_in_port(
|
||||
version, 'http://localhost:%s/v2.0/' % CONF.admin_port)
|
||||
self.assertEqual(data, expected)
|
||||
|
||||
def test_public_version_v2(self):
|
||||
client = self.client(self.public_app)
|
||||
resp = client.get('/v2.0/')
|
||||
self.assertEqual(resp.status_int, 200)
|
||||
data = jsonutils.loads(resp.body)
|
||||
expected = v2_VERSION_RESPONSE
|
||||
self._paste_in_port(expected['version'],
|
||||
'http://localhost:%s/v2.0/' % CONF.public_port)
|
||||
self.assertEqual(data, expected)
|
||||
|
||||
def test_admin_version_v2(self):
|
||||
client = self.client(self.admin_app)
|
||||
resp = client.get('/v2.0/')
|
||||
self.assertEqual(resp.status_int, 200)
|
||||
data = jsonutils.loads(resp.body)
|
||||
expected = v2_VERSION_RESPONSE
|
||||
self._paste_in_port(expected['version'],
|
||||
'http://localhost:%s/v2.0/' % CONF.admin_port)
|
||||
self.assertEqual(data, expected)
|
||||
|
||||
def test_public_version_v3(self):
|
||||
print CONF.public_port
|
||||
client = self.client(self.public_app)
|
||||
resp = client.get('/v3/')
|
||||
self.assertEqual(resp.status_int, 200)
|
||||
data = jsonutils.loads(resp.body)
|
||||
expected = v3_VERSION_RESPONSE
|
||||
self._paste_in_port(expected['version'],
|
||||
'http://localhost:%s/v3/' % CONF.public_port)
|
||||
self.assertEqual(data, expected)
|
||||
|
||||
def test_admin_version_v3(self):
|
||||
client = self.client(self.public_app)
|
||||
resp = client.get('/v3/')
|
||||
self.assertEqual(resp.status_int, 200)
|
||||
data = jsonutils.loads(resp.body)
|
||||
expected = v3_VERSION_RESPONSE
|
||||
self._paste_in_port(expected['version'],
|
||||
'http://localhost:%s/v3/' % CONF.admin_port)
|
||||
self.assertEqual(data, expected)
|
||||
|
Loading…
Reference in New Issue
Block a user