api: Add response body schemas for networks API

Yet another proxy API documented, albeit very loosely. We also remove a
conditional that can never be reached: we will always have a network
from neutron by time we attempt to show it. If we didn't, we'd have
exited early due to an exception.

Change-Id: I008975b3eabf5f3552ebad7e5bbe847b9c7eaa16
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane
2024-11-14 15:57:47 +00:00
parent 8f9cbe0015
commit ce8faa8d74
3 changed files with 83 additions and 4 deletions
+4 -4
View File
@@ -37,9 +37,6 @@ _removal_reason_api = _removal_reason % 'API'
def network_dict(context, network):
if not network:
return {}
fields = ('id', 'cidr', 'netmask', 'gateway', 'broadcast', 'dns1', 'dns2',
'cidr_v6', 'gateway_v6', 'label', 'netmask_v6')
admin_fields = ('created_at', 'updated_at', 'deleted_at', 'deleted',
@@ -70,16 +67,18 @@ def network_dict(context, network):
return result
@validation.validated
class NetworkController(wsgi.Controller):
def __init__(self, network_api=None):
super(NetworkController, self).__init__()
# TODO(stephenfin): 'network_api' is only being passed for use by tests
# NOTE(stephenfin): 'network_api' is only being passed for use by tests
self.network_api = network_api or neutron.API()
@wsgi.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(())
@validation.query_schema(schema.index_query)
@validation.response_body_schema(schema.index_response)
def index(self, req):
context = req.environ['nova.context']
context.can(net_policies.POLICY_ROOT % 'list',
@@ -91,6 +90,7 @@ class NetworkController(wsgi.Controller):
@wsgi.api_version("2.1", MAX_PROXY_API_SUPPORT_VERSION)
@wsgi.expected_errors(404)
@validation.query_schema(schema.show_query)
@validation.response_body_schema(schema.show_response)
def show(self, req, id):
context = req.environ['nova.context']
context.can(net_policies.POLICY_ROOT % 'show',
@@ -20,6 +20,83 @@ disassociate = {}
index_query = {}
show_query = {}
# NOTE(stephenfin): This is a *very* loose schema since this is a deprecated
# API and only the id and label fields are populated with non-null values these
# days.
_network_response = {
'type': 'object',
'properties': {
'bridge': {'type': ['string', 'null']},
'bridge_interface': {'type': ['string', 'null']},
'broadcast': {'type': ['string', 'null']},
'cidr': {'type': ['string', 'null']},
'cidr_v6': {'type': ['string', 'null']},
'created_at': {'type': ['string', 'null']},
'deleted': {'type': ['string', 'null']},
'deleted_at': {'type': ['string', 'null']},
'dhcp_server': {'type': ['string', 'null']},
'dhcp_start': {'type': ['string', 'null']},
'dns1': {'type': ['string', 'null']},
'dns2': {'type': ['string', 'null']},
'enable_dhcp': {'type': ['string', 'null']},
'gateway': {'type': ['string', 'null']},
'gateway_v6': {'type': ['string', 'null']},
'host': {'type': ['string', 'null']},
'id': {'type': 'string', 'format': 'string'},
'injected': {'type': ['string', 'null']},
'label': {'type': 'string'},
'multi_host': {'type': ['string', 'null']},
'mtu': {'type': ['integer', 'null']},
'netmask': {'type': ['string', 'null']},
'netmask_v6': {'type': ['string', 'null']},
'priority': {'type': ['string', 'null']},
'project_id': {'type': ['string', 'null']},
'rxtx_base': {'type': ['string', 'null']},
'share_address': {'type': ['string', 'null']},
'updated_at': {'type': ['string', 'null']},
'vlan': {'type': ['string', 'null']},
'vpn_private_address': {'type': ['string', 'null']},
'vpn_public_address': {'type': ['string', 'null']},
'vpn_public_port': {'type': ['integer', 'null']},
},
'required': [
# admin fields are optional, but the rest will always be shown
'broadcast',
'cidr',
'cidr_v6',
'dns1',
'dns2',
'gateway',
'gateway_v6',
'id',
'label',
'netmask',
'netmask_v6',
],
'additionalProperties': False,
}
index_response = {
'type': 'object',
'properties': {
'networks': {
'type': 'array',
'items': _network_response,
},
},
'required': ['networks'],
'additionalProperties': False,
}
show_response = {
'type': 'object',
'properties': {
'network': _network_response,
},
'required': ['network'],
'additionalProperties': False,
}
disassociate_response = {}
delete_response = {}
create_response = {}
@@ -51,6 +51,7 @@ class NetworksPolicyTest(base.BasePolicyTest):
@mock.patch('nova.network.neutron.API.get_all')
def test_list_networks_policy(self, mock_get):
mock_get.return_value = []
rule_name = "os_compute_api:os-networks:list"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.index,
@@ -58,6 +59,7 @@ class NetworksPolicyTest(base.BasePolicyTest):
@mock.patch('nova.network.neutron.API.get')
def test_show_network_policy(self, mock_get):
mock_get.return_value = {'id': uuids.network_id, 'name': 'foo'}
rule_name = "os_compute_api:os-networks:show"
self.common_policy_auth(self.project_reader_authorized_contexts,
rule_name, self.controller.show,