summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenry Nash <henryn@linux.vnet.ibm.com>2013-03-06 01:54:27 +0000
committerHenry Nash <henryn@linux.vnet.ibm.com>2013-03-09 19:39:34 +0000
commit2dd6481a2005df7de0fed1fd630b8d2fbe38b775 (patch)
tree30c565241677fe8c2cf90c5a37e5e6e0e682ca55
parent756cd5a2972e076cdc9a119526e2038d0b838256 (diff)
downloadkeystone-2dd6481a2005df7de0fed1fd630b8d2fbe38b775.tar.gz
keystone-2dd6481a2005df7de0fed1fd630b8d2fbe38b775.tar.xz
keystone-2dd6481a2005df7de0fed1fd630b8d2fbe38b775.zip
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
-rw-r--r--keystone/controllers.py37
-rw-r--r--keystone/routers.py15
-rw-r--r--keystone/service.py7
-rw-r--r--tests/test_versions.py229
4 files changed, 197 insertions, 91 deletions
diff --git a/keystone/controllers.py b/keystone/controllers.py
index e19840e9..8864ca6c 100644
--- a/keystone/controllers.py
+++ b/keystone/controllers.py
@@ -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': 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': 'application/vnd.openstack.identity-v2.0'
- '+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']
+ })
diff --git a/keystone/routers.py b/keystone/routers.py
index 83f277dd..f1a380e7 100644
--- a/keystone/routers.py
+++ b/keystone/routers.py
@@ -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):
diff --git a/keystone/service.py b/keystone/service.py
index 423aee06..6c7587b2 100644
--- a/keystone/service.py
+++ b/keystone/service.py
@@ -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)
diff --git a/tests/test_versions.py b/tests/test_versions.py
index 8faf68ca..0ca2edda 100644
--- a/tests/test_versions.py
+++ b/tests/test_versions.py
@@ -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)