Added validation to the users/databases/root calls.
* Added a custom extension manager to make extension behavior normal * Added proper serializer/deserializer to the user/database/root calls * Added exception map for processing exceptions * Fixed all the returns to return wsgi.Result * Added validation method for create user/database/root
This commit is contained in:
parent
f635542677
commit
80413fc4b3
@ -16,62 +16,73 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import routes
|
||||
import webob.dec
|
||||
import logging
|
||||
|
||||
from reddwarf.openstack.common import extensions
|
||||
from reddwarf.common import wsgi
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
ExtensionsDescriptor = extensions.ExtensionDescriptor
|
||||
ResourceExtension = extensions.ResourceExtension
|
||||
|
||||
|
||||
class ReddwarfExtensionMiddleware(extensions.ExtensionMiddleware):
|
||||
|
||||
def __init__(self, application, config, ext_mgr=None):
|
||||
ext_mgr = ext_mgr or ExtensionManager(
|
||||
config['api_extensions_path'])
|
||||
mapper = routes.Mapper()
|
||||
|
||||
# extended resources
|
||||
for resource_ext in ext_mgr.get_resources():
|
||||
LOG.debug(_('Extended resource: %s'), resource_ext.collection)
|
||||
LOG.debug(resource_ext.deserializer)
|
||||
# The only difference here is that we are using our common
|
||||
# wsgi.Resource instead of the openstack common wsgi.Resource
|
||||
controller_resource = wsgi.Resource(resource_ext.controller,
|
||||
resource_ext.deserializer,
|
||||
resource_ext.serializer)
|
||||
|
||||
self._map_custom_collection_actions(resource_ext, mapper,
|
||||
controller_resource)
|
||||
kargs = dict(controller=controller_resource,
|
||||
collection=resource_ext.collection_actions,
|
||||
member=resource_ext.member_actions)
|
||||
if resource_ext.parent:
|
||||
kargs['parent_resource'] = resource_ext.parent
|
||||
mapper.resource(resource_ext.collection,
|
||||
resource_ext.collection, **kargs)
|
||||
|
||||
# extended actions
|
||||
action_resources = self._action_ext_resources(application, ext_mgr,
|
||||
mapper)
|
||||
for action in ext_mgr.get_actions():
|
||||
LOG.debug(_('Extended action: %s'), action.action_name)
|
||||
resource = action_resources[action.collection]
|
||||
resource.add_action(action.action_name, action.handler)
|
||||
|
||||
# extended requests
|
||||
req_controllers = self._request_ext_resources(application, ext_mgr,
|
||||
mapper)
|
||||
for request_ext in ext_mgr.get_request_extensions():
|
||||
LOG.debug(_('Extended request: %s'), request_ext.key)
|
||||
controller = req_controllers[request_ext.key]
|
||||
controller.add_handler(request_ext.handler)
|
||||
|
||||
self._router = routes.middleware.RoutesMiddleware(self._dispatch,
|
||||
mapper)
|
||||
|
||||
super(extensions.ExtensionMiddleware, self).__init__(application)
|
||||
|
||||
|
||||
def factory(global_config, **local_config):
|
||||
"""Paste factory."""
|
||||
def _factory(app):
|
||||
extensions.DEFAULT_XMLNS = "http://docs.openstack.org/reddwarf"
|
||||
ext_mgr = TenantExtensionManager(
|
||||
ext_mgr = extensions.ExtensionManager(
|
||||
global_config.get('api_extensions_path', ''))
|
||||
return extensions.ExtensionMiddleware(app, global_config, ext_mgr)
|
||||
return ReddwarfExtensionMiddleware(app, global_config, ext_mgr)
|
||||
return _factory
|
||||
|
||||
|
||||
# Not sure if this is the way we should do it.
|
||||
# Might need to make openstack common more extensible for tenants
|
||||
# or any random values in the routes methods (index, show, etc...)
|
||||
class TenantExtensionManager(extensions.ExtensionManager):
|
||||
|
||||
def __init__(self, path):
|
||||
super(TenantExtensionManager, self).__init__(path)
|
||||
|
||||
#TODO(hub-cap): fix openstack-common.extensions to work with tenant ids
|
||||
def get_resources(self):
|
||||
"""Returns a list of ResourceExtension objects."""
|
||||
resources = []
|
||||
extension_resource = TenantExtensionsResource(self)
|
||||
res_ext = extensions.ResourceExtension('{tenant_id}/extensions',
|
||||
extension_resource,
|
||||
serializer=extension_resource.serializer)
|
||||
resources.append(res_ext)
|
||||
for alias, ext in self.extensions.iteritems():
|
||||
try:
|
||||
resources.extend(ext.get_resources())
|
||||
except AttributeError:
|
||||
# NOTE(dprince): Extension aren't required to have resource
|
||||
# extensions
|
||||
pass
|
||||
return resources
|
||||
|
||||
|
||||
class TenantExtensionsResource(extensions.ExtensionsResource):
|
||||
|
||||
def __init__(self, extension_manager):
|
||||
super(TenantExtensionsResource, self).__init__(extension_manager)
|
||||
|
||||
def index(self, req, tenant_id):
|
||||
return super(TenantExtensionsResource, self).index(req)
|
||||
|
||||
def show(self, req, id, tenant_id):
|
||||
return super(TenantExtensionsResource, self).show(req, id)
|
||||
|
||||
def delete(self, req, id, tenant_id):
|
||||
return super(TenantExtensionsResource, self).delete(req, id)
|
||||
|
||||
def create(self, req, tenant_id):
|
||||
return super(TenantExtensionsResource, self).create(req)
|
||||
|
@ -35,6 +35,8 @@ Server = openstack_wsgi.Server
|
||||
Debug = openstack_wsgi.Debug
|
||||
Middleware = openstack_wsgi.Middleware
|
||||
JSONDictSerializer = openstack_wsgi.JSONDictSerializer
|
||||
XMLDictSerializer = openstack_wsgi.XMLDictSerializer
|
||||
RequestDeserializer = openstack_wsgi.RequestDeserializer
|
||||
|
||||
eventlet.patcher.monkey_patch(all=False, socket=True)
|
||||
|
||||
@ -60,7 +62,6 @@ class VersionedURLMap(object):
|
||||
app = self.urlmap.get(version, Fault(http_exc))
|
||||
else:
|
||||
app = self.urlmap
|
||||
|
||||
return app(environ, start_response)
|
||||
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
import logging
|
||||
|
||||
from reddwarf.common import extensions
|
||||
from reddwarf.common import wsgi
|
||||
from reddwarf.extensions.mysql import service
|
||||
|
||||
|
||||
@ -43,23 +44,34 @@ class Mysql(extensions.ExtensionsDescriptor):
|
||||
|
||||
def get_resources(self):
|
||||
resources = []
|
||||
serializer = wsgi.ReddwarfResponseSerializer(
|
||||
body_serializers={'application/xml':
|
||||
wsgi.ReddwarfXMLDictSerializer()})
|
||||
resource = extensions.ResourceExtension(
|
||||
'databases',
|
||||
service.SchemaController(),
|
||||
parent={'member_name': 'instance',
|
||||
'collection_name': '{tenant_id}/instances'})
|
||||
'collection_name': '{tenant_id}/instances'},
|
||||
deserializer=wsgi.RequestDeserializer(),
|
||||
serializer=serializer)
|
||||
resources.append(resource)
|
||||
resource = extensions.ResourceExtension(
|
||||
'users',
|
||||
service.UserController(),
|
||||
parent={'member_name': 'instance',
|
||||
'collection_name': '{tenant_id}/instances'})
|
||||
'collection_name': '{tenant_id}/instances'},
|
||||
# deserializer=extensions.ExtensionsXMLSerializer()
|
||||
deserializer=wsgi.RequestDeserializer(),
|
||||
serializer=serializer)
|
||||
resources.append(resource)
|
||||
resource = extensions.ResourceExtension(
|
||||
'root',
|
||||
service.RootController(),
|
||||
parent={'member_name': 'instance',
|
||||
'collection_name': '{tenant_id}/instances'})
|
||||
'collection_name': '{tenant_id}/instances'},
|
||||
deserializer=wsgi.RequestDeserializer(),
|
||||
serializer=serializer)
|
||||
|
||||
resources.append(resource)
|
||||
|
||||
return resources
|
||||
|
@ -31,6 +31,29 @@ LOG = logging.getLogger(__name__)
|
||||
class BaseController(wsgi.Controller):
|
||||
"""Base controller class."""
|
||||
|
||||
exclude_attr = []
|
||||
exception_map = {
|
||||
webob.exc.HTTPUnprocessableEntity: [
|
||||
],
|
||||
webob.exc.HTTPBadRequest: [
|
||||
exception.BadRequest,
|
||||
],
|
||||
webob.exc.HTTPNotFound: [
|
||||
exception.NotFound,
|
||||
],
|
||||
webob.exc.HTTPConflict: [
|
||||
],
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def _extract_required_params(self, params, model_name):
|
||||
params = params or {}
|
||||
model_params = params.get(model_name, {})
|
||||
return utils.stringify_keys(utils.exclude(model_params,
|
||||
*self.exclude_attr))
|
||||
|
||||
|
||||
class RootController(BaseController):
|
||||
"""Controller for instance functionality"""
|
||||
@ -44,7 +67,7 @@ class RootController(BaseController):
|
||||
auth_tok=req.headers["X-Auth-Token"],
|
||||
tenant=tenant_id)
|
||||
is_root_enabled = models.Root.load(context, instance_id)
|
||||
return views.RootEnabledView(is_root_enabled).data()
|
||||
return wsgi.Result(views.RootEnabledView(is_root_enabled).data(), 201)
|
||||
|
||||
def create(self, req, body, tenant_id, instance_id):
|
||||
""" Enable the root user for the db instance """
|
||||
@ -54,7 +77,7 @@ class RootController(BaseController):
|
||||
auth_tok=req.headers["X-Auth-Token"],
|
||||
tenant=tenant_id)
|
||||
root = models.Root.create(context, instance_id)
|
||||
return views.RootCreatedView(root).data()
|
||||
return wsgi.Result(views.RootCreatedView(root).data(), 201)
|
||||
|
||||
|
||||
class UserController(BaseController):
|
||||
@ -67,15 +90,12 @@ class UserController(BaseController):
|
||||
raise exception.BadRequest("The request contains an empty body")
|
||||
|
||||
if not body.get('users', ''):
|
||||
raise exception.BadRequest("Required element/key 'users' was not "
|
||||
"specified")
|
||||
raise exception.BadRequest(key='users')
|
||||
for user in body.get('users'):
|
||||
if not user.get('name'):
|
||||
raise exception.BadRequest("Required attribute/key 'name' was "
|
||||
"not specified")
|
||||
raise exception.BadRequest(key='name')
|
||||
if not user.get('password'):
|
||||
raise exception.BadRequest("Required attribute/key 'password' "
|
||||
"was not specified")
|
||||
raise exception.BadRequest(key='password')
|
||||
|
||||
def index(self, req, tenant_id, instance_id):
|
||||
"""Return all users."""
|
||||
@ -85,8 +105,7 @@ class UserController(BaseController):
|
||||
auth_tok=req.headers["X-Auth-Token"],
|
||||
tenant=tenant_id)
|
||||
users = models.Users.load(context, instance_id)
|
||||
# Not exactly sure why we cant return a wsgi.Result() here
|
||||
return views.UsersView(users).data()
|
||||
return wsgi.Result(views.UsersView(users).data(), 201)
|
||||
|
||||
def create(self, req, body, tenant_id, instance_id):
|
||||
"""Creates a set of users"""
|
||||
@ -96,14 +115,11 @@ class UserController(BaseController):
|
||||
context = rd_context.ReddwarfContext(
|
||||
auth_tok=req.headers["X-Auth-Token"],
|
||||
tenant=tenant_id)
|
||||
try:
|
||||
self.validate(body)
|
||||
except exception.BadRequest as br:
|
||||
return webob.exc.HTTPBadRequest(br)
|
||||
self.validate(body)
|
||||
users = body['users']
|
||||
model_users = models.populate_users(users)
|
||||
models.User.create(context, instance_id, model_users)
|
||||
return webob.exc.HTTPAccepted()
|
||||
return wsgi.Result(202)
|
||||
|
||||
def delete(self, req, tenant_id, instance_id, id):
|
||||
LOG.info("Deleting user for instance '%s'" % instance_id)
|
||||
@ -114,7 +130,7 @@ class UserController(BaseController):
|
||||
user = guest_models.MySQLUser()
|
||||
user.name = id
|
||||
models.User.delete(context, instance_id, user.serialize())
|
||||
return webob.exc.HTTPAccepted()
|
||||
return wsgi.Result(202)
|
||||
|
||||
|
||||
class SchemaController(BaseController):
|
||||
@ -140,7 +156,7 @@ class SchemaController(BaseController):
|
||||
tenant=tenant_id)
|
||||
schemas = models.Schemas.load(context, instance_id)
|
||||
# Not exactly sure why we cant return a wsgi.Result() here
|
||||
return views.SchemasView(schemas).data()
|
||||
return wsgi.Result(views.SchemasView(schemas).data(), 201)
|
||||
|
||||
def create(self, req, body, tenant_id, instance_id):
|
||||
"""Creates a set of schemas"""
|
||||
@ -150,14 +166,11 @@ class SchemaController(BaseController):
|
||||
context = rd_context.ReddwarfContext(
|
||||
auth_tok=req.headers["X-Auth-Token"],
|
||||
tenant=tenant_id)
|
||||
try:
|
||||
self.validate(body)
|
||||
except exception.BadRequest as br:
|
||||
return webob.exc.HTTPBadRequest(br)
|
||||
self.validate(body)
|
||||
schemas = body['databases']
|
||||
model_schemas = models.populate_databases(schemas)
|
||||
models.Schema.create(context, instance_id, model_schemas)
|
||||
return webob.exc.HTTPAccepted()
|
||||
return wsgi.Result(202)
|
||||
|
||||
def delete(self, req, tenant_id, instance_id, id):
|
||||
LOG.info("Deleting schema for instance '%s'" % instance_id)
|
||||
@ -168,4 +181,4 @@ class SchemaController(BaseController):
|
||||
schema = guest_models.MySQLDatabase()
|
||||
schema.name = id
|
||||
models.Schema.delete(context, instance_id, schema.serialize())
|
||||
return webob.exc.HTTPAccepted()
|
||||
return wsgi.Result(202)
|
||||
|
Loading…
Reference in New Issue
Block a user