Pass request data as an argument to API methods
This commit generalises the approach taken by filtered_context; the methods no longer access the request data directly but instead receive it as an argument. This change helps to standardise the code base. Also, by automatically supplying the data as an argument, it reduces the likelihood that the validation process will be bypassed when any new functionality is added. In earlier version, some parts of the API were directly accessing the raw request data via 'request.json' instead of the validated data that was in 'g.json'. Change-Id: Icba9612ef5fa968de706ede610cce111ec9723c1 Related-Bug: 1623095
This commit is contained in:
parent
3fd67e5002
commit
a894913ae6
|
@ -41,12 +41,11 @@ def filtered_context():
|
|||
objname = f.__qualname__.split('.')[0].rstrip('s').lower()
|
||||
|
||||
@functools.wraps(f)
|
||||
def method_wrapper(self, context):
|
||||
query_filters = flask.g.args
|
||||
def method_wrapper(self, context, request_args):
|
||||
inspect.getmodule(f).LOG.info(
|
||||
"Getting all %s objects that match filters %s" % (
|
||||
objname, query_filters))
|
||||
return f(self, context, **query_filters)
|
||||
objname, request_args))
|
||||
return f(self, context, request_args)
|
||||
|
||||
return method_wrapper
|
||||
return decorator
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from collections import OrderedDict
|
||||
from flask import g
|
||||
from operator import attrgetter
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_log import log
|
||||
|
@ -81,9 +80,9 @@ class AnsibleInventory(base.Resource):
|
|||
}
|
||||
return inventory
|
||||
|
||||
def get(self, context):
|
||||
region_id = g.args["region_id"]
|
||||
cell_id = g.args["cell_id"]
|
||||
def get(self, context, request_args):
|
||||
region_id = request_args["region_id"]
|
||||
cell_id = request_args["cell_id"]
|
||||
|
||||
filters = {}
|
||||
if region_id:
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from flask import g
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_log import log
|
||||
|
||||
|
@ -14,15 +13,15 @@ class Cells(base.Resource):
|
|||
|
||||
@base.http_codes
|
||||
@base.filtered_context()
|
||||
def get(self, context, **filters):
|
||||
def get(self, context, request_args):
|
||||
"""Get all cells, with optional filtering."""
|
||||
cells_obj = dbapi.cells_get_all(context, filters)
|
||||
cells_obj = dbapi.cells_get_all(context, request_args)
|
||||
return jsonutils.to_primitive(cells_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
def post(self, context):
|
||||
def post(self, context, request_data):
|
||||
"""Create a new cell."""
|
||||
json = util.copy_project_id_into_json(context, g.json)
|
||||
json = util.copy_project_id_into_json(context, request_data)
|
||||
cell_obj = dbapi.cells_create(context, json)
|
||||
cell = jsonutils.to_primitive(cell_obj)
|
||||
if 'variables' in json:
|
||||
|
@ -41,9 +40,9 @@ class CellById(base.Resource):
|
|||
cell['variables'] = jsonutils.to_primitive(cell_obj.variables)
|
||||
return cell, 200, None
|
||||
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
"""Update existing cell."""
|
||||
cell_obj = dbapi.cells_update(context, id, g.json)
|
||||
cell_obj = dbapi.cells_update(context, id, request_data)
|
||||
return jsonutils.to_primitive(cell_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
|
@ -63,20 +62,20 @@ class CellsVariables(base.Resource):
|
|||
return resp, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
"""
|
||||
Update existing cell variables, or create if it does
|
||||
not exist.
|
||||
"""
|
||||
obj = dbapi.cells_variables_update(context, id, g.json)
|
||||
obj = dbapi.cells_variables_update(context, id, request_data)
|
||||
resp = {"variables": jsonutils.to_primitive(obj.variables)}
|
||||
return resp, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def delete(self, context, id):
|
||||
def delete(self, context, id, request_data):
|
||||
"""Delete cell variables."""
|
||||
# NOTE(sulo): this is not that great. Find a better way to do this.
|
||||
# We can pass multiple keys suchs as key1=one key2=two etc. but not
|
||||
# the best way to do this.
|
||||
dbapi.cells_variables_delete(context, id, g.json)
|
||||
dbapi.cells_variables_delete(context, id, request_data)
|
||||
return None, 204, None
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from flask import g
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_log import log
|
||||
|
||||
|
@ -14,15 +13,15 @@ class Hosts(base.Resource):
|
|||
|
||||
@base.http_codes
|
||||
@base.filtered_context()
|
||||
def get(self, context, **filters):
|
||||
def get(self, context, request_args):
|
||||
"""Get all hosts for region, with optional filtering."""
|
||||
hosts_obj = dbapi.hosts_get_all(context, filters)
|
||||
hosts_obj = dbapi.hosts_get_all(context, request_args)
|
||||
return jsonutils.to_primitive(hosts_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
def post(self, context):
|
||||
def post(self, context, request_data):
|
||||
"""Create a new host."""
|
||||
json = util.copy_project_id_into_json(context, g.json)
|
||||
json = util.copy_project_id_into_json(context, request_data)
|
||||
host_obj = dbapi.hosts_create(context, json)
|
||||
host = jsonutils.to_primitive(host_obj)
|
||||
if 'variables' in json:
|
||||
|
@ -44,17 +43,17 @@ def format_variables(args, obj):
|
|||
class HostById(base.Resource):
|
||||
|
||||
@base.http_codes
|
||||
def get(self, context, id):
|
||||
def get(self, context, id, request_args):
|
||||
"""Get host by given id"""
|
||||
host_obj = dbapi.hosts_get_by_id(context, id)
|
||||
host_obj = format_variables(g.args, host_obj)
|
||||
host_obj = format_variables(request_args, host_obj)
|
||||
host = jsonutils.to_primitive(host_obj)
|
||||
host['variables'] = jsonutils.to_primitive(host_obj.vars)
|
||||
return host, 200, None
|
||||
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
"""Update existing host data, or create if it does not exist."""
|
||||
host_obj = dbapi.hosts_update(context, id, g.json)
|
||||
host_obj = dbapi.hosts_update(context, id, request_data)
|
||||
return jsonutils.to_primitive(host_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
|
@ -67,27 +66,27 @@ class HostById(base.Resource):
|
|||
class HostsVariables(base.Resource):
|
||||
|
||||
@base.http_codes
|
||||
def get(self, context, id):
|
||||
def get(self, context, id, request_args):
|
||||
"""Get variables for given host."""
|
||||
obj = dbapi.hosts_get_by_id(context, id)
|
||||
obj = format_variables(g.args, obj)
|
||||
obj = format_variables(request_args, obj)
|
||||
response = {"variables": jsonutils.to_primitive(obj.vars)}
|
||||
return response, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
"""Update existing host variables, or create if it does not exist."""
|
||||
obj = dbapi.hosts_variables_update(context, id, g.json)
|
||||
obj = dbapi.hosts_variables_update(context, id, request_data)
|
||||
response = {"variables": jsonutils.to_primitive(obj.variables)}
|
||||
return response, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def delete(self, context, id):
|
||||
def delete(self, context, id, request_data):
|
||||
"""Delete host variables."""
|
||||
# NOTE(sulo): this is not that great. Find a better way to do this.
|
||||
# We can pass multiple keys suchs as key1=one key2=two etc. but not
|
||||
# the best way to do this.
|
||||
dbapi.hosts_variables_delete(context, id, g.json)
|
||||
dbapi.hosts_variables_delete(context, id, request_data)
|
||||
return None, 204, None
|
||||
|
||||
|
||||
|
@ -101,17 +100,17 @@ class HostsLabels(base.Resource):
|
|||
return response, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
"""
|
||||
Update existing device label entirely, or add if it does
|
||||
not exist.
|
||||
"""
|
||||
resp = dbapi.hosts_labels_update(context, id, g.json)
|
||||
resp = dbapi.hosts_labels_update(context, id, request_data)
|
||||
response = {"labels": list(resp.labels)}
|
||||
return response, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def delete(self, context, id):
|
||||
def delete(self, context, id, request_data):
|
||||
"""Delete device label entirely."""
|
||||
dbapi.hosts_labels_delete(context, id, g.json)
|
||||
dbapi.hosts_labels_delete(context, id, request_data)
|
||||
return None, 204, None
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from flask import g
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_log import log
|
||||
|
||||
|
@ -15,15 +14,15 @@ class Networks(base.Resource):
|
|||
|
||||
@base.http_codes
|
||||
@base.filtered_context()
|
||||
def get(self, context, **filters):
|
||||
def get(self, context, request_args):
|
||||
"""Get all networks, with optional filtering."""
|
||||
networks_obj = dbapi.networks_get_all(context, filters)
|
||||
networks_obj = dbapi.networks_get_all(context, request_args)
|
||||
return jsonutils.to_primitive(networks_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
def post(self, context):
|
||||
def post(self, context, request_data):
|
||||
"""Create a new network."""
|
||||
json = util.copy_project_id_into_json(context, g.json)
|
||||
json = util.copy_project_id_into_json(context, request_data)
|
||||
network_obj = dbapi.networks_create(context, json)
|
||||
return jsonutils.to_primitive(network_obj), 200, None
|
||||
|
||||
|
@ -39,9 +38,9 @@ class NetworkById(base.Resource):
|
|||
device['variables'] = jsonutils.to_primitive(obj.variables)
|
||||
return device, 200, None
|
||||
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
"""Update existing network values."""
|
||||
net_obj = dbapi.networks_update(context, id, g.json)
|
||||
net_obj = dbapi.networks_update(context, id, request_data)
|
||||
return jsonutils.to_primitive(net_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
|
@ -62,16 +61,16 @@ class NetworksVariables(base.Resource):
|
|||
return resp, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
""""Update existing variables, or create if it does not exist."""
|
||||
obj = dbapi.networks_variables_update(context, id, g.json)
|
||||
obj = dbapi.networks_variables_update(context, id, request_data)
|
||||
resp = {"variables": jsonutils.to_primitive(obj.variables)}
|
||||
return resp, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def delete(self, context, id):
|
||||
def delete(self, context, id, request_data):
|
||||
"""Delete networks variables."""
|
||||
dbapi.networks_variables_delete(context, id, g.json)
|
||||
dbapi.networks_variables_delete(context, id, request_data)
|
||||
return None, 204, None
|
||||
|
||||
|
||||
|
@ -80,15 +79,15 @@ class NetworkDevices(base.Resource):
|
|||
|
||||
@base.http_codes
|
||||
@base.filtered_context()
|
||||
def get(self, context, **filters):
|
||||
def get(self, context, request_args):
|
||||
"""Get all network devices."""
|
||||
devices_obj = dbapi.network_devices_get_all(context, filters)
|
||||
devices_obj = dbapi.network_devices_get_all(context, request_args)
|
||||
return jsonutils.to_primitive(devices_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
def post(self, context):
|
||||
def post(self, context, request_data):
|
||||
"""Create a new network device."""
|
||||
json = util.copy_project_id_into_json(context, g.json)
|
||||
json = util.copy_project_id_into_json(context, request_data)
|
||||
obj = dbapi.network_devices_create(context, json)
|
||||
device = jsonutils.to_primitive(obj)
|
||||
return device, 200, None
|
||||
|
@ -98,9 +97,9 @@ class NetworkDeviceById(base.Resource):
|
|||
"""Controller for Network Devices by ID."""
|
||||
|
||||
@base.http_codes
|
||||
def get(self, context, id):
|
||||
def get(self, context, id, request_args):
|
||||
"""Get network device by given id"""
|
||||
resolved_values = g.args["resolved-values"]
|
||||
resolved_values = request_args["resolved-values"]
|
||||
obj = dbapi.network_devices_get_by_id(context, id)
|
||||
if resolved_values:
|
||||
obj.vars = obj.resolved
|
||||
|
@ -110,9 +109,9 @@ class NetworkDeviceById(base.Resource):
|
|||
device['variables'] = jsonutils.to_primitive(obj.vars)
|
||||
return device, 200, None
|
||||
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
"""Update existing device values."""
|
||||
net_obj = dbapi.network_devices_update(context, id, g.json)
|
||||
net_obj = dbapi.network_devices_update(context, id, request_data)
|
||||
return jsonutils.to_primitive(net_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
|
@ -133,16 +132,16 @@ class NetworkDevicesVariables(base.Resource):
|
|||
return resp, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
""""Update device variables, or create if it does not exist."""
|
||||
obj = dbapi.network_devices_variables_update(context, id, g.json)
|
||||
obj = dbapi.network_devices_variables_update(context, id, request_data)
|
||||
resp = {"variables": jsonutils.to_primitive(obj.variables)}
|
||||
return resp, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def delete(self, context, id):
|
||||
def delete(self, context, id, request_data):
|
||||
"""Delete network device variables."""
|
||||
dbapi.network_devices_variables_delete(context, id, g.json)
|
||||
dbapi.network_devices_variables_delete(context, id, request_data)
|
||||
return None, 204, None
|
||||
|
||||
|
||||
|
@ -157,9 +156,9 @@ class NetworkDeviceLabels(base.Resource):
|
|||
return response, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
"""Update existing device label. Adds if it does not exist."""
|
||||
resp = dbapi.network_devices_labels_update(context, id, g.json)
|
||||
resp = dbapi.network_devices_labels_update(context, id, request_data)
|
||||
response = {"labels": list(resp.labels)}
|
||||
return response, 200, None
|
||||
|
||||
|
@ -175,15 +174,17 @@ class NetworkInterfaces(base.Resource):
|
|||
|
||||
@base.http_codes
|
||||
@base.filtered_context()
|
||||
def get(self, context, **filters):
|
||||
def get(self, context, request_args):
|
||||
"""Get all network interfaces."""
|
||||
interfaces_obj = dbapi.network_interfaces_get_all(context, filters)
|
||||
interfaces_obj = dbapi.network_interfaces_get_all(
|
||||
context, request_args
|
||||
)
|
||||
return jsonutils.to_primitive(interfaces_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
def post(self, context):
|
||||
def post(self, context, request_data):
|
||||
"""Create a new network interface."""
|
||||
json = util.copy_project_id_into_json(context, g.json)
|
||||
json = util.copy_project_id_into_json(context, request_data)
|
||||
obj = dbapi.network_interfaces_create(context, json)
|
||||
interface = jsonutils.to_primitive(obj)
|
||||
return interface, 200, None
|
||||
|
@ -199,9 +200,9 @@ class NetworkInterfaceById(base.Resource):
|
|||
interface['variables'] = jsonutils.to_primitive(obj.variables)
|
||||
return interface, 200, None
|
||||
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
"""Update existing network interface values."""
|
||||
net_obj = dbapi.network_interfaces_update(context, id, g.json)
|
||||
net_obj = dbapi.network_interfaces_update(context, id, request_data)
|
||||
return jsonutils.to_primitive(net_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from flask import g
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_log import log
|
||||
|
||||
|
@ -14,16 +13,16 @@ class Regions(base.Resource):
|
|||
|
||||
@base.http_codes
|
||||
@base.filtered_context()
|
||||
def get(self, context, **filters):
|
||||
def get(self, context, request_args):
|
||||
"""Get region(s) for the project. Get region details if
|
||||
for a particular region.
|
||||
"""
|
||||
region_id = filters.get("id")
|
||||
region_name = filters.get("name")
|
||||
region_id = request_args.get("id")
|
||||
region_name = request_args.get("name")
|
||||
|
||||
if not region_id and not region_name:
|
||||
# Get all regions for this tenant
|
||||
regions_obj = dbapi.regions_get_all(context, filters)
|
||||
regions_obj = dbapi.regions_get_all(context, request_args)
|
||||
return jsonutils.to_primitive(regions_obj), 200, None
|
||||
|
||||
if region_name:
|
||||
|
@ -37,9 +36,9 @@ class Regions(base.Resource):
|
|||
return jsonutils.to_primitive([region_obj]), 200, None
|
||||
|
||||
@base.http_codes
|
||||
def post(self, context):
|
||||
def post(self, context, request_data):
|
||||
"""Create a new region."""
|
||||
json = util.copy_project_id_into_json(context, g.json)
|
||||
json = util.copy_project_id_into_json(context, request_data)
|
||||
region_obj = dbapi.regions_create(context, json)
|
||||
region = jsonutils.to_primitive(region_obj)
|
||||
if 'variables' in json:
|
||||
|
@ -58,9 +57,9 @@ class RegionsById(base.Resource):
|
|||
region['variables'] = jsonutils.to_primitive(region_obj.variables)
|
||||
return region, 200, None
|
||||
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
"""Update existing region."""
|
||||
region_obj = dbapi.regions_update(context, id, g.json)
|
||||
region_obj = dbapi.regions_update(context, id, request_data)
|
||||
return jsonutils.to_primitive(region_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
|
@ -80,17 +79,17 @@ class RegionsVariables(base.Resource):
|
|||
return response, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def put(self, context, id):
|
||||
def put(self, context, id, request_data):
|
||||
"""
|
||||
Update existing region variables, or create if it does
|
||||
not exist.
|
||||
"""
|
||||
obj = dbapi.regions_variables_update(context, id, g.json)
|
||||
obj = dbapi.regions_variables_update(context, id, request_data)
|
||||
response = {"variables": jsonutils.to_primitive(obj.variables)}
|
||||
return response, 200, None
|
||||
|
||||
@base.http_codes
|
||||
def delete(self, context, id):
|
||||
def delete(self, context, id, request_data):
|
||||
"""Delete region variables."""
|
||||
dbapi.regions_variables_delete(context, id, g.json)
|
||||
dbapi.regions_variables_delete(context, id, request_data)
|
||||
return None, 204, None
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from flask import g
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_log import log
|
||||
|
||||
|
@ -12,10 +11,10 @@ LOG = log.getLogger(__name__)
|
|||
class Projects(base.Resource):
|
||||
|
||||
@base.http_codes
|
||||
def get(self, context):
|
||||
def get(self, context, request_args):
|
||||
"""Get all projects. Requires super admin privileges."""
|
||||
project_id = g.args["id"]
|
||||
project_name = g.args["name"]
|
||||
project_id = request_args["id"]
|
||||
project_name = request_args["name"]
|
||||
|
||||
if project_name:
|
||||
project_obj = dbapi.projects_get_by_name(context, project_name)
|
||||
|
@ -29,9 +28,9 @@ class Projects(base.Resource):
|
|||
return jsonutils.to_primitive(projects_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
def post(self, context):
|
||||
def post(self, context, request_data):
|
||||
"""Create a new project. Requires super admin privileges."""
|
||||
project_obj = dbapi.projects_create(context, g.json)
|
||||
project_obj = dbapi.projects_create(context, request_data)
|
||||
return jsonutils.to_primitive(project_obj), 200, None
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from flask import g
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_log import log
|
||||
from oslo_utils import uuidutils
|
||||
|
@ -14,10 +13,10 @@ LOG = log.getLogger(__name__)
|
|||
class Users(base.Resource):
|
||||
|
||||
@base.http_codes
|
||||
def get(self, context):
|
||||
def get(self, context, request_args):
|
||||
"""Get all users. Requires project admin privileges."""
|
||||
user_id = g.args["id"]
|
||||
user_name = g.args["name"]
|
||||
user_id = request_args["id"]
|
||||
user_name = request_args["name"]
|
||||
|
||||
if user_name:
|
||||
user_obj = dbapi.users_get_by_name(context, user_name)
|
||||
|
@ -33,13 +32,13 @@ class Users(base.Resource):
|
|||
return jsonutils.to_primitive(users_obj), 200, None
|
||||
|
||||
@base.http_codes
|
||||
def post(self, context):
|
||||
def post(self, context, request_data):
|
||||
"""Create a new user. Requires project admin privileges."""
|
||||
json = util.copy_project_id_into_json(context, g.json)
|
||||
json = util.copy_project_id_into_json(context, request_data)
|
||||
project_id = json["project_id"]
|
||||
dbapi.projects_get_by_id(context, project_id)
|
||||
api_key = uuidutils.generate_uuid()
|
||||
g.json["api_key"] = api_key
|
||||
request_data["api_key"] = api_key
|
||||
user_obj = dbapi.users_create(context, json)
|
||||
return jsonutils.to_primitive(user_obj), 200, None
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ from datetime import date
|
|||
from functools import wraps
|
||||
|
||||
from werkzeug.datastructures import MultiDict, Headers
|
||||
from flask import request, g, current_app, json
|
||||
from flask import request, current_app, json
|
||||
from flask_restful import abort
|
||||
from flask_restful.utils import unpack
|
||||
from jsonschema import Draft4Validator
|
||||
|
@ -231,11 +231,12 @@ def request_validate(view):
|
|||
if method == 'HEAD':
|
||||
method = 'GET'
|
||||
locations = validators.get((endpoint, method), {})
|
||||
data_type = {"json": "request_data", "args": "request_args"}
|
||||
for location, schema in locations.items():
|
||||
value = getattr(request, location, MultiDict())
|
||||
validator = FlaskValidatorAdaptor(schema)
|
||||
result = validator.validate(value)
|
||||
setattr(g, location, result)
|
||||
kwargs[data_type[location]] = result
|
||||
context = request.environ['context']
|
||||
return view(*args, context=context, **kwargs)
|
||||
|
||||
|
|
Loading…
Reference in New Issue