Merge "module refactoring"
This commit is contained in:
commit
7db702cab1
@ -16,3 +16,4 @@
|
||||
|
||||
from keystone.catalog.core import *
|
||||
from keystone.catalog import controllers
|
||||
from keystone.catalog import routers
|
||||
|
@ -20,18 +20,9 @@ import uuid
|
||||
from keystone.catalog import core
|
||||
from keystone.common import controller
|
||||
from keystone.common import wsgi
|
||||
from keystone import identity
|
||||
from keystone import policy
|
||||
from keystone import token
|
||||
|
||||
|
||||
class Service(wsgi.Application):
|
||||
def __init__(self):
|
||||
self.catalog_api = core.Manager()
|
||||
self.identity_api = identity.Manager()
|
||||
self.policy_api = policy.Manager()
|
||||
self.token_api = token.Manager()
|
||||
super(Service, self).__init__()
|
||||
class Service(controller.V2Controller):
|
||||
|
||||
def get_services(self, context):
|
||||
self.assert_admin(context)
|
||||
@ -57,14 +48,7 @@ class Service(wsgi.Application):
|
||||
return {'OS-KSADM:service': new_service_ref}
|
||||
|
||||
|
||||
class Endpoint(wsgi.Application):
|
||||
def __init__(self):
|
||||
self.catalog_api = core.Manager()
|
||||
self.identity_api = identity.Manager()
|
||||
self.policy_api = policy.Manager()
|
||||
self.token_api = token.Manager()
|
||||
super(Endpoint, self).__init__()
|
||||
|
||||
class Endpoint(controller.V2Controller):
|
||||
def get_endpoints(self, context):
|
||||
self.assert_admin(context)
|
||||
endpoint_list = self.catalog_api.list_endpoints(context)
|
||||
|
25
keystone/catalog/routers.py
Normal file
25
keystone/catalog/routers.py
Normal file
@ -0,0 +1,25 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 OpenStack LLC
|
||||
#
|
||||
# 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.
|
||||
from keystone.catalog import controllers
|
||||
from keystone.common import router
|
||||
from keystone.common import wsgi
|
||||
|
||||
|
||||
def append_v3_routers(mapper, routers, apis):
|
||||
routers.append(router.Router(controllers.ServiceV3(**apis),
|
||||
'services', 'service'))
|
||||
routers.append(router.Router(controllers.EndpointV3(**apis),
|
||||
'endpoints', 'endpoint'))
|
57
keystone/common/router.py
Normal file
57
keystone/common/router.py
Normal file
@ -0,0 +1,57 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 OpenStack LLC
|
||||
#
|
||||
# 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.
|
||||
from keystone.common import wsgi
|
||||
from keystone import config
|
||||
|
||||
|
||||
class Router(wsgi.ComposableRouter):
|
||||
def __init__(self, controller, collection_key, key):
|
||||
self.controller = controller
|
||||
self.key = key
|
||||
self.collection_key = collection_key
|
||||
|
||||
def add_routes(self, mapper):
|
||||
collection_path = '/%(collection_key)s' % {
|
||||
'collection_key': self.collection_key}
|
||||
entity_path = '/%(collection_key)s/{%(key)s_id}' % {
|
||||
'collection_key': self.collection_key,
|
||||
'key': self.key}
|
||||
|
||||
mapper.connect(
|
||||
collection_path,
|
||||
controller=self.controller,
|
||||
action='create_%s' % self.key,
|
||||
conditions=dict(method=['POST']))
|
||||
mapper.connect(
|
||||
collection_path,
|
||||
controller=self.controller,
|
||||
action='list_%s' % self.collection_key,
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect(
|
||||
entity_path,
|
||||
controller=self.controller,
|
||||
action='get_%s' % self.key,
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect(
|
||||
entity_path,
|
||||
controller=self.controller,
|
||||
action='update_%s' % self.key,
|
||||
conditions=dict(method=['PATCH']))
|
||||
mapper.connect(
|
||||
entity_path,
|
||||
controller=self.controller,
|
||||
action='delete_%s' % self.key,
|
||||
conditions=dict(method=['DELETE']))
|
@ -13,10 +13,11 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from keystone import catalog
|
||||
from keystone.common import wsgi
|
||||
from keystone import identity
|
||||
from keystone import policy
|
||||
from keystone import token
|
||||
|
||||
|
||||
class CrudExtension(wsgi.ExtensionRouter):
|
||||
@ -27,11 +28,16 @@ class CrudExtension(wsgi.ExtensionRouter):
|
||||
"""
|
||||
|
||||
def add_routes(self, mapper):
|
||||
tenant_controller = identity.controllers.Tenant()
|
||||
user_controller = identity.controllers.User()
|
||||
role_controller = identity.controllers.Role()
|
||||
service_controller = catalog.controllers.Service()
|
||||
endpoint_controller = catalog.controllers.Endpoint()
|
||||
apis = dict(catalog_api=catalog.Manager(),
|
||||
identity_api=identity.Manager(),
|
||||
policy_api=policy.Manager(),
|
||||
token_api=token.Manager())
|
||||
|
||||
tenant_controller = identity.controllers.Tenant(**apis)
|
||||
user_controller = identity.controllers.User(**apis)
|
||||
role_controller = identity.controllers.Role(**apis)
|
||||
service_controller = catalog.controllers.Service(**apis)
|
||||
endpoint_controller = catalog.controllers.Endpoint(**apis)
|
||||
|
||||
# Tenant Operations
|
||||
mapper.connect(
|
||||
|
@ -18,21 +18,19 @@ import copy
|
||||
import uuid
|
||||
|
||||
from keystone import exception
|
||||
from keystone.common import controller
|
||||
from keystone.common import logging
|
||||
from keystone.common import wsgi
|
||||
from keystone import catalog
|
||||
from keystone import identity
|
||||
from keystone import policy
|
||||
from keystone import token
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UserController(wsgi.Application):
|
||||
def __init__(self):
|
||||
self.identity_api = identity.Manager()
|
||||
self.token_api = token.Manager()
|
||||
self.user_controller = identity.controllers.User()
|
||||
|
||||
class UserController(identity.controllers.User):
|
||||
def set_user_password(self, context, user_id, user):
|
||||
token_id = context.get('token_id')
|
||||
original_password = user.get('original_password')
|
||||
@ -62,9 +60,9 @@ class UserController(wsgi.Application):
|
||||
|
||||
admin_context = copy.copy(context)
|
||||
admin_context['is_admin'] = True
|
||||
self.user_controller.set_user_password(admin_context,
|
||||
user_id,
|
||||
update_dict)
|
||||
super(UserController, self).set_user_password(admin_context,
|
||||
user_id,
|
||||
update_dict)
|
||||
|
||||
token_id = uuid.uuid4().hex
|
||||
new_token_ref = copy.copy(token_ref)
|
||||
@ -83,7 +81,12 @@ class CrudExtension(wsgi.ExtensionRouter):
|
||||
"""
|
||||
|
||||
def add_routes(self, mapper):
|
||||
user_controller = UserController()
|
||||
apis = dict(catalog_api=catalog.Manager(),
|
||||
identity_api=identity.Manager(),
|
||||
policy_api=policy.Manager(),
|
||||
token_api=token.Manager())
|
||||
|
||||
user_controller = UserController(**apis)
|
||||
|
||||
mapper.connect('/OS-KSCRUD/users/{user_id}',
|
||||
controller=user_controller,
|
||||
|
144
keystone/controllers.py
Normal file
144
keystone/controllers.py
Normal file
@ -0,0 +1,144 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 OpenStack LLC
|
||||
#
|
||||
# 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.
|
||||
|
||||
from keystone.common import wsgi
|
||||
from keystone import catalog
|
||||
from keystone import exception
|
||||
|
||||
|
||||
class Extensions(wsgi.Application):
|
||||
"""Base extensions controller to be extended by public and admin API's."""
|
||||
|
||||
def __init__(self, extensions=None):
|
||||
super(Extensions, self).__init__()
|
||||
|
||||
self.extensions = extensions or {}
|
||||
|
||||
def get_extensions_info(self, context):
|
||||
return {'extensions': {'values': self.extensions.values()}}
|
||||
|
||||
def get_extension_info(self, context, extension_alias):
|
||||
try:
|
||||
return {'extension': self.extensions[extension_alias]}
|
||||
except KeyError:
|
||||
raise exception.NotFound(target=extension_alias)
|
||||
|
||||
|
||||
class AdminExtensions(Extensions):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AdminExtensions, self).__init__(*args, **kwargs)
|
||||
|
||||
# TODO(dolph): Extensions should obviously provide this information
|
||||
# themselves, but hardcoding it here allows us to match
|
||||
# the API spec in the short term with minimal complexity.
|
||||
self.extensions['OS-KSADM'] = {
|
||||
'name': 'Openstack Keystone Admin',
|
||||
'namespace': 'http://docs.openstack.org/identity/api/ext/'
|
||||
'OS-KSADM/v1.0',
|
||||
'alias': 'OS-KSADM',
|
||||
'updated': '2011-08-19T13:25:27-06:00',
|
||||
'description': 'Openstack extensions to Keystone v2.0 API '
|
||||
'enabling Admin Operations.',
|
||||
'links': [
|
||||
{
|
||||
'rel': 'describedby',
|
||||
# TODO(dolph): link needs to be revised after
|
||||
# bug 928059 merges
|
||||
'type': 'text/html',
|
||||
'href': 'https://github.com/openstack/identity-api',
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
class PublicExtensions(Extensions):
|
||||
pass
|
||||
|
||||
|
||||
class Version(wsgi.Application):
|
||||
def __init__(self, version_type):
|
||||
self.catalog_api = catalog.Manager()
|
||||
self.url_key = '%sURL' % version_type
|
||||
|
||||
super(Version, 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 exception.NotImplemented()
|
||||
|
||||
def _get_versions_list(self, context):
|
||||
"""The list of versions is dependent on the context."""
|
||||
identity_url = self._get_identity_url(context)
|
||||
if not identity_url.endswith('/'):
|
||||
identity_url = identity_url + '/'
|
||||
|
||||
versions = {}
|
||||
versions['v2.0'] = {
|
||||
'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'
|
||||
}, {
|
||||
'base': 'application/xml',
|
||||
'type': 'application/vnd.openstack.identity-v2.0'
|
||||
'+xml'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return versions
|
||||
|
||||
def get_versions(self, context):
|
||||
versions = self._get_versions_list(context)
|
||||
return wsgi.render_response(status=(300, 'Multiple Choices'), body={
|
||||
'versions': {
|
||||
'values': versions.values()
|
||||
}
|
||||
})
|
||||
|
||||
def get_version(self, context):
|
||||
versions = self._get_versions_list(context)
|
||||
return wsgi.render_response(body={
|
||||
'version': versions['v2.0']
|
||||
})
|
@ -32,13 +32,7 @@ from keystone import token
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Tenant(wsgi.Application):
|
||||
def __init__(self):
|
||||
self.identity_api = core.Manager()
|
||||
self.policy_api = policy.Manager()
|
||||
self.token_api = token.Manager()
|
||||
super(Tenant, self).__init__()
|
||||
|
||||
class Tenant(controller.V2Controller):
|
||||
def get_all_tenants(self, context, **kw):
|
||||
"""Gets a list of all tenants for an admin user."""
|
||||
if 'name' in context['query_string']:
|
||||
@ -157,13 +151,7 @@ class Tenant(wsgi.Application):
|
||||
return o
|
||||
|
||||
|
||||
class User(wsgi.Application):
|
||||
def __init__(self):
|
||||
self.identity_api = core.Manager()
|
||||
self.policy_api = policy.Manager()
|
||||
self.token_api = token.Manager()
|
||||
super(User, self).__init__()
|
||||
|
||||
class User(controller.V2Controller):
|
||||
def get_user(self, context, user_id):
|
||||
self.assert_admin(context)
|
||||
return {'user': self.identity_api.get_user(context, user_id)}
|
||||
@ -240,13 +228,7 @@ class User(wsgi.Application):
|
||||
return self.update_user(context, user_id, user)
|
||||
|
||||
|
||||
class Role(wsgi.Application):
|
||||
def __init__(self):
|
||||
self.identity_api = core.Manager()
|
||||
self.token_api = token.Manager()
|
||||
self.policy_api = policy.Manager()
|
||||
super(Role, self).__init__()
|
||||
|
||||
class Role(controller.V2Controller):
|
||||
# COMPAT(essex-3)
|
||||
def get_user_roles(self, context, user_id, tenant_id=None):
|
||||
"""Get the roles for a user and tenant pair.
|
||||
|
@ -13,16 +13,19 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""WSGI Routers for the Identity service."""
|
||||
|
||||
from keystone.common import wsgi
|
||||
from keystone.identity import controllers
|
||||
from keystone.common import router
|
||||
|
||||
|
||||
class Public(wsgi.ComposableRouter):
|
||||
def __init__(self, apis):
|
||||
self.apis = apis
|
||||
super(Public, self).__init__()
|
||||
|
||||
def add_routes(self, mapper):
|
||||
tenant_controller = controllers.Tenant()
|
||||
tenant_controller = controllers.Tenant(**self.apis)
|
||||
mapper.connect('/tenants',
|
||||
controller=tenant_controller,
|
||||
action='get_tenants_for_token',
|
||||
@ -30,9 +33,13 @@ class Public(wsgi.ComposableRouter):
|
||||
|
||||
|
||||
class Admin(wsgi.ComposableRouter):
|
||||
def __init__(self, apis):
|
||||
self.apis = apis
|
||||
super(Admin, self).__init__()
|
||||
|
||||
def add_routes(self, mapper):
|
||||
# Tenant Operations
|
||||
tenant_controller = controllers.Tenant()
|
||||
tenant_controller = controllers.Tenant(**self.apis)
|
||||
mapper.connect('/tenants',
|
||||
controller=tenant_controller,
|
||||
action='get_all_tenants',
|
||||
@ -43,14 +50,14 @@ class Admin(wsgi.ComposableRouter):
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
# User Operations
|
||||
user_controller = controllers.User()
|
||||
user_controller = controllers.User(**self.apis)
|
||||
mapper.connect('/users/{user_id}',
|
||||
controller=user_controller,
|
||||
action='get_user',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
# Role Operations
|
||||
roles_controller = controllers.Role()
|
||||
roles_controller = controllers.Role(**self.apis)
|
||||
mapper.connect('/tenants/{tenant_id}/users/{user_id}/roles',
|
||||
controller=roles_controller,
|
||||
action='get_user_roles',
|
||||
@ -59,3 +66,57 @@ class Admin(wsgi.ComposableRouter):
|
||||
controller=roles_controller,
|
||||
action='get_user_roles',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
|
||||
def append_v3_routers(mapper, routers, apis):
|
||||
routers.append(
|
||||
router.Router(controllers.DomainV3(**apis),
|
||||
'domains', 'domain'))
|
||||
project_controller = controllers.ProjectV3(**apis)
|
||||
routers.append(
|
||||
router.Router(project_controller,
|
||||
'projects', 'project'))
|
||||
mapper.connect('/users/{user_id}/projects',
|
||||
controller=project_controller,
|
||||
action='list_user_projects',
|
||||
conditions=dict(method=['GET']))
|
||||
routers.append(
|
||||
router.Router(controllers.UserV3(**apis),
|
||||
'users', 'user'))
|
||||
routers.append(
|
||||
router.Router(controllers.CredentialV3(**apis),
|
||||
'credentials', 'credential'))
|
||||
role_controller = controllers.RoleV3(**apis)
|
||||
routers.append(router.Router(role_controller, 'roles', 'role'))
|
||||
mapper.connect('/projects/{project_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='create_grant',
|
||||
conditions=dict(method=['PUT']))
|
||||
mapper.connect('/projects/{project_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='check_grant',
|
||||
conditions=dict(method=['HEAD']))
|
||||
mapper.connect('/projects/{project_id}/users/{user_id}/roles',
|
||||
controller=role_controller,
|
||||
action='list_grants',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect('/projects/{project_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='revoke_grant',
|
||||
conditions=dict(method=['DELETE']))
|
||||
mapper.connect('/domains/{domain_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='create_grant',
|
||||
conditions=dict(method=['PUT']))
|
||||
mapper.connect('/domains/{domain_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='check_grant',
|
||||
conditions=dict(method=['HEAD']))
|
||||
mapper.connect('/domains/{domain_id}/users/{user_id}/roles',
|
||||
controller=role_controller,
|
||||
action='list_grants',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect('/domains/{domain_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='revoke_grant',
|
||||
conditions=dict(method=['DELETE']))
|
||||
|
@ -16,3 +16,4 @@
|
||||
|
||||
from keystone.policy.core import *
|
||||
from keystone.policy import controllers
|
||||
from keystone.policy import routers
|
||||
|
22
keystone/policy/routers.py
Normal file
22
keystone/policy/routers.py
Normal file
@ -0,0 +1,22 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 OpenStack LLC
|
||||
#
|
||||
# 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.
|
||||
from keystone.policy import controllers
|
||||
from keystone.common import router
|
||||
|
||||
|
||||
def append_v3_routers(mapper, routers, apis):
|
||||
policy_controller = controllers.PolicyV3(**apis)
|
||||
routers.append(router.Router(policy_controller, 'policies', 'policy'))
|
68
keystone/routers.py
Normal file
68
keystone/routers.py
Normal file
@ -0,0 +1,68 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 OpenStack LLC
|
||||
#
|
||||
# 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.
|
||||
"""
|
||||
The only types of routers in this file should be ComposingRouters.
|
||||
The routers for the submodules should be in the module specific router files
|
||||
for example, the Composable Router for identity belongs in
|
||||
keystone/identity/routers.py
|
||||
"""
|
||||
|
||||
|
||||
from keystone.common import wsgi
|
||||
from keystone import catalog
|
||||
from keystone import controllers
|
||||
from keystone import exception
|
||||
|
||||
|
||||
class Extension(wsgi.ComposableRouter):
|
||||
def __init__(self, is_admin=True):
|
||||
if is_admin:
|
||||
self.controller = controllers.AdminExtensions()
|
||||
else:
|
||||
self.controller = controllers.PublicExtensions()
|
||||
|
||||
def add_routes(self, mapper):
|
||||
extensions_controller = self.controller
|
||||
mapper.connect('/extensions',
|
||||
controller=extensions_controller,
|
||||
action='get_extensions_info',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect('/extensions/{extension_alias}',
|
||||
controller=extensions_controller,
|
||||
action='get_extension_info',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
|
||||
class Version(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')
|
||||
|
||||
|
||||
class Versions(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_versions')
|
@ -22,484 +22,64 @@ from keystone.common import wsgi
|
||||
from keystone import exception
|
||||
from keystone import identity
|
||||
from keystone import policy
|
||||
from keystone import routers
|
||||
from keystone import token
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class V3Router(wsgi.ComposingRouter):
|
||||
def crud_routes(self, mapper, controller, collection_key, key):
|
||||
collection_path = '/%(collection_key)s' % {
|
||||
'collection_key': collection_key}
|
||||
entity_path = '/%(collection_key)s/{%(key)s_id}' % {
|
||||
'collection_key': collection_key,
|
||||
'key': key}
|
||||
|
||||
mapper.connect(
|
||||
collection_path,
|
||||
controller=controller,
|
||||
action='create_%s' % key,
|
||||
conditions=dict(method=['POST']))
|
||||
mapper.connect(
|
||||
collection_path,
|
||||
controller=controller,
|
||||
action='list_%s' % collection_key,
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect(
|
||||
entity_path,
|
||||
controller=controller,
|
||||
action='get_%s' % key,
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect(
|
||||
entity_path,
|
||||
controller=controller,
|
||||
action='update_%s' % key,
|
||||
conditions=dict(method=['PATCH']))
|
||||
mapper.connect(
|
||||
entity_path,
|
||||
controller=controller,
|
||||
action='delete_%s' % key,
|
||||
conditions=dict(method=['DELETE']))
|
||||
|
||||
def __init__(self):
|
||||
mapper = routes.Mapper()
|
||||
|
||||
apis = dict(
|
||||
catalog_api=catalog.Manager(),
|
||||
identity_api=identity.Manager(),
|
||||
policy_api=policy.Manager(),
|
||||
token_api=token.Manager())
|
||||
|
||||
# Catalog
|
||||
|
||||
self.crud_routes(
|
||||
mapper,
|
||||
catalog.controllers.ServiceV3(**apis),
|
||||
'services',
|
||||
'service')
|
||||
|
||||
self.crud_routes(
|
||||
mapper,
|
||||
catalog.controllers.EndpointV3(**apis),
|
||||
'endpoints',
|
||||
'endpoint')
|
||||
|
||||
# Identity
|
||||
|
||||
self.crud_routes(
|
||||
mapper,
|
||||
identity.controllers.DomainV3(**apis),
|
||||
'domains',
|
||||
'domain')
|
||||
|
||||
project_controller = identity.controllers.ProjectV3(**apis)
|
||||
self.crud_routes(
|
||||
mapper,
|
||||
project_controller,
|
||||
'projects',
|
||||
'project')
|
||||
mapper.connect(
|
||||
'/users/{user_id}/projects',
|
||||
controller=project_controller,
|
||||
action='list_user_projects',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
self.crud_routes(
|
||||
mapper,
|
||||
identity.controllers.UserV3(**apis),
|
||||
'users',
|
||||
'user')
|
||||
|
||||
self.crud_routes(
|
||||
mapper,
|
||||
identity.controllers.CredentialV3(**apis),
|
||||
'credentials',
|
||||
'credential')
|
||||
|
||||
role_controller = identity.controllers.RoleV3(**apis)
|
||||
self.crud_routes(
|
||||
mapper,
|
||||
role_controller,
|
||||
'roles',
|
||||
'role')
|
||||
mapper.connect(
|
||||
'/projects/{project_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='create_grant',
|
||||
conditions=dict(method=['PUT']))
|
||||
mapper.connect(
|
||||
'/projects/{project_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='check_grant',
|
||||
conditions=dict(method=['HEAD']))
|
||||
mapper.connect(
|
||||
'/projects/{project_id}/users/{user_id}/roles',
|
||||
controller=role_controller,
|
||||
action='list_grants',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect(
|
||||
'/projects/{project_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='revoke_grant',
|
||||
conditions=dict(method=['DELETE']))
|
||||
mapper.connect(
|
||||
'/domains/{domain_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='create_grant',
|
||||
conditions=dict(method=['PUT']))
|
||||
mapper.connect(
|
||||
'/domains/{domain_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='check_grant',
|
||||
conditions=dict(method=['HEAD']))
|
||||
mapper.connect(
|
||||
'/domains/{domain_id}/users/{user_id}/roles',
|
||||
controller=role_controller,
|
||||
action='list_grants',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect(
|
||||
'/domains/{domain_id}/users/{user_id}/roles/{role_id}',
|
||||
controller=role_controller,
|
||||
action='revoke_grant',
|
||||
conditions=dict(method=['DELETE']))
|
||||
|
||||
# Policy
|
||||
|
||||
policy_controller = policy.controllers.PolicyV3(**apis)
|
||||
self.crud_routes(
|
||||
mapper,
|
||||
policy_controller,
|
||||
'policies',
|
||||
'policy')
|
||||
|
||||
# Token
|
||||
|
||||
"""
|
||||
# v2.0 LEGACY
|
||||
mapper.connect('/tokens/{token_id}',
|
||||
controller=auth_controller,
|
||||
action='validate_token',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect('/tokens/{token_id}',
|
||||
controller=auth_controller,
|
||||
action='validate_token_head',
|
||||
conditions=dict(method=['HEAD']))
|
||||
mapper.connect('/tokens/{token_id}',
|
||||
controller=auth_controller,
|
||||
action='delete_token',
|
||||
conditions=dict(method=['DELETE']))
|
||||
mapper.connect('/tokens/{token_id}/endpoints',
|
||||
controller=auth_controller,
|
||||
action='endpoints',
|
||||
conditions=dict(method=['GET']))
|
||||
"""
|
||||
|
||||
super(V3Router, self).__init__(mapper, [])
|
||||
|
||||
|
||||
class AdminRouter(wsgi.ComposingRouter):
|
||||
def __init__(self):
|
||||
mapper = routes.Mapper()
|
||||
|
||||
apis = dict(
|
||||
catalog_api=catalog.Manager(),
|
||||
identity_api=identity.Manager(),
|
||||
policy_api=policy.Manager(),
|
||||
token_api=token.Manager())
|
||||
|
||||
version_controller = VersionController('admin')
|
||||
mapper.connect('/',
|
||||
controller=version_controller,
|
||||
action='get_version')
|
||||
|
||||
# Token Operations
|
||||
auth_controller = token.controllers.Auth(**apis)
|
||||
mapper.connect('/tokens',
|
||||
controller=auth_controller,
|
||||
action='authenticate',
|
||||
conditions=dict(method=['POST']))
|
||||
mapper.connect('/tokens/revoked',
|
||||
controller=auth_controller,
|
||||
action='revocation_list',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect('/tokens/{token_id}',
|
||||
controller=auth_controller,
|
||||
action='validate_token',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect('/tokens/{token_id}',
|
||||
controller=auth_controller,
|
||||
action='validate_token_head',
|
||||
conditions=dict(method=['HEAD']))
|
||||
mapper.connect('/tokens/{token_id}',
|
||||
controller=auth_controller,
|
||||
action='delete_token',
|
||||
conditions=dict(method=['DELETE']))
|
||||
mapper.connect('/tokens/{token_id}/endpoints',
|
||||
controller=auth_controller,
|
||||
action='endpoints',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
# Certificates used to verify auth tokens
|
||||
mapper.connect('/certificates/ca',
|
||||
controller=auth_controller,
|
||||
action='ca_cert',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
mapper.connect('/certificates/signing',
|
||||
controller=auth_controller,
|
||||
action='signing_cert',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
# Miscellaneous Operations
|
||||
extensions_controller = AdminExtensionsController()
|
||||
mapper.connect('/extensions',
|
||||
controller=extensions_controller,
|
||||
action='get_extensions_info',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect('/extensions/{extension_alias}',
|
||||
controller=extensions_controller,
|
||||
action='get_extension_info',
|
||||
conditions=dict(method=['GET']))
|
||||
identity_router = identity.routers.Admin()
|
||||
routers = [identity_router]
|
||||
super(AdminRouter, self).__init__(mapper, routers)
|
||||
|
||||
|
||||
class PublicRouter(wsgi.ComposingRouter):
|
||||
def __init__(self):
|
||||
mapper = routes.Mapper()
|
||||
|
||||
apis = dict(
|
||||
catalog_api=catalog.Manager(),
|
||||
identity_api=identity.Manager(),
|
||||
policy_api=policy.Manager(),
|
||||
token_api=token.Manager())
|
||||
|
||||
version_controller = VersionController('public')
|
||||
mapper.connect('/',
|
||||
controller=version_controller,
|
||||
action='get_version')
|
||||
|
||||
# Token Operations
|
||||
auth_controller = token.controllers.Auth(**apis)
|
||||
mapper.connect('/tokens',
|
||||
controller=auth_controller,
|
||||
action='authenticate',
|
||||
conditions=dict(method=['POST']))
|
||||
|
||||
mapper.connect('/certificates/ca',
|
||||
controller=auth_controller,
|
||||
action='ca_cert',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
mapper.connect('/certificates/signing',
|
||||
controller=auth_controller,
|
||||
action='signing_cert',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
# Miscellaneous
|
||||
extensions_controller = PublicExtensionsController()
|
||||
mapper.connect('/extensions',
|
||||
controller=extensions_controller,
|
||||
action='get_extensions_info',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect('/extensions/{extension_alias}',
|
||||
controller=extensions_controller,
|
||||
action='get_extension_info',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
identity_router = identity.routers.Public()
|
||||
routers = [identity_router]
|
||||
|
||||
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 exception.NotImplemented()
|
||||
|
||||
def _get_versions_list(self, context):
|
||||
"""The list of versions is dependent on the context."""
|
||||
identity_url = self._get_identity_url(context)
|
||||
if not identity_url.endswith('/'):
|
||||
identity_url = identity_url + '/'
|
||||
|
||||
versions = {}
|
||||
versions['v2.0'] = {
|
||||
'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'
|
||||
}, {
|
||||
'base': 'application/xml',
|
||||
'type': 'application/vnd.openstack.identity-v2.0'
|
||||
'+xml'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return versions
|
||||
|
||||
def get_versions(self, context):
|
||||
versions = self._get_versions_list(context)
|
||||
return wsgi.render_response(status=(300, 'Multiple Choices'), body={
|
||||
'versions': {
|
||||
'values': versions.values()
|
||||
}
|
||||
})
|
||||
|
||||
def get_version(self, context):
|
||||
versions = self._get_versions_list(context)
|
||||
return wsgi.render_response(body={
|
||||
'version': versions['v2.0']
|
||||
})
|
||||
|
||||
|
||||
class NoopController(wsgi.Application):
|
||||
def __init__(self):
|
||||
super(NoopController, self).__init__()
|
||||
|
||||
def noop(self, context):
|
||||
return {}
|
||||
|
||||
|
||||
class ExtensionsController(wsgi.Application):
|
||||
"""Base extensions controller to be extended by public and admin API's."""
|
||||
|
||||
def __init__(self, extensions=None):
|
||||
super(ExtensionsController, self).__init__()
|
||||
|
||||
self.extensions = extensions or {}
|
||||
|
||||
def get_extensions_info(self, context):
|
||||
return {'extensions': {'values': self.extensions.values()}}
|
||||
|
||||
def get_extension_info(self, context, extension_alias):
|
||||
try:
|
||||
return {'extension': self.extensions[extension_alias]}
|
||||
except KeyError:
|
||||
raise exception.NotFound(target=extension_alias)
|
||||
|
||||
|
||||
class PublicExtensionsController(ExtensionsController):
|
||||
pass
|
||||
|
||||
|
||||
class AdminExtensionsController(ExtensionsController):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AdminExtensionsController, self).__init__(*args, **kwargs)
|
||||
|
||||
# TODO(dolph): Extensions should obviously provide this information
|
||||
# themselves, but hardcoding it here allows us to match
|
||||
# the API spec in the short term with minimal complexity.
|
||||
self.extensions['OS-KSADM'] = {
|
||||
'name': 'Openstack Keystone Admin',
|
||||
'namespace': 'http://docs.openstack.org/identity/api/ext/'
|
||||
'OS-KSADM/v1.0',
|
||||
'alias': 'OS-KSADM',
|
||||
'updated': '2011-08-19T13:25:27-06:00',
|
||||
'description': 'Openstack extensions to Keystone v2.0 API '
|
||||
'enabling Admin Operations.',
|
||||
'links': [
|
||||
{
|
||||
'rel': 'describedby',
|
||||
# TODO(dolph): link needs to be revised after
|
||||
# bug 928059 merges
|
||||
'type': 'text/html',
|
||||
'href': 'https://github.com/openstack/identity-api',
|
||||
}
|
||||
]
|
||||
}
|
||||
def _apis():
|
||||
return dict(catalog_api=catalog.Manager(),
|
||||
identity_api=identity.Manager(),
|
||||
policy_api=policy.Manager(),
|
||||
token_api=token.Manager())
|
||||
|
||||
|
||||
@logging.fail_gracefully
|
||||
def public_app_factory(global_conf, **local_conf):
|
||||
conf = global_conf.copy()
|
||||
conf.update(local_conf)
|
||||
return PublicRouter()
|
||||
return wsgi.ComposingRouter(routes.Mapper(),
|
||||
[identity.routers.Public(_apis()),
|
||||
token.routers.Router(_apis()),
|
||||
routers.Version('public'),
|
||||
routers.Extension(False)])
|
||||
|
||||
|
||||
@logging.fail_gracefully
|
||||
def admin_app_factory(global_conf, **local_conf):
|
||||
conf = global_conf.copy()
|
||||
conf.update(local_conf)
|
||||
return AdminRouter()
|
||||
return wsgi.ComposingRouter(routes.Mapper(),
|
||||
[identity.routers.Admin(_apis()),
|
||||
token.routers.Router(_apis()),
|
||||
routers.Version('admin'),
|
||||
routers.Extension()])
|
||||
|
||||
|
||||
@logging.fail_gracefully
|
||||
def public_version_app_factory(global_conf, **local_conf):
|
||||
conf = global_conf.copy()
|
||||
conf.update(local_conf)
|
||||
return PublicVersionRouter()
|
||||
return wsgi.ComposingRouter(routes.Mapper(),
|
||||
[routers.Versions('public')])
|
||||
|
||||
|
||||
@logging.fail_gracefully
|
||||
def admin_version_app_factory(global_conf, **local_conf):
|
||||
conf = global_conf.copy()
|
||||
conf.update(local_conf)
|
||||
return AdminVersionRouter()
|
||||
return wsgi.ComposingRouter(routes.Mapper(),
|
||||
[routers.Versions('admin')])
|
||||
|
||||
|
||||
@logging.fail_gracefully
|
||||
def v3_app_factory(global_conf, **local_conf):
|
||||
conf = global_conf.copy()
|
||||
conf.update(local_conf)
|
||||
return V3Router()
|
||||
mapper = routes.Mapper()
|
||||
v3routers = []
|
||||
for module in [catalog, identity, policy]:
|
||||
module.routers.append_v3_routers(mapper, v3routers, _apis())
|
||||
#TODO put token routes here
|
||||
return wsgi.ComposingRouter(mapper, v3routers)
|
||||
|
@ -16,3 +16,4 @@
|
||||
|
||||
from keystone.token.core import *
|
||||
from keystone.token import controllers
|
||||
from keystone.token import routers
|
||||
|
61
keystone/token/routers.py
Normal file
61
keystone/token/routers.py
Normal file
@ -0,0 +1,61 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 OpenStack LLC
|
||||
#
|
||||
# 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.
|
||||
from keystone.common import wsgi
|
||||
from keystone.token import controllers
|
||||
|
||||
|
||||
class Router(wsgi.ComposableRouter):
|
||||
def __init__(self, apis):
|
||||
self.apis = apis
|
||||
super(Router, self).__init__()
|
||||
|
||||
def add_routes(self, mapper):
|
||||
token_controller = controllers.Auth(**self.apis)
|
||||
mapper.connect('/tokens',
|
||||
controller=token_controller,
|
||||
action='authenticate',
|
||||
conditions=dict(method=['POST']))
|
||||
mapper.connect('/tokens/revoked',
|
||||
controller=token_controller,
|
||||
action='revocation_list',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect('/tokens/{token_id}',
|
||||
controller=token_controller,
|
||||
action='validate_token',
|
||||
conditions=dict(method=['GET']))
|
||||
mapper.connect('/tokens/{token_id}',
|
||||
controller=token_controller,
|
||||
action='validate_token_head',
|
||||
conditions=dict(method=['HEAD']))
|
||||
mapper.connect('/tokens/{token_id}',
|
||||
controller=token_controller,
|
||||
action='delete_token',
|
||||
conditions=dict(method=['DELETE']))
|
||||
mapper.connect('/tokens/{token_id}/endpoints',
|
||||
controller=token_controller,
|
||||
action='endpoints',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
# Certificates used to verify auth tokens
|
||||
mapper.connect('/certificates/ca',
|
||||
controller=token_controller,
|
||||
action='ca_cert',
|
||||
conditions=dict(method=['GET']))
|
||||
|
||||
mapper.connect('/certificates/signing',
|
||||
controller=token_controller,
|
||||
action='signing_cert',
|
||||
conditions=dict(method=['GET']))
|
Loading…
x
Reference in New Issue
Block a user