diff options
-rw-r--r-- | etc/keystone.conf | 14 | ||||
-rw-r--r-- | keystone/service.py | 112 | ||||
-rw-r--r-- | tests/test_versions.py | 107 |
3 files changed, 208 insertions, 25 deletions
diff --git a/etc/keystone.conf b/etc/keystone.conf index bbc84b78..fde13004 100644 --- a/etc/keystone.conf +++ b/etc/keystone.conf @@ -68,10 +68,24 @@ pipeline = token_auth admin_token_auth json_body debug ec2_extension public_serv [pipeline:admin_api] pipeline = token_auth admin_token_auth json_body debug ec2_extension crud_extension admin_service +[app:public_version_service] +paste.app_factory = keystone.service:public_version_app_factory + +[app:admin_version_service] +paste.app_factory = keystone.service:admin_version_app_factory + +[pipeline:public_version_api] +pipeline = public_version_service + +[pipeline:admin_version_api] +pipeline = admin_version_service + [composite:main] use = egg:Paste#urlmap /v2.0 = public_api +/ = public_version_api [composite:admin] use = egg:Paste#urlmap /v2.0 = admin_api +/ = admin_version_service diff --git a/keystone/service.py b/keystone/service.py index e2698cf7..96e1cffa 100644 --- a/keystone/service.py +++ b/keystone/service.py @@ -1,8 +1,5 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -import json -import urllib -import urlparse import uuid import routes @@ -15,7 +12,6 @@ from keystone import identity from keystone import policy from keystone import token from keystone.common import logging -from keystone.common import utils from keystone.common import wsgi @@ -43,12 +39,6 @@ class AdminRouter(wsgi.ComposingRouter): conditions=dict(method=['GET'])) # Miscellaneous Operations - version_controller = VersionController() - mapper.connect('/', - controller=version_controller, - action='get_version_info', module='admin/version', - conditions=dict(method=['GET'])) - extensions_controller = ExtensionsController() mapper.connect('/extensions', controller=extensions_controller, @@ -76,13 +66,6 @@ class PublicRouter(wsgi.ComposingRouter): conditions=dict(method=['POST'])) # Miscellaneous - version_controller = VersionController() - mapper.connect('/', - controller=version_controller, - action='get_version_info', - module='service/version', - conditions=dict(method=['GET'])) - extensions_controller = ExtensionsController() mapper.connect('/extensions', controller=extensions_controller, @@ -95,6 +78,81 @@ class PublicRouter(wsgi.ComposingRouter): super(PublicRouter, self).__init__(mapper, routers) +class PublicVersionRouter(wsgi.ComposingRouter): + def __init__(self): + mapper = routes.Mapper() + version_controller = VersionController('public') + mapper.connect('/', + controller=version_controller, + action='get_versions') + routers = [] + super(PublicVersionRouter, self).__init__(mapper, routers) + + +class AdminVersionRouter(wsgi.ComposingRouter): + def __init__(self): + mapper = routes.Mapper() + version_controller = VersionController('admin') + mapper.connect('/', + controller=version_controller, + action='get_versions') + routers = [] + super(AdminVersionRouter, self).__init__(mapper, routers) + + +class VersionController(wsgi.Application): + def __init__(self, version_type): + self.catalog_api = catalog.Manager() + self.url_key = "%sURL" % version_type + super(VersionController, self).__init__() + + def _get_identity_url(self, context): + catalog_ref = self.catalog_api.get_catalog( + context=context, + user_id=None, + tenant_id=None) + for region, region_ref in catalog_ref.iteritems(): + for service, service_ref in region_ref.iteritems(): + if service == 'identity': + return service_ref[self.url_key] + + raise NotImplemented() + + def get_versions(self, context): + identity_url = self._get_identity_url(context) + if not identity_url.endswith('/'): + identity_url = identity_url + '/' + return { + "versions": { + "values": [{ + "id": "v2.0", + "status": "beta", + "updated": "2011-11-19T00:00:00Z", + "links": [{ + "rel": "self", + "href": identity_url, + }, { + "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" + }] + }] + } + } + + class NoopController(wsgi.Application): def __init__(self): super(NoopController, self).__init__() @@ -355,14 +413,6 @@ class TokenController(wsgi.Application): return services.values() -class VersionController(wsgi.Application): - def __init__(self): - super(VersionController, self).__init__() - - def get_version_info(self, context, module='version'): - raise NotImplemented() - - class ExtensionsController(wsgi.Application): def __init__(self): super(ExtensionsController, self).__init__() @@ -381,3 +431,15 @@ def admin_app_factory(global_conf, **local_conf): conf = global_conf.copy() conf.update(local_conf) return AdminRouter() + + +def public_version_app_factory(global_conf, **local_conf): + conf = global_conf.copy() + conf.update(local_conf) + return PublicVersionRouter() + + +def admin_version_app_factory(global_conf, **local_conf): + conf = global_conf.copy() + conf.update(local_conf) + return AdminVersionRouter() diff --git a/tests/test_versions.py b/tests/test_versions.py new file mode 100644 index 00000000..6a088654 --- /dev/null +++ b/tests/test_versions.py @@ -0,0 +1,107 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack, LLC +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import json + +from keystone import test +from keystone import config + + +CONF = config.CONF + + +class VersionTestCase(test.TestCase): + def setUp(self): + super(VersionTestCase, self).setUp() + self.load_backends() + self.public_app = self.loadapp('keystone', 'main') + self.admin_app = self.loadapp('keystone', 'admin') + + self.public_server = self.serveapp('keystone', name='main') + self.admin_server = self.serveapp('keystone', name='admin') + + def test_public_versions(self): + client = self.client(self.public_app) + resp = client.get('/') + data = json.loads(resp.body) + expected = { + "versions": { + "values": [{ + "id": "v2.0", + "status": "beta", + "updated": "2011-11-19T00: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" + }] + }] + } + } + self.assertEqual(data, expected) + + def test_admin_versions(self): + client = self.client(self.admin_app) + resp = client.get('/') + data = json.loads(resp.body) + expected = { + "versions": { + "values": [{ + "id": "v2.0", + "status": "beta", + "updated": "2011-11-19T00: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" + }] + }] + } + } + self.assertEqual(data, expected) |