Apply API-WG guidelines for naming resources

The URLs defined in the routes have been updated to replace underscores
with hyphens. The tests have been updated to account for this change. In
addition tests have been added to ensure that the URLs meet the
API-WG guidelines [1], namely that they contain only lowercase characters
and do not contain punctuation, with the exception of hyphens.

[1] https://specs.openstack.org/openstack/api-wg/guidelines/naming.html

Change-Id: I77c02de2973e12c6fbcdcc925fa6686aa1f7a094
Closes-Bug: 1657889
This commit is contained in:
Mark Harrington 2017-01-21 15:40:20 +00:00
parent 1f11f58a00
commit 9fe3e18812
5 changed files with 66 additions and 43 deletions

View File

@ -10,7 +10,7 @@ from craton.api.v1.resources.inventory import networks
routes = [
dict(resource=ansible_inventory.AnsibleInventory,
urls=['/ansible_inventory'],
urls=['/ansible-inventory'],
endpoint='ansible_inventory'),
dict(resource=hosts.HostsVariables,
urls=['/hosts/<id>/variables'],
@ -64,21 +64,21 @@ routes = [
urls=['/networks/<id>'],
endpoint='networks_id'),
dict(resource=networks.NetworkInterfaces,
urls=['/network_interfaces'],
urls=['/network-interfaces'],
endpoint='network_interfaces'),
dict(resource=networks.NetworkInterfaceById,
urls=['/network_interfaces/<id>'],
urls=['/network-interfaces/<id>'],
endpoint='network_interfaces_id'),
dict(resource=networks.NetworkDevices,
urls=['/network_devices'],
urls=['/network-devices'],
endpoint='network_devices'),
dict(resource=networks.NetworkDeviceById,
urls=['/network_devices/<id>'],
urls=['/network-devices/<id>'],
endpoint='network_devices_id'),
dict(resource=networks.NetworkDevicesVariables,
urls=['/network_devices/<id>/variables'],
urls=['/network-devices/<id>/variables'],
endpoint='network_devices_id_variables'),
dict(resource=networks.NetworkDeviceLabels,
urls=['/network_devices/<id>/labels'],
urls=['/network-devices/<id>/labels'],
endpoint='network_devices_labels'),
]

View File

@ -957,7 +957,7 @@ class APIV1NetworkDevicesIDTest(APIV1Test):
@mock.patch.object(dbapi, 'network_devices_get_by_id')
def test_get_network_devices_by_id_invalid_property(self, fake_device):
fake_device.return_value = fake_resources.NETWORK_DEVICE1
resp = self.get('/v1/network_devices/1?foo=isaninvalidproperty')
resp = self.get('/v1/network-devices/1?foo=isaninvalidproperty')
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.json['hostname'], 'NetDevices1')
fake_device.assert_called_once_with(mock.ANY, '1')
@ -965,7 +965,7 @@ class APIV1NetworkDevicesIDTest(APIV1Test):
@mock.patch.object(dbapi, 'network_devices_get_by_id')
def test_get_network_devices_by_id(self, fake_device):
fake_device.return_value = fake_resources.NETWORK_DEVICE1
resp = self.get('/v1/network_devices/1')
resp = self.get('/v1/network-devices/1')
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.json['hostname'], 'NetDevices1')
fake_device.assert_called_once_with(mock.ANY, '1')
@ -975,7 +975,7 @@ class APIV1NetworkDevicesIDTest(APIV1Test):
payload = {"hostname": "NetDev_New1"}
fake_device.return_value = dict(fake_resources.NETWORK_DEVICE1.items(),
**payload)
resp = self.put('v1/network_devices/1', data=payload)
resp = self.put('v1/network-devices/1', data=payload)
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.json['hostname'], "NetDev_New1")
fake_device.assert_called_once_with(
@ -986,20 +986,20 @@ class APIV1NetworkDevicesIDTest(APIV1Test):
def test_put_network_device_invalid_property(self, fake_device):
fake_device.return_value = fake_resources.NETWORK_DEVICE1
payload = {"foo": "isinvalid"}
resp = self.put('v1/network_devices/1', data=payload)
resp = self.put('v1/network-devices/1', data=payload)
self.assertEqual(resp.status_code, 200)
fake_device.assert_called_once_with(mock.ANY, '1', {})
@mock.patch.object(dbapi, 'network_devices_get_by_id')
def test_get_network_devices_get_by_id(self, mock_devices):
mock_devices.return_value = fake_resources.NETWORK_DEVICE1
resp = self.get('/v1/network_devices/1')
resp = self.get('/v1/network-devices/1')
self.assertEqual(resp.json["hostname"],
fake_resources.NETWORK_DEVICE1.hostname)
@mock.patch.object(dbapi, 'network_devices_delete')
def test_delete_network_devices(self, mock_devices):
resp = self.delete('v1/network_devices/1')
resp = self.delete('v1/network-devices/1')
self.assertEqual(204, resp.status_code)
@ -1009,7 +1009,7 @@ class APIV1NetworkDevicesTest(APIV1Test):
region_id = '1'
ip_address = '10.10.0.1'
filters = {'region_id': region_id, 'ip_address': ip_address}
path_query = '/v1/network_devices?region_id={}&ip_address={}'.format(
path_query = '/v1/network-devices?region_id={}&ip_address={}'.format(
region_id, ip_address
)
fake_devices.return_value = fake_resources.NETWORK_DEVICE_LIST1
@ -1024,21 +1024,21 @@ class APIV1NetworkDevicesTest(APIV1Test):
@mock.patch.object(dbapi, 'network_devices_get_all')
def test_get_network_devices_invalid_property(self, fake_devices):
fake_devices.return_value = fake_resources.NETWORK_DEVICE_LIST2
resp = self.get('/v1/network_devices?foo=isaninvalidproperty')
resp = self.get('/v1/network-devices?foo=isaninvalidproperty')
self.assertEqual(len(resp.json), 2)
fake_devices.assert_called_once_with(mock.ANY, {})
@mock.patch.object(dbapi, 'network_devices_get_all')
def test_get_network_devices(self, fake_devices):
fake_devices.return_value = fake_resources.NETWORK_DEVICE_LIST2
resp = self.get('/v1/network_devices')
resp = self.get('/v1/network-devices')
self.assertEqual(len(resp.json), 2)
fake_devices.assert_called_once_with(mock.ANY, {})
@mock.patch.object(dbapi, 'network_devices_get_all')
def test_network_devices_get_by_region(self, mock_devices):
mock_devices.return_value = fake_resources.NETWORK_DEVICE_LIST1
resp = self.get('/v1/network_devices?region_id=1')
resp = self.get('/v1/network-devices?region_id=1')
self.assertEqual(len(resp.json), 1)
self.assertEqual(200, resp.status_code)
self.assertEqual(
@ -1051,7 +1051,7 @@ class APIV1NetworkDevicesTest(APIV1Test):
mock_devices.return_value = None
data = {'hostname': 'NewNetDevice1', 'region_id': 1,
'device_type': 'Sample', 'ip_address': '0.0.0.0'}
resp = self.post('/v1/network_devices', data=data)
resp = self.post('/v1/network-devices', data=data)
self.assertEqual(200, resp.status_code)
@mock.patch.object(dbapi, 'network_devices_create')
@ -1059,7 +1059,7 @@ class APIV1NetworkDevicesTest(APIV1Test):
mock_devices.return_value = None
# data is missing entry
data = {'hostname': 'Sample'}
resp = self.post('/v1/network_devices', data=data)
resp = self.post('/v1/network-devices', data=data)
self.assertEqual(422, resp.status_code)
@mock.patch.object(dbapi, 'network_devices_create')
@ -1068,7 +1068,7 @@ class APIV1NetworkDevicesTest(APIV1Test):
data = {'hostname': 'NewNetDevice1', 'region_id': 1,
'device_type': 'Sample', 'ip_address': '0.0.0.0',
'foo': 'isinvalid'}
resp = self.post('/v1/network_devices', data=data)
resp = self.post('/v1/network-devices', data=data)
self.assertEqual(200, resp.status_code)
mock_devices.assert_called_once()
@ -1078,7 +1078,7 @@ class APIV1NetworkDevicesLabelsTest(APIV1Test):
def test_network_devices_labels_update(self, mock_devices):
payload = {"labels": ["a", "b"]}
mock_devices.return_value = fake_resources.NETWORK_DEVICE1
resp = self.put('v1/network_devices/1/labels', data=payload)
resp = self.put('v1/network-devices/1/labels', data=payload)
self.assertEqual(200, resp.status_code)
self.assertEqual(resp.json, payload)
@ -1086,7 +1086,7 @@ class APIV1NetworkDevicesLabelsTest(APIV1Test):
def test_network_devices_labels_update_invalid_property(self, fake_device):
fake_device.return_value = fake_resources.NETWORK_DEVICE1
payload = {"foo": "isinvalid"}
resp = self.put('v1/network_devices/1/labels', data=payload)
resp = self.put('v1/network-devices/1/labels', data=payload)
self.assertEqual(resp.status_code, 200)
fake_device.assert_called_once_with(mock.ANY, '1', {})
@ -1094,14 +1094,14 @@ class APIV1NetworkDevicesLabelsTest(APIV1Test):
def test_network_devices_delete_labels(self, mock_network_device):
payload = {"labels": ["label1", "label2"]}
db_data = payload.copy()
resp = self.delete('v1/network_devices/1/labels', data=payload)
resp = self.delete('v1/network-devices/1/labels', data=payload)
self.assertEqual(resp.status_code, 204)
mock_network_device.assert_called_once_with(mock.ANY, '1', db_data)
@mock.patch.object(dbapi, 'network_devices_labels_delete')
def test_network_devices_delete_bad_data_type(self, mock_network_device):
payload = ["label1", "label2"]
resp = self.delete('v1/network_devices/1/labels', data=payload)
resp = self.delete('v1/network-devices/1/labels', data=payload)
self.assertEqual(resp.status_code, 422)
mock_network_device.assert_not_called()
@ -1110,7 +1110,7 @@ class APIV1NetworkDevicesVariablesTest(APIV1Test):
@mock.patch.object(dbapi, 'network_devices_get_by_id')
def test_network_devices_get_variables(self, mock_network_device):
mock_network_device.return_value = fake_resources.NETWORK_DEVICE1
resp = self.get('v1/network_devices/1/variables')
resp = self.get('v1/network-devices/1/variables')
expected = {"variables": {"key1": "value1", "key2": "value2"}}
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.json, expected)
@ -1120,7 +1120,7 @@ class APIV1NetworkDevicesVariablesTest(APIV1Test):
mock_network_device.return_value = fake_resources.NETWORK_DEVICE1
payload = {"a": "b"}
db_data = payload.copy()
resp = self.put('v1/network_devices/1/variables', data=payload)
resp = self.put('v1/network-devices/1/variables', data=payload)
self.assertEqual(resp.status_code, 200)
mock_network_device.assert_called_once_with(mock.ANY, '1', db_data)
@ -1128,7 +1128,7 @@ class APIV1NetworkDevicesVariablesTest(APIV1Test):
def test_network_devices_put_bad_data_type(self, mock_network_device):
mock_network_device.return_value = fake_resources.NETWORK_DEVICE1
payload = ["a", "b"]
resp = self.put('v1/network_devices/1/variables', data=payload)
resp = self.put('v1/network-devices/1/variables', data=payload)
self.assertEqual(resp.status_code, 422)
mock_network_device.assert_not_called()
@ -1136,14 +1136,14 @@ class APIV1NetworkDevicesVariablesTest(APIV1Test):
def test_network_devices_delete_variables(self, mock_network_device):
payload = {"key1": "value1"}
db_data = payload.copy()
resp = self.delete('v1/network_devices/1/variables', data=payload)
resp = self.delete('v1/network-devices/1/variables', data=payload)
self.assertEqual(resp.status_code, 204)
mock_network_device.assert_called_once_with(mock.ANY, '1', db_data)
@mock.patch.object(dbapi, 'network_devices_variables_delete')
def test_network_devices_delete_bad_data_type(self, mock_network_device):
payload = ["a", "b"]
resp = self.delete('v1/network_devices/1/variables', data=payload)
resp = self.delete('v1/network-devices/1/variables', data=payload)
self.assertEqual(resp.status_code, 422)
mock_network_device.assert_not_called()
@ -1155,7 +1155,7 @@ class APIV1NetworkInterfacesTest(APIV1Test):
ip_address = '10.10.0.1'
filters = {'device_id': device_id, 'ip_address': ip_address}
path_query = (
'/v1/network_interfaces?device_id={}&ip_address={}'.format(
'/v1/network-interfaces?device_id={}&ip_address={}'.format(
device_id, ip_address
)
)
@ -1170,7 +1170,7 @@ class APIV1NetworkInterfacesTest(APIV1Test):
@mock.patch.object(dbapi, 'network_interfaces_get_all')
def test_get_network_interfaces_by_device_id(self, fake_interfaces):
fake_interfaces.return_value = fake_resources.NETWORK_INTERFACE_LIST1
resp = self.get('/v1/network_interfaces?name=NetInterface&device_id=1')
resp = self.get('/v1/network-interfaces?name=NetInterface&device_id=1')
network_interface_resp = fake_resources.NETWORK_INTERFACE1
self.assertEqual(resp.json[0]["name"], network_interface_resp.name)
@ -1179,7 +1179,7 @@ class APIV1NetworkInterfacesTest(APIV1Test):
fake_interfaces.return_value = None
data = {'name': 'NewNetInterface', 'device_id': 1,
'ip_address': '0.0.0.0', 'interface_type': 'Sample'}
resp = self.post('/v1/network_interfaces', data=data)
resp = self.post('/v1/network-interfaces', data=data)
self.assertEqual(200, resp.status_code)
@mock.patch.object(dbapi, 'network_interfaces_create')
@ -1187,7 +1187,7 @@ class APIV1NetworkInterfacesTest(APIV1Test):
fake_interfaces.return_value = fake_resources.NETWORK_INTERFACE1
# data is missing entry
data = {'name': 'sample'}
resp = self.post('/v1/network_interfaces', data=data)
resp = self.post('/v1/network-interfaces', data=data)
self.assertEqual(422, resp.status_code)
@mock.patch.object(dbapi, 'network_interfaces_create')
@ -1196,14 +1196,14 @@ class APIV1NetworkInterfacesTest(APIV1Test):
data = {'name': 'NewNetInterface', 'device_id': 1,
'ip_address': '0.0.0.0', 'interface_type': 'Sample',
'foo': 'isinvalid'}
resp = self.post('/v1/network_interfaces', data=data)
resp = self.post('/v1/network-interfaces', data=data)
self.assertEqual(200, resp.status_code)
fake_interfaces.assert_called_once()
@mock.patch.object(dbapi, 'network_interfaces_get_all')
def test_get_network_interfaces(self, fake_interfaces):
fake_interfaces.return_value = fake_resources.NETWORK_INTERFACE_LIST2
resp = self.get('/v1/network_interfaces')
resp = self.get('/v1/network-interfaces')
self.assertEqual(200, resp.status_code)
self.assertEqual(len(resp.json), 2)
fake_interfaces.assert_called_once_with(mock.ANY, {})
@ -1211,7 +1211,7 @@ class APIV1NetworkInterfacesTest(APIV1Test):
@mock.patch.object(dbapi, 'network_interfaces_get_all')
def test_get_network_interfaces_invalid_property(self, fake_interfaces):
fake_interfaces.return_value = fake_resources.NETWORK_INTERFACE_LIST2
resp = self.get('/v1/network_interfaces?foo=invalid')
resp = self.get('/v1/network-interfaces?foo=invalid')
self.assertEqual(200, resp.status_code)
self.assertEqual(len(resp.json), 2)
fake_interfaces.assert_called_once_with(mock.ANY, {})
@ -1221,7 +1221,7 @@ class APIV1NetworkInterfacesIDTest(APIV1Test):
@mock.patch.object(dbapi, 'network_interfaces_get_by_id')
def test_get_network_interfaces_by_id(self, fake_interfaces):
fake_interfaces.return_value = fake_resources.NETWORK_INTERFACE1
resp = self.get('/v1/network_interfaces/1')
resp = self.get('/v1/network-interfaces/1')
self.assertEqual(resp.json["name"],
fake_resources.NETWORK_INTERFACE1.name)
@ -1233,7 +1233,7 @@ class APIV1NetworkInterfacesIDTest(APIV1Test):
record.update(payload)
fake_interfaces.return_value = record
resp = self.put('/v1/network_interfaces/1', data=payload)
resp = self.put('/v1/network-interfaces/1', data=payload)
self.assertEqual(resp.json['name'], db_data['name'])
self.assertEqual(200, resp.status_code)
@ -1243,7 +1243,7 @@ class APIV1NetworkInterfacesIDTest(APIV1Test):
def test_network_interfaces_update_invalid_property(self, fake_interfaces):
fake_interfaces.return_value = fake_resources.NETWORK_INTERFACE1
payload = {'foo': 'invalid'}
resp = self.put('/v1/network_interfaces/1', data=payload)
resp = self.put('/v1/network-interfaces/1', data=payload)
self.assertEqual(200, resp.status_code)
self.assertNotIn('foo', resp.json)
@ -1251,5 +1251,5 @@ class APIV1NetworkInterfacesIDTest(APIV1Test):
@mock.patch.object(dbapi, 'network_interfaces_delete')
def test_network_interfaces_delete(self, fake_interfaces):
resp = self.delete('/v1/network_interfaces/1')
resp = self.delete('/v1/network-interfaces/1')
self.assertEqual(204, resp.status_code)

View File

@ -0,0 +1,23 @@
from craton import api
from craton.tests import TestCase
class TestRouteURLNaming(TestCase):
pass
def generate_route_naming_functions(cls):
def gen_test(endpoint, url):
def test(self):
self.assertRegex(url, '^/v1/[a-z-]+(/<id>(/[a-z-]+)?)?$')
test_name = 'test_route_naming_{}'.format(endpoint)
setattr(cls, test_name, test)
app = api.setup_app()
for rule in app.url_map.iter_rules():
endpoint = rule.endpoint[3:]
url = rule.rule
gen_test(endpoint, url)
generate_route_naming_functions(TestRouteURLNaming)

View File

@ -28,7 +28,7 @@ import requests
import sys
CRATON_INVENTORY_URL = "http://<host>:<port>/v1/ansible_inventory?region=%s"
CRATON_INVENTORY_URL = "http://<host>:<port>/v1/ansible-inventory?region=%s"
def parse_args():

View File

@ -141,7 +141,7 @@ class Inventory(object):
return resp.json()
def create_netdevice(self, name, device_type):
network_devices_url = self.url + "/network_devices"
network_devices_url = self.url + "/network-devices"
payload = {"hostname": name,
"model_name": "model-x",
"os_version": "version-1",
@ -159,7 +159,7 @@ class Inventory(object):
return resp.json()
def create_net_interface(self, device, int_num, network=None):
netinterfaces_url = self.url + "/network_interfaces"
netinterfaces_url = self.url + "/network-interfaces"
name = "eth%s" % int_num
payload = {"name": name,
"interface_type": "ethernet",