Merge remote-tracking branch 'origin/feature/keystone-v3' into HEAD

Conflicts:
	keystone/catalog/core.py
	keystone/identity/core.py

Change-Id: Id47b9dd9c4da811d13454b539f78b751d40ed87d
This commit is contained in:
Dolph Mathews 2012-11-02 14:52:38 -05:00
commit 86aaff4a50
7 changed files with 880 additions and 81 deletions

View File

@ -183,6 +183,9 @@ paste.filter_factory = keystone.contrib.stats:StatsExtension.factory
[app:public_service]
paste.app_factory = keystone.service:public_app_factory
[app:service_v3]
paste.app_factory = keystone.service:v3_app_factory
[app:admin_service]
paste.app_factory = keystone.service:admin_app_factory
@ -192,6 +195,9 @@ pipeline = stats_monitoring url_normalize token_auth admin_token_auth xml_body j
[pipeline:admin_api]
pipeline = stats_monitoring url_normalize token_auth admin_token_auth xml_body json_body debug stats_reporting ec2_extension s3_extension crud_extension admin_service
[pipeline:api_v3]
pipeline = stats_monitoring url_normalize token_auth admin_token_auth xml_body json_body debug stats_reporting ec2_extension s3_extension service_v3
[app:public_version_service]
paste.app_factory = keystone.service:public_version_app_factory
@ -207,9 +213,11 @@ pipeline = stats_monitoring url_normalize xml_body admin_version_service
[composite:main]
use = egg:Paste#urlmap
/v2.0 = public_api
/v3 = api_v3
/ = public_version_api
[composite:admin]
use = egg:Paste#urlmap
/v2.0 = admin_api
/v3 = api_v3
/ = admin_version_api

View File

@ -19,6 +19,7 @@
import uuid
from keystone.common import controller
from keystone.common import logging
from keystone.common import manager
from keystone.common import wsgi
@ -106,6 +107,14 @@ class Manager(manager.Manager):
class Driver(object):
"""Interface description for an Catalog driver."""
def create_service(self, service_id, service_ref):
"""Creates a new service.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented()
def list_services(self):
"""List all service ids in catalog.
@ -114,6 +123,14 @@ class Driver(object):
"""
raise exception.NotImplemented()
def get_all_services(self):
"""List all services.
:returns: list of service_refs or an empty list.
"""
raise exception.NotImplemented()
def get_service(self, service_id):
"""Get service by id.
@ -123,6 +140,15 @@ class Driver(object):
"""
raise exception.NotImplemented()
def update_service(self, service_id):
"""Update service by id.
:returns: service_ref dict
:raises: keystone.exception.ServiceNotFound
"""
raise exception.NotImplemented()
def delete_service(self, service_id):
"""Deletes an existing service.
@ -131,14 +157,6 @@ class Driver(object):
"""
raise exception.NotImplemented()
def create_service(self, service_id, service_ref):
"""Creates a new service.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented()
def create_endpoint(self, endpoint_id, endpoint_ref):
"""Creates a new endpoint for a service.
@ -148,14 +166,6 @@ class Driver(object):
"""
raise exception.NotImplemented()
def delete_endpoint(self, endpoint_id):
"""Deletes an endpoint for a service.
:raises: keystone.exception.EndpointNotFound
"""
raise exception.NotImplemented()
def get_endpoint(self, endpoint_id):
"""Get endpoint by id.
@ -173,6 +183,32 @@ class Driver(object):
"""
raise exception.NotImplemented()
def get_all_endpoints(self):
"""List all endpoints.
:returns: list of endpoint_refs or an empty list.
"""
raise exception.NotImplemented()
def update_endpoint(self, endpoint_id, endpoint_ref):
"""Get endpoint by id.
:returns: endpoint_ref dict
:raises: keystone.exception.EndpointNotFound
keystone.exception.ServiceNotFound
"""
raise exception.NotImplemented()
def delete_endpoint(self, endpoint_id):
"""Deletes an endpoint for a service.
:raises: keystone.exception.EndpointNotFound
"""
raise exception.NotImplemented()
def get_catalog(self, user_id, tenant_id, metadata=None):
"""Retreive and format the current service catalog.
@ -261,3 +297,82 @@ class EndpointController(wsgi.Application):
def delete_endpoint(self, context, endpoint_id):
self.assert_admin(context)
self.catalog_api.delete_endpoint(context, endpoint_id)
class ServiceControllerV3(controller.V3Controller):
def create_service(self, context, service):
self.assert_admin(context)
ref = self._assign_unique_id(self._normalize_dict(service))
self._require_attribute(ref, 'type')
ref = self.catalog_api.create_service(context, ref['id'], ref)
return {'service': ref}
def list_services(self, context):
self.assert_admin(context)
refs = self.catalog_api.get_all_services(context)
refs = self._filter_by_attribute(context, refs, 'type')
return {'services': self._paginate(context, refs)}
def get_service(self, context, service_id):
self.assert_admin(context)
ref = self.catalog_api.get_service(context, service_id)
return {'service': ref}
def update_service(self, context, service_id, service):
self.assert_admin(context)
self._require_matching_id(service_id, service)
ref = self.catalog_api.update_service(context, service_id, service)
return {'service': ref}
def delete_service(self, context, service_id):
self.assert_admin(context)
return self.catalog_api.delete_service(context, service_id)
class EndpointControllerV3(controller.V3Controller):
def create_endpoint(self, context, endpoint):
self.assert_admin(context)
ref = self._assign_unique_id(self._normalize_dict(endpoint))
self._require_attribute(ref, 'service_id')
self._require_attribute(ref, 'interface')
self.catalog_api.get_service(context, ref['service_id'])
ref = self.catalog_api.create_endpoint(context, ref['id'], ref)
return {'endpoint': ref}
def list_endpoints(self, context):
self.assert_admin(context)
refs = self.catalog_api.get_all_endpoints(context)
refs = self._filter_by_attribute(context, refs, 'service_id')
refs = self._filter_by_attribute(context, refs, 'interface')
return {'endpoints': self._paginate(context, refs)}
def get_endpoint(self, context, endpoint_id):
self.assert_admin(context)
ref = self.catalog_api.get_endpoint(context, endpoint_id)
return {'endpoint': ref}
def update_endpoint(self, context, endpoint_id, endpoint):
self.assert_admin(context)
self._require_matching_id(endpoint_id, endpoint)
if 'service_id' in endpoint:
self.catalog_api.get_service(context, endpoint['service_id'])
ref = self.catalog_api.update_endpoint(context, endpoint_id, endpoint)
return {'endpoint': ref}
def delete_endpoint(self, context, endpoint_id):
self.assert_admin(context)
return self.catalog_api.delete_endpoint(context, endpoint_id)

View File

@ -0,0 +1,45 @@
import uuid
from keystone.common import wsgi
from keystone import exception
class V3Controller(wsgi.Application):
"""Base controller class for Identity API v3."""
def __init__(self, catalog_api, identity_api, token_api, policy_api):
self.catalog_api = catalog_api
self.identity_api = identity_api
self.policy_api = policy_api
self.token_api = token_api
super(V3Controller, self).__init__()
def _paginate(self, context, refs):
"""Paginates a list of references by page & per_page query strings."""
page = context['query_string'].get('page', 1)
per_page = context['query_string'].get('per_page', 30)
return refs[per_page * (page - 1):per_page * page]
def _require_attribute(self, ref, attr):
"""Ensures the reference contains the specified attribute."""
if ref.get(attr) is None or ref.get(attr) == '':
msg = '%s field is required and cannot be empty' % attr
raise exception.ValidationError(message=msg)
def _require_matching_id(self, value, ref):
"""Ensures the value matches the reference's ID, if any."""
if 'id' in ref and ref['id'] != value:
raise exception.ValidationError('Cannot change ID')
def _assign_unique_id(self, ref):
"""Generates and assigns a unique identifer to a reference."""
ref = ref.copy()
ref['id'] = uuid.uuid4().hex
return ref
def _filter_by_attribute(self, context, refs, attr):
"""Filters a list of references by query string value."""
if attr in context['query_string']:
value = context['query_string'][attr]
return [r for r in refs if r[attr] == value]
return refs

View File

@ -83,6 +83,10 @@ class MetadataNotFound(NotFound):
# so this exception should not be exposed
class PolicyNotFound(NotFound):
"""Could not find policy: %(policy_id)s"""
class RoleNotFound(NotFound):
"""Could not find role: %(role_id)s"""

View File

@ -20,6 +20,7 @@ import urllib
import urlparse
import uuid
from keystone.common import controller
from keystone.common import logging
from keystone.common import manager
from keystone.common import wsgi
@ -89,15 +90,6 @@ class Driver(object):
"""
raise exception.NotImplemented()
def get_user(self, user_id):
"""Get a user by id.
:returns: user_ref
:raises: keystone.exception.UserNotFound
"""
raise exception.NotImplemented()
def get_user_by_name(self, user_name):
"""Get a user by name.
@ -107,36 +99,6 @@ class Driver(object):
"""
raise exception.NotImplemented()
def get_role(self, role_id):
"""Get a role by id.
:returns: role_ref
:raises: keystone.exception.RoleNotFound
"""
raise exception.NotImplemented()
def list_users(self):
"""List all users in the system.
NOTE(termie): I'd prefer if this listed only the users for a given
tenant.
:returns: a list of user_refs or an empty list
"""
raise exception.NotImplemented()
def list_roles(self):
"""List all roles in the system.
:returns: a list of role_refs or an empty list.
"""
raise exception.NotImplemented()
# NOTE(termie): seven calls below should probably be exposed by the api
# more clearly when the api redesign happens
def add_user_to_tenant(self, tenant_id, user_id):
"""Add user to a tenant without an explicit role relationship.
@ -215,31 +177,6 @@ class Driver(object):
"""
raise exception.NotImplemented()
# user crud
def create_user(self, user_id, user):
"""Creates a new user.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented()
def update_user(self, user_id, user):
"""Updates an existing user.
:raises: keystone.exception.UserNotFound, keystone.exception.Conflict
"""
raise exception.NotImplemented()
def delete_user(self, user_id):
"""Deletes an existing user.
:raises: keystone.exception.UserNotFound
"""
raise exception.NotImplemented()
# tenant crud
def create_tenant(self, tenant_id, tenant):
"""Creates a new tenant.
@ -278,7 +215,182 @@ class Driver(object):
def delete_metadata(self, user_id, tenant_id):
raise exception.NotImplemented()
# domain crud
def create_domain(self, domain_id, domain):
"""Creates a new domain.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented()
def list_domains(self):
"""List all domains in the system.
:returns: a list of domain_refs or an empty list.
"""
raise exception.NotImplemented()
def get_domain(self, domain_id):
"""Get a domain by ID.
:returns: user_ref
:raises: keystone.exception.DomainNotFound
"""
raise exception.NotImplemented()
def update_domain(self, domain_id, domain):
"""Updates an existing domain.
:raises: keystone.exception.DomainNotFound,
keystone.exception.Conflict
"""
raise exception.NotImplemented()
def delete_domain(self, domain_id):
"""Deletes an existing domain.
:raises: keystone.exception.DomainNotFound
"""
raise exception.NotImplemented()
# project crud
def create_project(self, project_id, project):
"""Creates a new project.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented()
def list_projects(self):
"""List all projects in the system.
:returns: a list of project_refs or an empty list.
"""
raise exception.NotImplemented()
def get_project(self):
"""Get a project by ID.
:returns: user_ref
:raises: keystone.exception.ProjectNotFound
"""
raise exception.NotImplemented()
def update_project(self, project_id, project):
"""Updates an existing project.
:raises: keystone.exception.ProjectNotFound,
keystone.exception.Conflict
"""
raise exception.NotImplemented()
def delete_project(self, project_id):
"""Deletes an existing project.
:raises: keystone.exception.ProjectNotFound
"""
raise exception.NotImplemented()
# user crud
def create_user(self, user_id, user):
"""Creates a new user.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented()
def list_users(self):
"""List all users in the system.
:returns: a list of user_refs or an empty list.
"""
raise exception.NotImplemented()
def get_user(self, user_id):
"""Get a user by ID.
:returns: user_ref
:raises: keystone.exception.UserNotFound
"""
raise exception.NotImplemented()
def update_user(self, user_id, user):
"""Updates an existing user.
:raises: keystone.exception.UserNotFound,
keystone.exception.Conflict
"""
raise exception.NotImplemented()
def delete_user(self, user_id):
"""Deletes an existing user.
:raises: keystone.exception.UserNotFound
"""
raise exception.NotImplemented()
# credential crud
def create_credential(self, credential_id, credential):
"""Creates a new credential.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented()
def list_credentials(self):
"""List all credentials in the system.
:returns: a list of credential_refs or an empty list.
"""
raise exception.NotImplemented()
def get_credential(self, credential_id):
"""Get a credential by ID.
:returns: credential_ref
:raises: keystone.exception.CredentialNotFound
"""
raise exception.NotImplemented()
def update_credential(self, credential_id, credential):
"""Updates an existing credential.
:raises: keystone.exception.CredentialNotFound,
keystone.exception.Conflict
"""
raise exception.NotImplemented()
def delete_credential(self, credential_id):
"""Deletes an existing credential.
:raises: keystone.exception.CredentialNotFound
"""
raise exception.NotImplemented()
# role crud
def create_role(self, role_id, role):
"""Creates a new role.
@ -287,10 +399,28 @@ class Driver(object):
"""
raise exception.NotImplemented()
def list_roles(self):
"""List all roles in the system.
:returns: a list of role_refs or an empty list.
"""
raise exception.NotImplemented()
def get_role(self, role_id):
"""Get a role by ID.
:returns: role_ref
:raises: keystone.exception.RoleNotFound
"""
raise exception.NotImplemented()
def update_role(self, role_id, role):
"""Updates an existing role.
:raises: keystone.exception.RoleNotFound, keystone.exception.Conflict
:raises: keystone.exception.RoleNotFound,
keystone.exception.Conflict
"""
raise exception.NotImplemented()
@ -721,3 +851,223 @@ class RoleController(wsgi.Application):
self.identity_api.remove_user_from_tenant(
context, tenant_id, user_id)
self.token_api.revoke_tokens(context, user_id, tenant_id)
class DomainControllerV3(controller.V3Controller):
def create_domain(self, context, domain):
self.assert_admin(context)
ref = self._assign_unique_id(self._normalize_dict(domain))
ref = self.identity_api.create_domain(context, ref['id'], ref)
return {'domain': ref}
def list_domains(self, context):
self.assert_admin(context)
refs = self.identity_api.list_domains(context)
return {'domains': self._paginate(context, refs)}
def get_domain(self, context, domain_id):
self.assert_admin(context)
ref = self.identity_api.get_domain(context, domain_id)
return {'domain': ref}
def update_domain(self, context, domain_id, domain):
self.assert_admin(context)
self._require_matching_id(domain_id, domain)
ref = self.identity_api.update_domain(context, domain_id, domain)
return {'domain': ref}
def delete_domain(self, context, domain_id):
self.assert_admin(context)
return self.identity_api.delete_domain(context, domain_id)
class ProjectControllerV3(controller.V3Controller):
def create_project(self, context, project):
self.assert_admin(context)
ref = self._assign_unique_id(self._normalize_dict(project))
ref = self.identity_api.create_project(context, ref['id'], ref)
return {'project': ref}
def list_projects(self, context):
self.assert_admin(context)
refs = self.identity_api.list_projects(context)
return {'projects': self._paginate(context, refs)}
def list_user_projects(self, context, user_id):
# FIXME(dolph): this should also be callable by user_id themselves
self.assert_admin(context)
refs = self.identity_api.list_user_projects(context, user_id)
return {'projects': self._paginate(context, refs)}
def get_project(self, context, project_id):
self.assert_admin(context)
ref = self.identity_api.get_project(context, project_id)
return {'project': ref}
def update_project(self, context, project_id, project):
self.assert_admin(context)
self._require_matching_id(project_id, project)
ref = self.identity_api.update_project(context, project_id, project)
return {'project': ref}
def delete_project(self, context, project_id):
self.assert_admin(context)
return self.identity_api.delete_project(context, project_id)
class UserControllerV3(controller.V3Controller):
def create_user(self, context, user):
self.assert_admin(context)
ref = self._assign_unique_id(self._normalize_dict(user))
ref = self.identity_api.create_user(context, ref['id'], ref)
return {'user': ref}
def list_users(self, context):
self.assert_admin(context)
refs = self.identity_api.list_users(context)
return {'users': self._paginate(context, refs)}
def get_user(self, context, user_id):
self.assert_admin(context)
ref = self.identity_api.get_user(context, user_id)
return {'user': ref}
def update_user(self, context, user_id, user):
self.assert_admin(context)
self._require_matching_id(user_id, user)
ref = self.identity_api.update_user(context, user_id, user)
return {'user': ref}
def delete_user(self, context, user_id):
self.assert_admin(context)
return self.identity_api.delete_user(context, user_id)
class CredentialControllerV3(controller.V3Controller):
def create_credential(self, context, credential):
self.assert_admin(context)
ref = self._assign_unique_id(self._normalize_dict(credential))
ref = self.identity_api.create_credential(context, ref['id'], ref)
return {'credential': ref}
def list_credentials(self, context):
self.assert_admin(context)
refs = self.identity_api.list_credentials(context)
return {'credentials': self._paginate(context, refs)}
def get_credential(self, context, credential_id):
self.assert_admin(context)
ref = self.identity_api.get_credential(context, credential_id)
return {'credential': ref}
def update_credential(self, context, credential_id, credential):
self.assert_admin(context)
self._require_matching_id(credential_id, credential)
ref = self.identity_api.update_credential(
context,
credential_id,
credential)
return {'credential': ref}
def delete_credential(self, context, credential_id):
self.assert_admin(context)
return self.identity_api.delete_credential(context, credential_id)
class RoleControllerV3(controller.V3Controller):
def create_role(self, context, role):
self.assert_admin(context)
ref = self._assign_unique_id(self._normalize_dict(role))
ref = self.identity_api.create_role(context, ref['id'], ref)
return {'role': ref}
def list_roles(self, context):
self.assert_admin(context)
refs = self.identity_api.list_roles(context)
return {'roles': self._paginate(context, refs)}
def get_role(self, context, role_id):
self.assert_admin(context)
ref = self.identity_api.get_role(context, role_id)
return {'role': ref}
def update_role(self, context, role_id, role):
self.assert_admin(context)
self._require_matching_id(role_id, role)
ref = self.identity_api.update_role(context, role_id, role)
return {'role': ref}
def delete_role(self, context, role_id):
self.assert_admin(context)
return self.identity_api.delete_role(context, role_id)
def _require_domain_or_project(self, domain_id, project_id):
if (domain_id and project_id) or (not domain_id and not project_id):
msg = 'Specify a domain or project, not both'
raise exception.ValidationError(msg)
def create_grant(self, context, role_id, user_id, domain_id=None,
project_id=None):
"""Grants a role to a user on either a domain or project."""
self.assert_admin(context)
self._require_domain_or_project(domain_id, project_id)
return self.identity_api.create_grant(
context, role_id, user_id, domain_id, project_id)
def list_grants(self, context, user_id, domain_id=None,
project_id=None):
"""Lists roles granted to a user on either a domain or project."""
self.assert_admin(context)
self._require_domain_or_project(domain_id, project_id)
return self.identity_api.list_grants(
context, user_id, domain_id, project_id)
def check_grant(self, context, role_id, user_id, domain_id=None,
project_id=None):
"""Checks if a role has been granted on either a domain or project."""
self.assert_admin(context)
self._require_domain_or_project(domain_id, project_id)
self.identity_api.get_grant(
context, role_id, user_id, domain_id, project_id)
def revoke_grant(self, context, role_id, user_id, domain_id=None,
project_id=None):
"""Revokes a role from a user on either a domain or project."""
self.assert_admin(context)
self._require_domain_or_project(domain_id, project_id)
self.identity_api.delete_grant(
context, role_id, user_id, domain_id, project_id)

View File

@ -16,7 +16,9 @@
"""Main entry point into the Policy service."""
from keystone.common import manager
from keystone.common import controller
from keystone import config
from keystone import exception
@ -35,6 +37,26 @@ class Manager(manager.Manager):
def __init__(self):
super(Manager, self).__init__(CONF.policy.driver)
def get_policy(self, context, policy_id):
try:
return self.driver.get_policy(policy_id)
except exception.NotFound:
raise exception.PolicyNotFound(policy_id=policy_id)
def update_policy(self, context, policy_id, policy):
if 'id' in policy and policy_id != policy['id']:
raise exception.ValidationError('Cannot change policy ID')
try:
return self.driver.update_policy(policy_id, policy)
except exception.NotFound:
raise exception.PolicyNotFound(policy_id=policy_id)
def delete_policy(self, context, policy_id):
try:
return self.driver.delete_policy(policy_id)
except exception.NotFound:
raise exception.PolicyNotFound(policy_id=policy_id)
class Driver(object):
def enforce(context, credentials, action, target):
@ -44,3 +66,81 @@ class Driver(object):
`keystone.common.policy.enforce`.
"""
raise exception.NotImplemented()
def create_policy(self, policy_id, policy):
"""Store a policy blob for a particular endpoint.
:raises: keystone.exception.EndpointNotFound,
keystone.exception.Conflict
"""
raise exception.NotImplemented()
def list_policies(self):
"""List all policies."""
raise exception.NotImplemented()
def get_policy(self, policy_id):
"""Retrieve a specific policy blob.
:raises: keystone.exception.PolicyNotFound
"""
raise exception.NotImplemented()
def update_policy(self, policy_id, policy):
"""Update a policy blob.
:raises: keystone.exception.PolicyNotFound,
keystone.exception.EndpointNotFound
"""
raise exception.NotImplemented()
def delete_policy(self, policy_id):
"""Remove a policy blob.
:raises: keystone.exception.PolicyNotFound
"""
raise exception.NotImplemented()
class PolicyControllerV3(controller.V3Controller):
def create_policy(self, context, policy):
self.assert_admin(context)
ref = self._assign_unique_id(self._normalize_dict(policy))
self._require_attribute(ref, 'blob')
self._require_attribute(ref, 'type')
self._require_attribute(ref, 'endpoint_id')
self.catalog_api.get_endpoint(context, ref['endpoint_id'])
ref = self.policy_api.create_policy(context, ref['id'], ref)
return {'policy': ref}
def list_policies(self, context):
self.assert_admin(context)
refs = self.policy_api.list_policies(context)
refs = self._filter_by_attribute(context, refs, 'endpoint_id')
refs = self._filter_by_attribute(context, refs, 'type')
return {'policies': self._paginate(context, refs)}
def get_policy(self, context, policy_id):
self.assert_admin(context)
ref = self.policy_api.get_policy(context, policy_id)
return {'policy': ref}
def update_policy(self, context, policy_id, policy):
self.assert_admin(context)
if 'endpoint_id' in policy:
self.catalog_api.get_endpoint(context, policy['endpoint_id'])
ref = self.policy_api.update_policy(context, policy_id, policy)
return {'policy': ref}
def delete_policy(self, context, policy_id):
self.assert_admin(context)
return self.policy_api.delete_policy(context, policy_id)

View File

@ -33,6 +33,176 @@ 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.ServiceControllerV3(**apis),
'services',
'service')
self.crud_routes(
mapper,
catalog.EndpointControllerV3(**apis),
'endpoints',
'endpoint')
# Identity
self.crud_routes(
mapper,
identity.DomainControllerV3(**apis),
'domains',
'domain')
project_controller = identity.ProjectControllerV3(**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.UserControllerV3(**apis),
'users',
'user')
self.crud_routes(
mapper,
identity.CredentialControllerV3(**apis),
'credentials',
'credential')
role_controller = identity.RoleControllerV3(**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.PolicyControllerV3(**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()
@ -808,3 +978,10 @@ def admin_version_app_factory(global_conf, **local_conf):
conf = global_conf.copy()
conf.update(local_conf)
return AdminVersionRouter()
@logging.fail_gracefully
def v3_app_factory(global_conf, **local_conf):
conf = global_conf.copy()
conf.update(local_conf)
return V3Router()