Merge "Allow resolved vars in details list calls"
This commit is contained in:
commit
8570377429
|
@ -7,7 +7,6 @@ import decorator
|
|||
|
||||
import flask
|
||||
import flask_restful as restful
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from craton.api.v1.validators import ensure_project_exists
|
||||
from craton.api.v1.validators import request_validate
|
||||
|
@ -31,19 +30,6 @@ class Resource(restful.Resource):
|
|||
return resp
|
||||
|
||||
|
||||
def get_resource_with_vars(obj):
|
||||
r_obj = []
|
||||
for resource in obj:
|
||||
r = jsonutils.to_primitive(resource, convert_instances=True)
|
||||
r['variables'] = jsonutils.to_primitive(resource.variables)
|
||||
r_obj.append(r)
|
||||
|
||||
if r_obj:
|
||||
return r_obj
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
@decorator.decorator
|
||||
def http_codes(f, *args, **kwargs):
|
||||
try:
|
||||
|
|
|
@ -23,7 +23,8 @@ class Cells(base.Resource):
|
|||
context, request_args, pagination_params,
|
||||
)
|
||||
if details:
|
||||
cells_obj = base.get_resource_with_vars(cells_obj)
|
||||
cells_obj = [utils.get_resource_with_vars(request_args, cell)
|
||||
for cell in cells_obj]
|
||||
|
||||
links = base.links_from(link_params)
|
||||
response_body = {'cells': cells_obj, 'links': links}
|
||||
|
@ -53,9 +54,7 @@ class CellById(base.Resource):
|
|||
@base.http_codes
|
||||
def get(self, context, id, request_args):
|
||||
cell_obj = dbapi.cells_get_by_id(context, id)
|
||||
cell_obj = utils.format_variables(request_args, cell_obj)
|
||||
cell = jsonutils.to_primitive(cell_obj)
|
||||
cell['variables'] = jsonutils.to_primitive(cell_obj.vars)
|
||||
cell = utils.get_resource_with_vars(request_args, cell_obj)
|
||||
return cell, 200, None
|
||||
|
||||
def put(self, context, id, request_data):
|
||||
|
|
|
@ -3,6 +3,7 @@ from oslo_log import log
|
|||
|
||||
from craton.api import v1
|
||||
from craton.api.v1 import base
|
||||
from craton.api.v1.resources import utils
|
||||
from craton import db as dbapi
|
||||
from craton import util
|
||||
|
||||
|
@ -20,12 +21,16 @@ class Clouds(base.Resource):
|
|||
"""
|
||||
cloud_id = request_args.get("id")
|
||||
cloud_name = request_args.get("name")
|
||||
details = request_args.get("details")
|
||||
|
||||
if not (cloud_id or cloud_name):
|
||||
# Get all clouds for this project
|
||||
clouds_obj, link_params = dbapi.clouds_get_all(
|
||||
context, request_args, pagination_params,
|
||||
)
|
||||
if details:
|
||||
clouds_obj = [utils.get_resource_with_vars(request_args, c)
|
||||
for c in clouds_obj]
|
||||
else:
|
||||
if cloud_name:
|
||||
cloud_obj = dbapi.clouds_get_by_name(context, cloud_name)
|
||||
|
|
|
@ -17,6 +17,7 @@ class Devices(base.Resource):
|
|||
@base.pagination_context
|
||||
def get(self, context, request_args, pagination_params):
|
||||
"""Get all devices, with optional filtering."""
|
||||
details = request_args.get("details")
|
||||
device_objs, link_params = dbapi.devices_get_all(
|
||||
context, request_args, pagination_params,
|
||||
)
|
||||
|
@ -24,7 +25,12 @@ class Devices(base.Resource):
|
|||
|
||||
devices = {"hosts": [], "network-devices": []}
|
||||
for device_obj in device_objs:
|
||||
device = jsonutils.to_primitive(device_obj)
|
||||
if details:
|
||||
device = utils.get_resource_with_vars(request_args,
|
||||
device_obj)
|
||||
else:
|
||||
device = jsonutils.to_primitive(device_obj)
|
||||
|
||||
utils.add_up_link(context, device)
|
||||
|
||||
if isinstance(device_obj, models.Host):
|
||||
|
|
|
@ -22,7 +22,8 @@ class Hosts(base.Resource):
|
|||
context, request_args, pagination_params,
|
||||
)
|
||||
if details:
|
||||
hosts_obj = base.get_resource_with_vars(hosts_obj)
|
||||
hosts_obj = [utils.get_resource_with_vars(request_args, h)
|
||||
for h in hosts_obj]
|
||||
|
||||
links = base.links_from(link_params)
|
||||
response_body = jsonutils.to_primitive(
|
||||
|
@ -61,9 +62,7 @@ class HostById(base.Resource):
|
|||
def get(self, context, id, request_args):
|
||||
"""Get host by given id"""
|
||||
host_obj = dbapi.hosts_get_by_id(context, id)
|
||||
host_obj = utils.format_variables(request_args, host_obj)
|
||||
host = jsonutils.to_primitive(host_obj)
|
||||
host['variables'] = jsonutils.to_primitive(host_obj.vars)
|
||||
host = utils.get_resource_with_vars(request_args, host_obj)
|
||||
|
||||
utils.add_up_link(context, host)
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ class Networks(base.Resource):
|
|||
context, request_args, pagination_params,
|
||||
)
|
||||
if details:
|
||||
networks_obj = base.get_resource_with_vars(networks_obj)
|
||||
networks_obj = [utils.get_resource_with_vars(request_args, n)
|
||||
for n in networks_obj]
|
||||
|
||||
links = base.links_from(link_params)
|
||||
response_body = {'networks': networks_obj, 'links': links}
|
||||
|
@ -78,7 +79,8 @@ class NetworkDevices(base.Resource):
|
|||
context, request_args, pagination_params,
|
||||
)
|
||||
if details:
|
||||
devices_obj = base.get_resource_with_vars(devices_obj)
|
||||
devices_obj = [utils.get_resource_with_vars(request_args, d)
|
||||
for d in devices_obj]
|
||||
|
||||
links = base.links_from(link_params)
|
||||
response_body = jsonutils.to_primitive(
|
||||
|
|
|
@ -29,7 +29,8 @@ class Regions(base.Resource):
|
|||
context, request_args, pagination_params,
|
||||
)
|
||||
if details:
|
||||
regions_obj = base.get_resource_with_vars(regions_obj)
|
||||
regions_obj = [utils.get_resource_with_vars(request_args, r)
|
||||
for r in regions_obj]
|
||||
else:
|
||||
if region_name:
|
||||
region_obj = dbapi.regions_get_by_name(context, region_name)
|
||||
|
@ -69,9 +70,7 @@ class RegionsById(base.Resource):
|
|||
@base.http_codes
|
||||
def get(self, context, id, request_args):
|
||||
region_obj = dbapi.regions_get_by_id(context, id)
|
||||
region_obj = utils.format_variables(request_args, region_obj)
|
||||
region = jsonutils.to_primitive(region_obj)
|
||||
region['variables'] = jsonutils.to_primitive(region_obj.vars)
|
||||
region = utils.get_resource_with_vars(request_args, region_obj)
|
||||
return region, 200, None
|
||||
|
||||
def put(self, context, id, request_data):
|
||||
|
|
|
@ -3,6 +3,7 @@ from oslo_log import log
|
|||
|
||||
from craton.api import v1
|
||||
from craton.api.v1 import base
|
||||
from craton.api.v1.resources import utils
|
||||
from craton import db as dbapi
|
||||
|
||||
|
||||
|
@ -16,6 +17,7 @@ class Projects(base.Resource):
|
|||
def get(self, context, request_args, pagination_params):
|
||||
"""Get all projects. Requires super admin privileges."""
|
||||
project_name = request_args["name"]
|
||||
details = request_args.get("details")
|
||||
|
||||
if project_name:
|
||||
projects_obj, link_params = dbapi.projects_get_by_name(
|
||||
|
@ -25,6 +27,10 @@ class Projects(base.Resource):
|
|||
projects_obj, link_params = dbapi.projects_get_all(
|
||||
context, request_args, pagination_params,
|
||||
)
|
||||
if details:
|
||||
projects_obj = [utils.get_resource_with_vars(request_args, p)
|
||||
for p in projects_obj]
|
||||
|
||||
links = base.links_from(link_params)
|
||||
response_body = {'projects': projects_obj, 'links': links}
|
||||
return jsonutils.to_primitive(response_body), 200, None
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from flask import url_for
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from craton import db as dbapi
|
||||
|
||||
|
@ -6,7 +7,7 @@ from craton import db as dbapi
|
|||
def format_variables(args, obj):
|
||||
"""Update resource response with requested type of variables."""
|
||||
if args:
|
||||
resolved_values = args["resolved-values"]
|
||||
resolved_values = args.get("resolved-values", None)
|
||||
else:
|
||||
resolved_values = None
|
||||
|
||||
|
@ -17,6 +18,14 @@ def format_variables(args, obj):
|
|||
return obj
|
||||
|
||||
|
||||
def get_resource_with_vars(args, obj):
|
||||
"""Get resource in json primitive with variables."""
|
||||
obj = format_variables(args, obj)
|
||||
res = jsonutils.to_primitive(obj)
|
||||
res['variables'] = jsonutils.to_primitive(obj.vars)
|
||||
return res
|
||||
|
||||
|
||||
def get_device_type(context, device_id):
|
||||
device = dbapi.resource_get_by_id(context, "devices", device_id)
|
||||
return device.type
|
||||
|
|
|
@ -833,6 +833,14 @@ validators = {
|
|||
"default": False,
|
||||
"type": "boolean",
|
||||
},
|
||||
"resolved-values": {
|
||||
"default": True,
|
||||
"type": "boolean",
|
||||
},
|
||||
"details": {
|
||||
"default": False,
|
||||
"type": "boolean",
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
@ -916,6 +924,10 @@ validators = {
|
|||
"type": "integer",
|
||||
"description": "ID of the region to get",
|
||||
},
|
||||
"resolved-values": {
|
||||
"default": True,
|
||||
"type": "boolean",
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
@ -938,6 +950,10 @@ validators = {
|
|||
"type": "integer",
|
||||
"description": "ID of the cloud to get",
|
||||
},
|
||||
"details": {
|
||||
"default": False,
|
||||
"type": "boolean",
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
@ -991,6 +1007,10 @@ validators = {
|
|||
"type": "integer",
|
||||
"description": "ID of host to get",
|
||||
},
|
||||
"resolved-values": {
|
||||
"default": True,
|
||||
"type": "boolean",
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
@ -1051,6 +1071,10 @@ validators = {
|
|||
"type": "string",
|
||||
"description": "name of the cell to get",
|
||||
},
|
||||
"resolved-values": {
|
||||
"default": True,
|
||||
"type": "boolean",
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
@ -1111,6 +1135,10 @@ validators = {
|
|||
"type": "string",
|
||||
"description": "variable filters to get a project",
|
||||
},
|
||||
"details": {
|
||||
"default": False,
|
||||
"type": "boolean",
|
||||
},
|
||||
}, marker_type="string"),
|
||||
},
|
||||
},
|
||||
|
@ -1187,6 +1215,10 @@ validators = {
|
|||
"type": "string",
|
||||
"description": "cell id of the device to get",
|
||||
},
|
||||
"resolved-values": {
|
||||
"default": True,
|
||||
"type": "boolean",
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
@ -1377,6 +1409,14 @@ validators = {
|
|||
"type": "string",
|
||||
"description": "cell idof the network to get",
|
||||
},
|
||||
"resolved-values": {
|
||||
"default": True,
|
||||
"type": "boolean",
|
||||
},
|
||||
"details": {
|
||||
"default": False,
|
||||
"type": "boolean",
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
|
|
@ -366,10 +366,11 @@ class DeviceTestBase(TestCase):
|
|||
def create_cloud(self, name='cloud-1'):
|
||||
return super(DeviceTestBase, self).create_cloud(name=name)
|
||||
|
||||
def create_region(self, name='region-1', cloud=None):
|
||||
def create_region(self, name='region-1', cloud=None, variables=None):
|
||||
return super(DeviceTestBase, self).create_region(
|
||||
name=name,
|
||||
cloud=cloud if cloud else self.cloud
|
||||
cloud=cloud if cloud else self.cloud,
|
||||
variables=variables,
|
||||
)
|
||||
|
||||
def create_network_device(self, name, device_type, ip_address, region=None,
|
||||
|
|
|
@ -89,6 +89,24 @@ class APIV1CellTest(APIV1ResourceWithVariablesTestCase):
|
|||
"('updated_at' was unexpected)"]
|
||||
self.assertEqual(cell.json()['errors'], msg)
|
||||
|
||||
def test_cells_get_all_with_details(self):
|
||||
self.create_cell('cell1', variables={'a': 'b'})
|
||||
self.create_cell('cell2', variables={'c': 'd'})
|
||||
url = self.url + '/v1/cells?details=all'
|
||||
resp = self.get(url)
|
||||
cells = resp.json()['cells']
|
||||
self.assertEqual(2, len(cells))
|
||||
for cell in cells:
|
||||
self.assertTrue('variables' in cell)
|
||||
|
||||
for cell in cells:
|
||||
if cell['name'] == 'cell1':
|
||||
expected = {'a': 'b', "region": "one"}
|
||||
self.assertEqual(expected, cell['variables'])
|
||||
if cell['name'] == 'cell2':
|
||||
expected = {'c': 'd', "region": "one"}
|
||||
self.assertEqual(expected, cell['variables'])
|
||||
|
||||
def test_cells_get_all_for_region(self):
|
||||
# Create a cell first
|
||||
self.create_cell('cell-1')
|
||||
|
|
|
@ -85,6 +85,23 @@ class APIV1CloudTest(TestCase):
|
|||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(2, len(resp.json()))
|
||||
|
||||
def test_clouds_get_all_with_details_filter(self):
|
||||
c1 = self.create_cloud("ORD1", variables={'a': 'b'})
|
||||
c2 = self.create_cloud("ORD2", variables={'c': 'd'})
|
||||
url = self.url + '/v1/clouds?details=all'
|
||||
resp = self.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
clouds = resp.json()['clouds']
|
||||
self.assertEqual(2, len(clouds))
|
||||
for cloud in clouds:
|
||||
self.assertTrue('variables' in cloud)
|
||||
|
||||
for cloud in clouds:
|
||||
if cloud['name'] == 'ORD1':
|
||||
self.assertEqual(c1['variables'], {'a': 'b'})
|
||||
if cloud['name'] == 'ORD2':
|
||||
self.assertEqual(c2['variables'], {'c': 'd'})
|
||||
|
||||
def test_clouds_get_all_with_name_filter(self):
|
||||
self.create_cloud("ORD1")
|
||||
self.create_cloud("ORD2")
|
||||
|
|
|
@ -96,6 +96,23 @@ class APIV1HostTest(DeviceTestBase, APIV1ResourceWithVariablesTestCase):
|
|||
"('updated_at' was unexpected)"]
|
||||
self.assertEqual(host.json()['errors'], msg)
|
||||
|
||||
def test_get_all_hosts_with_details(self):
|
||||
region_vars = {'x': 'y'}
|
||||
region = self.create_region(name='region1', variables=region_vars)
|
||||
variables = {"a": "b"}
|
||||
self.create_host('host1', 'server', '192.168.1.1', region=region,
|
||||
**variables)
|
||||
self.create_host('host2', 'server', '192.168.1.2', region=region,
|
||||
**variables)
|
||||
url = self.url + '/v1/hosts?details=all'
|
||||
resp = self.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
hosts = resp.json()['hosts']
|
||||
self.assertEqual(2, len(hosts))
|
||||
for host in hosts:
|
||||
self.assertTrue('variables' in host)
|
||||
self.assertEqual({'a': 'b', 'x': 'y'}, host['variables'])
|
||||
|
||||
def test_host_get_by_ip_filter(self):
|
||||
self.create_host('host1', 'server', '192.168.1.1')
|
||||
self.create_host('host2', 'server', '192.168.1.2')
|
||||
|
|
|
@ -104,3 +104,29 @@ class APIV1NetworkSchemaTest(TestCase):
|
|||
msg = ["Additional properties are not allowed ('updated_at' was "
|
||||
"unexpected)"]
|
||||
self.assertEqual(network.json()['errors'], msg)
|
||||
|
||||
def test_network_get_all_with_details(self):
|
||||
payload = {
|
||||
'cloud_id': self.cloud['id'],
|
||||
'region_id': self.region['id'],
|
||||
'name': 'a',
|
||||
'cidr': self.cidr,
|
||||
'netmask': self.netmask,
|
||||
'gateway': self.gateway,
|
||||
'variables': {'a': 'b'},
|
||||
}
|
||||
resp = self.post(self.networks_url, data=payload)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
|
||||
payload['name'] = 'b'
|
||||
resp = self.post(self.networks_url, data=payload)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
|
||||
url = self.networks_url + '?details=all'
|
||||
resp = self.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
networks = resp.json()['networks']
|
||||
|
||||
for network in networks:
|
||||
self.assertTrue('variables' in network)
|
||||
self.assertEqual({'a': 'b'}, network['variables'])
|
||||
|
|
|
@ -118,6 +118,24 @@ class APIV1RegionTest(RegionTests):
|
|||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(2, len(resp.json()))
|
||||
|
||||
def test_regions_get_all_with_details(self):
|
||||
self.create_region('ORD1', variables={'a': 'b'})
|
||||
self.create_region('ORD2', variables={'c': 'd'})
|
||||
url = self.url + '/v1/regions?details=all'
|
||||
resp = self.get(url)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
regions = resp.json()['regions']
|
||||
self.assertEqual(2, len(regions))
|
||||
for region in regions:
|
||||
self.assertTrue('variables' in region)
|
||||
for region in regions:
|
||||
if region['name'] == 'ORD1':
|
||||
self.assertEqual({'a': 'b', 'version': 'x'},
|
||||
region['variables'])
|
||||
if region['name'] == 'ORD2':
|
||||
self.assertEqual({'c': 'd', 'version': 'x'},
|
||||
region['variables'])
|
||||
|
||||
def test_regions_get_all_with_name_filter(self):
|
||||
self.create_region("ORD1")
|
||||
self.create_region("ORD2")
|
||||
|
|
|
@ -153,6 +153,7 @@ class Networks(object):
|
|||
self.gateway = gateway
|
||||
self.netmask = netmask
|
||||
self.variables = variables
|
||||
self.resolved = copy.copy(variables)
|
||||
self.labels = labels
|
||||
self.cloud_id = cloud_id
|
||||
self.region_id = region_id
|
||||
|
|
|
@ -252,7 +252,8 @@ class APIV1CellsTest(APIV1Test):
|
|||
resp = self.get('v1/cells')
|
||||
self.assertEqual(len(resp.json), len(fake_resources.CELL_LIST))
|
||||
mock_cells.assert_called_once_with(
|
||||
mock.ANY, {}, {'limit': 30, 'marker': None},
|
||||
mock.ANY, {'resolved-values': True},
|
||||
{'limit': 30, 'marker': None},
|
||||
)
|
||||
|
||||
@mock.patch.object(dbapi, 'cells_get_all')
|
||||
|
@ -932,7 +933,8 @@ class APIV1HostsTest(APIV1Test):
|
|||
resp = self.get('/v1/hosts')
|
||||
self.assertEqual(len(resp.json['hosts']), 3)
|
||||
fake_hosts.assert_called_once_with(
|
||||
mock.ANY, {}, {'limit': 30, 'marker': None},
|
||||
mock.ANY, {'resolved-values': True},
|
||||
{'limit': 30, 'marker': None},
|
||||
)
|
||||
|
||||
@mock.patch.object(dbapi, 'hosts_get_all')
|
||||
|
@ -949,6 +951,7 @@ class APIV1HostsTest(APIV1Test):
|
|||
ip_address = '10.10.0.1'
|
||||
filters = {
|
||||
'region_id': 1, 'ip_address': ip_address,
|
||||
'resolved-values': True,
|
||||
}
|
||||
path_query = '/v1/hosts?region_id={}&ip_address={}'.format(
|
||||
region_id, ip_address
|
||||
|
@ -1312,7 +1315,8 @@ class APIV1NetworksTest(APIV1Test):
|
|||
resp = self.get('/v1/networks')
|
||||
self.assertEqual(len(resp.json['networks']), 3)
|
||||
fake_networks.assert_called_once_with(
|
||||
mock.ANY, {}, {'limit': 30, 'marker': None},
|
||||
mock.ANY, {'resolved-values': True, 'details': False},
|
||||
{'limit': 30, 'marker': None},
|
||||
)
|
||||
|
||||
@mock.patch.object(dbapi, 'networks_get_all')
|
||||
|
@ -1511,7 +1515,8 @@ class APIV1NetworkDevicesTest(APIV1Test):
|
|||
def test_get_network_devices_by_ip_address_filter(self, fake_devices):
|
||||
region_id = '1'
|
||||
ip_address = '10.10.0.1'
|
||||
filters = {'region_id': region_id, 'ip_address': ip_address}
|
||||
filters = {'region_id': region_id, 'ip_address': ip_address,
|
||||
'resolved-values': True}
|
||||
path_query = '/v1/network-devices?region_id={}&ip_address={}'.format(
|
||||
region_id, ip_address
|
||||
)
|
||||
|
@ -1538,7 +1543,8 @@ class APIV1NetworkDevicesTest(APIV1Test):
|
|||
resp = self.get('/v1/network-devices')
|
||||
self.assertEqual(len(resp.json), 2)
|
||||
fake_devices.assert_called_once_with(
|
||||
mock.ANY, {}, {'limit': 30, 'marker': None},
|
||||
mock.ANY, {'resolved-values': True},
|
||||
{'limit': 30, 'marker': None},
|
||||
)
|
||||
|
||||
@mock.patch.object(dbapi, 'network_devices_get_all')
|
||||
|
|
Loading…
Reference in New Issue