Merge "Convert limits and registered limits to flask dispatching"
This commit is contained in:
commit
b625ccc42c
|
@ -12,9 +12,13 @@
|
|||
|
||||
from keystone.api import credentials
|
||||
from keystone.api import discovery
|
||||
from keystone.api import limits
|
||||
from keystone.api import os_oauth1
|
||||
from keystone.api import os_revoke
|
||||
from keystone.api import registered_limits
|
||||
from keystone.api import trusts
|
||||
|
||||
__all__ = ('discovery', 'credentials', 'os_oauth1', 'os_revoke', 'trusts')
|
||||
__apis__ = (discovery, credentials, os_oauth1, os_revoke, trusts)
|
||||
__all__ = ('discovery', 'credentials', 'limits', 'os_oauth1', 'os_revoke',
|
||||
'registered_limits', 'trusts')
|
||||
__apis__ = (discovery, credentials, limits, os_oauth1, os_revoke,
|
||||
registered_limits, trusts)
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
# 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.
|
||||
|
||||
# This file handles all flask-restful resources for /v3/limits
|
||||
|
||||
import flask
|
||||
import flask_restful
|
||||
from six.moves import http_client
|
||||
|
||||
from keystone.common import json_home
|
||||
from keystone.common import provider_api
|
||||
from keystone.common import rbac_enforcer
|
||||
from keystone.common import validation
|
||||
from keystone import exception
|
||||
from keystone.i18n import _
|
||||
from keystone.limit import schema
|
||||
from keystone.server import flask as ks_flask
|
||||
|
||||
|
||||
PROVIDERS = provider_api.ProviderAPIs
|
||||
ENFORCER = rbac_enforcer.RBACEnforcer
|
||||
|
||||
|
||||
class LimitsResource(ks_flask.ResourceBase):
|
||||
collection_key = 'limits'
|
||||
member_key = 'limit'
|
||||
json_home_resource_status = json_home.Status.EXPERIMENTAL
|
||||
|
||||
def _list_limits(self):
|
||||
filters = ['service_id', 'region_id', 'resource_name', 'project_id']
|
||||
ENFORCER.enforce_call(action='identity:list_limits', filters=filters)
|
||||
hints = self.build_driver_hints(filters)
|
||||
project_id_filter = hints.get_exact_filter_by_name('project_id')
|
||||
if project_id_filter:
|
||||
if self.oslo_context.system_scope:
|
||||
refs = PROVIDERS.unified_limit_api.list_limits(hints)
|
||||
else:
|
||||
refs = []
|
||||
else:
|
||||
project_id = self.oslo_context.project_id
|
||||
if project_id:
|
||||
hints.add_filter('project_id', project_id)
|
||||
refs = PROVIDERS.unified_limit_api.list_limits(hints)
|
||||
return self.wrap_collection(refs, hints=hints)
|
||||
|
||||
def _get_limit(self, limit_id):
|
||||
ENFORCER.enforce_call(action='identity:get_limit')
|
||||
ref = PROVIDERS.unified_limit_api.get_limit(limit_id)
|
||||
if (not self.oslo_context.is_admin and
|
||||
not ('admin' in self.oslo_context.roles)):
|
||||
project_id = self.oslo_context.project_id
|
||||
if project_id and project_id != ref['project_id']:
|
||||
action = _('The authenticated project should match the '
|
||||
'project_id')
|
||||
raise exception.Forbidden(action=action)
|
||||
return self.wrap_member(ref)
|
||||
|
||||
def get(self, limit_id=None):
|
||||
if limit_id is not None:
|
||||
return self._get_limit(limit_id)
|
||||
return self._list_limits()
|
||||
|
||||
def post(self):
|
||||
ENFORCER.enforce_call(action='identity:create_limits')
|
||||
limits_b = (flask.request.get_json(silent=True, force=True) or {}).get(
|
||||
'limits', {})
|
||||
validation.lazy_validate(schema.limit_create, limits_b)
|
||||
limits = [self._assign_unique_id(self._normalize_dict(limit))
|
||||
for limit in limits_b]
|
||||
refs = PROVIDERS.unified_limit_api.create_limits(limits)
|
||||
refs = self.wrap_collection(refs)
|
||||
refs.pop('links')
|
||||
return refs, http_client.CREATED
|
||||
|
||||
def patch(self, limit_id):
|
||||
ENFORCER.enforce_call(action='identity:update_limit')
|
||||
limit = (flask.request.get_json(silent=True, force=True) or {}).get(
|
||||
'limit', {})
|
||||
validation.lazy_validate(schema.limit_update, limit)
|
||||
self._require_matching_id(limit)
|
||||
ref = PROVIDERS.unified_limit_api.update_limit(limit_id, limit)
|
||||
return self.wrap_member(ref)
|
||||
|
||||
def delete(self, limit_id):
|
||||
ENFORCER.enforce_call(action='identity:delete_limit')
|
||||
return (PROVIDERS.unified_limit_api.delete_limit(limit_id),
|
||||
http_client.NO_CONTENT)
|
||||
|
||||
|
||||
class LimitModelResource(flask_restful.Resource):
|
||||
def get(self):
|
||||
ENFORCER.enforce_call(action='identity:get_limit_model')
|
||||
model = PROVIDERS.unified_limit_api.get_model()
|
||||
return {'model': model}
|
||||
|
||||
|
||||
class LimitsAPI(ks_flask.APIBase):
|
||||
_name = 'limits'
|
||||
_import_name = __name__
|
||||
resources = [LimitsResource]
|
||||
resource_mapping = [
|
||||
ks_flask.construct_resource_map(
|
||||
resource=LimitModelResource,
|
||||
resource_kwargs={},
|
||||
url='/limits/model',
|
||||
rel='limit_model',
|
||||
status=json_home.Status.EXPERIMENTAL
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
APIs = (LimitsAPI,)
|
|
@ -0,0 +1,91 @@
|
|||
# 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.
|
||||
|
||||
# This file handles all flask-restful resources for /v3/registered_limits
|
||||
|
||||
import flask
|
||||
from six.moves import http_client
|
||||
|
||||
from keystone.common import json_home
|
||||
from keystone.common import provider_api
|
||||
from keystone.common import rbac_enforcer
|
||||
from keystone.common import validation
|
||||
from keystone.limit import schema
|
||||
from keystone.server import flask as ks_flask
|
||||
|
||||
|
||||
PROVIDERS = provider_api.ProviderAPIs
|
||||
ENFORCER = rbac_enforcer.RBACEnforcer
|
||||
|
||||
|
||||
class RegisteredLimitResource(ks_flask.ResourceBase):
|
||||
collection_key = 'registered_limits'
|
||||
member_key = 'registered_limit'
|
||||
json_home_resource_status = json_home.Status.EXPERIMENTAL
|
||||
|
||||
def _get_registered_limit(self, registered_limit_id):
|
||||
ENFORCER.enforce_call(action='identity:get_registered_limit')
|
||||
ref = PROVIDERS.unified_limit_api.get_registered_limit(
|
||||
registered_limit_id)
|
||||
return self.wrap_member(ref)
|
||||
|
||||
def _list_registered_limits(self):
|
||||
filters = ['service_id', 'region_id', 'resource_name']
|
||||
ENFORCER.enforce_call(action='identity:list_registered_limits',
|
||||
filters=filters)
|
||||
hints = self.build_driver_hints(filters)
|
||||
refs = PROVIDERS.unified_limit_api.list_registered_limits(hints)
|
||||
return self.wrap_collection(refs)
|
||||
|
||||
def get(self, registered_limit_id=None):
|
||||
if registered_limit_id is not None:
|
||||
return self._get_registered_limit(registered_limit_id)
|
||||
return self._list_registered_limits()
|
||||
|
||||
def post(self):
|
||||
ENFORCER.enforce_call(action='identity:create_registered_limits')
|
||||
reg_limits = (flask.request.get_json(
|
||||
silent=True, force=True) or {}).get('registered_limits', {})
|
||||
validation.lazy_validate(schema.registered_limit_create, reg_limits)
|
||||
registered_limits = [self._assign_unique_id(self._normalize_dict(r))
|
||||
for r in reg_limits]
|
||||
refs = PROVIDERS.unified_limit_api.create_registered_limits(
|
||||
registered_limits)
|
||||
refs = self.wrap_collection(refs)
|
||||
refs.pop('links')
|
||||
return refs, http_client.CREATED
|
||||
|
||||
def patch(self, registered_limit_id):
|
||||
ENFORCER.enforce_call(action='identity:update_registered_limit')
|
||||
registered_limit = (flask.request.get_json(
|
||||
silent=True, force=True) or {}).get('registered_limit', {})
|
||||
validation.lazy_validate(schema.registered_limit_update,
|
||||
registered_limit)
|
||||
self._require_matching_id(registered_limit)
|
||||
ref = PROVIDERS.unified_limit_api.update_registered_limit(
|
||||
registered_limit_id, registered_limit)
|
||||
return self.wrap_member(ref)
|
||||
|
||||
def delete(self, registered_limit_id):
|
||||
ENFORCER.enforce_call(action='identity:delete_registered_limit')
|
||||
return (PROVIDERS.unified_limit_api.delete_registered_limit(
|
||||
registered_limit_id), http_client.NO_CONTENT)
|
||||
|
||||
|
||||
class RegisteredLimitsAPI(ks_flask.APIBase):
|
||||
_name = 'registered_limit'
|
||||
_import_name = __name__
|
||||
resources = [RegisteredLimitResource]
|
||||
resource_mapping = []
|
||||
|
||||
|
||||
APIs = (RegisteredLimitsAPI,)
|
|
@ -1,139 +0,0 @@
|
|||
# Copyright 2018 Huawei
|
||||
# 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 controller
|
||||
from keystone.common import provider_api
|
||||
from keystone.common import validation
|
||||
from keystone import exception
|
||||
from keystone.i18n import _
|
||||
from keystone.limit import schema
|
||||
|
||||
PROVIDERS = provider_api.ProviderAPIs
|
||||
|
||||
|
||||
class RegisteredLimitV3(controller.V3Controller):
|
||||
collection_name = 'registered_limits'
|
||||
member_name = 'registered_limit'
|
||||
|
||||
def __init__(self):
|
||||
super(RegisteredLimitV3, self).__init__()
|
||||
self.get_member_from_driver = (
|
||||
self.unified_limit_api.get_registered_limit
|
||||
)
|
||||
|
||||
@controller.protected()
|
||||
def create_registered_limits(self, request, registered_limits):
|
||||
validation.lazy_validate(schema.registered_limit_create,
|
||||
registered_limits)
|
||||
registered_limits = [self._assign_unique_id(self._normalize_dict(
|
||||
registered_limit)) for registered_limit in registered_limits]
|
||||
refs = PROVIDERS.unified_limit_api.create_registered_limits(
|
||||
registered_limits)
|
||||
refs = RegisteredLimitV3.wrap_collection(request.context_dict, refs)
|
||||
refs.pop("links")
|
||||
return refs
|
||||
|
||||
@controller.protected()
|
||||
def update_registered_limit(self, request, registered_limit_id,
|
||||
registered_limit):
|
||||
validation.lazy_validate(schema.registered_limit_update,
|
||||
registered_limit)
|
||||
ref = PROVIDERS.unified_limit_api.update_registered_limit(
|
||||
registered_limit_id, registered_limit)
|
||||
return RegisteredLimitV3.wrap_member(request.context_dict, ref)
|
||||
|
||||
@controller.filterprotected('service_id', 'region_id', 'resource_name')
|
||||
def list_registered_limits(self, request, filters):
|
||||
hints = RegisteredLimitV3.build_driver_hints(request, filters)
|
||||
refs = PROVIDERS.unified_limit_api.list_registered_limits(hints)
|
||||
return RegisteredLimitV3.wrap_collection(request.context_dict, refs,
|
||||
hints=hints)
|
||||
|
||||
@controller.protected()
|
||||
def get_registered_limit(self, request, registered_limit_id):
|
||||
ref = PROVIDERS.unified_limit_api.get_registered_limit(
|
||||
registered_limit_id)
|
||||
return RegisteredLimitV3.wrap_member(request.context_dict, ref)
|
||||
|
||||
@controller.protected()
|
||||
def delete_registered_limit(self, request, registered_limit_id):
|
||||
return PROVIDERS.unified_limit_api.delete_registered_limit(
|
||||
registered_limit_id)
|
||||
|
||||
|
||||
class LimitV3(controller.V3Controller):
|
||||
collection_name = 'limits'
|
||||
member_name = 'limit'
|
||||
|
||||
def __init__(self):
|
||||
super(LimitV3, self).__init__()
|
||||
self.get_member_from_driver = self.unified_limit_api.get_limit
|
||||
|
||||
@controller.protected()
|
||||
def get_limit_model(self, request):
|
||||
model = PROVIDERS.unified_limit_api.get_model()
|
||||
return {'model': model}
|
||||
|
||||
@controller.protected()
|
||||
def create_limits(self, request, limits):
|
||||
validation.lazy_validate(schema.limit_create, limits)
|
||||
limits = [self._assign_unique_id(self._normalize_dict(limit))
|
||||
for limit in limits]
|
||||
refs = PROVIDERS.unified_limit_api.create_limits(limits)
|
||||
refs = LimitV3.wrap_collection(request.context_dict, refs)
|
||||
refs.pop("links")
|
||||
return refs
|
||||
|
||||
@controller.protected()
|
||||
def update_limit(self, request, limit_id, limit):
|
||||
validation.lazy_validate(schema.limit_update, limit)
|
||||
ref = PROVIDERS.unified_limit_api.update_limit(
|
||||
limit_id, limit)
|
||||
return LimitV3.wrap_member(request.context_dict, ref)
|
||||
|
||||
@controller.filterprotected('service_id', 'region_id', 'resource_name',
|
||||
'project_id')
|
||||
def list_limits(self, request, filters):
|
||||
hints = LimitV3.build_driver_hints(request, filters)
|
||||
context = request.context
|
||||
project_id_filter = hints.get_exact_filter_by_name('project_id')
|
||||
if project_id_filter:
|
||||
if context.system_scope:
|
||||
refs = PROVIDERS.unified_limit_api.list_limits(hints)
|
||||
else:
|
||||
refs = []
|
||||
else:
|
||||
project_id = context.project_id
|
||||
if project_id:
|
||||
hints.add_filter('project_id', project_id)
|
||||
refs = PROVIDERS.unified_limit_api.list_limits(hints)
|
||||
return LimitV3.wrap_collection(request.context_dict, refs, hints=hints)
|
||||
|
||||
@controller.protected()
|
||||
def get_limit(self, request, limit_id):
|
||||
ref = PROVIDERS.unified_limit_api.get_limit(limit_id)
|
||||
# TODO(wxy): Add system-scope check. If the request is system-scoped,
|
||||
# it can get any limits.
|
||||
context = request.context
|
||||
if not context.is_admin and not ('admin' in context.roles):
|
||||
project_id = context.project_id
|
||||
if project_id and project_id != ref['project_id']:
|
||||
action = _("The authenticated project should match the "
|
||||
"project_id")
|
||||
raise exception.Forbidden(action=action)
|
||||
|
||||
return LimitV3.wrap_member(request.context_dict, ref)
|
||||
|
||||
@controller.protected()
|
||||
def delete_limit(self, request, limit_id):
|
||||
return PROVIDERS.unified_limit_api.delete_limit(limit_id)
|
|
@ -1,75 +0,0 @@
|
|||
# Copyright 2018 Huawei
|
||||
#
|
||||
# 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 json_home
|
||||
from keystone.common import wsgi
|
||||
from keystone.limit import controllers
|
||||
|
||||
|
||||
class Routers(wsgi.RoutersBase):
|
||||
_path_prefixes = ('registered_limits', 'limits')
|
||||
|
||||
def append_v3_routers(self, mapper, routers):
|
||||
|
||||
self._add_resource(
|
||||
mapper, controllers.RegisteredLimitV3(),
|
||||
path='/registered_limits',
|
||||
post_action='create_registered_limits',
|
||||
get_head_action='list_registered_limits',
|
||||
status=json_home.Status.EXPERIMENTAL,
|
||||
rel=json_home.build_v3_resource_relation('registered_limits')
|
||||
)
|
||||
|
||||
self._add_resource(
|
||||
mapper, controllers.RegisteredLimitV3(),
|
||||
path='/registered_limits/{registered_limit_id}',
|
||||
get_head_action='get_registered_limit',
|
||||
patch_action='update_registered_limit',
|
||||
delete_action='delete_registered_limit',
|
||||
status=json_home.Status.EXPERIMENTAL,
|
||||
rel=json_home.build_v3_resource_relation('registered_limits'),
|
||||
path_vars={
|
||||
'registered_limit_id':
|
||||
json_home.Parameters.REGISTERED_LIMIT_ID}
|
||||
)
|
||||
|
||||
self._add_resource(
|
||||
mapper, controllers.LimitV3(),
|
||||
path='/limits',
|
||||
post_action='create_limits',
|
||||
get_head_action='list_limits',
|
||||
status=json_home.Status.EXPERIMENTAL,
|
||||
rel=json_home.build_v3_resource_relation('limits')
|
||||
)
|
||||
|
||||
self._add_resource(
|
||||
mapper, controllers.LimitV3(),
|
||||
path='/limits/model',
|
||||
get_head_action='get_limit_model',
|
||||
status=json_home.Status.EXPERIMENTAL,
|
||||
rel=json_home.build_v3_resource_relation('limit_model')
|
||||
)
|
||||
|
||||
self._add_resource(
|
||||
mapper, controllers.LimitV3(),
|
||||
path='/limits/{limit_id}',
|
||||
get_head_action='get_limit',
|
||||
patch_action='update_limit',
|
||||
delete_action='delete_limit',
|
||||
status=json_home.Status.EXPERIMENTAL,
|
||||
rel=json_home.build_v3_resource_relation('limits'),
|
||||
path_vars={
|
||||
'limit_id':
|
||||
json_home.Parameters.LIMIT_ID}
|
||||
)
|
|
@ -34,7 +34,6 @@ from keystone.contrib.s3 import routers as s3_routers
|
|||
from keystone.endpoint_policy import routers as endpoint_policy_routers
|
||||
from keystone.federation import routers as federation_routers
|
||||
from keystone.identity import routers as identity_routers
|
||||
from keystone.limit import routers as limit_routers
|
||||
from keystone.oauth1 import routers as oauth1_routers
|
||||
from keystone.policy import routers as policy_routers
|
||||
from keystone.resource import routers as resource_routers
|
||||
|
@ -43,7 +42,7 @@ from keystone.token import _simple_cert as simple_cert_ext
|
|||
# TODO(morgan): _MOVED_API_PREFIXES to be removed when the legacy dispatch
|
||||
# support is removed.
|
||||
_MOVED_API_PREFIXES = frozenset(['credentials', 'OS-OAUTH1', 'OS-REVOKE',
|
||||
'OS-TRUST'])
|
||||
'OS-TRUST', 'limits', 'registered_limits'])
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -52,7 +51,6 @@ ALL_API_ROUTERS = [auth_routers,
|
|||
catalog_routers,
|
||||
identity_routers,
|
||||
app_cred_routers,
|
||||
limit_routers,
|
||||
policy_routers,
|
||||
resource_routers,
|
||||
federation_routers,
|
||||
|
|
|
@ -358,6 +358,8 @@ class APIBase(object):
|
|||
resource_rel_func = getattr(
|
||||
r, 'json_home_resource_rel_func',
|
||||
json_home.build_v3_resource_relation)
|
||||
resource_rel_status = getattr(
|
||||
r, 'json_home_resource_status', None)
|
||||
collection_rel = resource_rel_func(resource_name=c_key)
|
||||
# NOTE(morgan): Add the prefix explicitly for JSON Home documents
|
||||
# to the collection path.
|
||||
|
@ -376,6 +378,12 @@ class APIBase(object):
|
|||
entity_rel_data = {'href-template': jh_e_path,
|
||||
'href-vars': {id_str: id_param_rel}}
|
||||
|
||||
if resource_rel_status is not None:
|
||||
json_home.Status.update_resource_data(
|
||||
rel_data, resource_rel_status)
|
||||
json_home.Status.update_resource_data(
|
||||
entity_rel_data, resource_rel_status)
|
||||
|
||||
json_home.JsonHomeResources.append_resource(
|
||||
collection_rel, rel_data)
|
||||
json_home.JsonHomeResources.append_resource(
|
||||
|
|
|
@ -609,6 +609,9 @@ V3_JSON_HOME_RESOURCES = {
|
|||
'group': json_home.build_v3_parameter_relation('config_group'),
|
||||
'option': json_home.build_v3_parameter_relation('config_option')}},
|
||||
json_home.build_v3_resource_relation('registered_limits'): {
|
||||
'hints': {'status': 'experimental'},
|
||||
'href': '/registered_limits'},
|
||||
json_home.build_v3_resource_relation('registered_limit'): {
|
||||
'href-template': '/registered_limits/{registered_limit_id}',
|
||||
'href-vars': {
|
||||
'registered_limit_id': json_home.build_v3_parameter_relation(
|
||||
|
@ -617,6 +620,9 @@ V3_JSON_HOME_RESOURCES = {
|
|||
'hints': {'status': 'experimental'}
|
||||
},
|
||||
json_home.build_v3_resource_relation('limits'): {
|
||||
'hints': {'status': 'experimental'},
|
||||
'href': '/limits'},
|
||||
json_home.build_v3_resource_relation('limit'): {
|
||||
'href-template': '/limits/{limit_id}',
|
||||
'href-vars': {
|
||||
'limit_id': json_home.build_v3_parameter_relation('limit_id')
|
||||
|
|
Loading…
Reference in New Issue