Promote v1.0 to current
* Mark v0.1 as deprecated * Add v1.0 to version list * Use subclasses for wsgi Routers * Add melange-manage route command to print routes * Fixes certain routes not being exposed in the v1.0 api (LP947327) Change-Id: Iac8294f2534decbbddf53230386fdbe8c622ff84
This commit is contained in:
parent
b69e9db4c1
commit
01cb899ef7
@ -39,6 +39,7 @@ from melange import version
|
||||
from melange.common import config
|
||||
from melange.common import utils
|
||||
from melange.db import db_api
|
||||
from melange.ipam import service
|
||||
|
||||
|
||||
def create_options(parser):
|
||||
@ -69,11 +70,23 @@ class Commands(object):
|
||||
def db_downgrade(self, version, repo_path=None):
|
||||
db_api.db_downgrade(self.conf, version, repo_path=repo_path)
|
||||
|
||||
def routes(self, version):
|
||||
version = version.split('=')[-1].upper().replace('.', '')
|
||||
if not version.startswith('V'):
|
||||
version = 'V' + version
|
||||
|
||||
api = getattr(service, 'API' + version, None)
|
||||
if not api:
|
||||
print _('Could not import Router %s') % api
|
||||
|
||||
for route in api().map.matchlist:
|
||||
print route.routepath, route.conditions['method']
|
||||
|
||||
def execute(self, command_name, *args):
|
||||
if self.has(command_name):
|
||||
return getattr(self, command_name)(*args)
|
||||
|
||||
_commands = ['db_sync', 'db_upgrade', 'db_downgrade']
|
||||
_commands = ['db_sync', 'db_upgrade', 'db_downgrade', 'routes']
|
||||
|
||||
@classmethod
|
||||
def has(cls, command_name):
|
||||
|
@ -568,106 +568,11 @@ class InterfaceAllowedIpsController(BaseController):
|
||||
interface.disallow_ip(ip)
|
||||
|
||||
|
||||
class APIV01(wsgi.Router):
|
||||
class APICommon(wsgi.Router):
|
||||
|
||||
def __init__(self):
|
||||
mapper = routes.Mapper()
|
||||
super(APIV01, self).__init__(mapper)
|
||||
self._networks_maper(mapper)
|
||||
self._interface_ip_allocations_mapper(mapper)
|
||||
self._interface_mapper(mapper)
|
||||
self._allowed_ips_mapper(mapper)
|
||||
APICommon(mapper)
|
||||
|
||||
def _networks_maper(self, mapper):
|
||||
resource = NetworksController().create_resource()
|
||||
path = "/ipam/tenants/{tenant_id}/networks/{network_id}"
|
||||
mapper.resource("networks", path, controller=resource)
|
||||
|
||||
def _interface_ip_allocations_mapper(self, mapper):
|
||||
path = ("/ipam/tenants/{tenant_id}/networks"
|
||||
"/{network_id}/interfaces/{interface_id}")
|
||||
resource = InterfaceIpAllocationsController().create_resource()
|
||||
with mapper.submapper(controller=resource, path_prefix=path) as submap:
|
||||
_connect(submap, "/ip_allocations", action='create',
|
||||
conditions=dict(method=['POST']))
|
||||
_connect(submap,
|
||||
"/ip_allocations",
|
||||
action='index',
|
||||
conditions=dict(method=['GET']))
|
||||
_connect(submap, "/ip_allocations", action='bulk_delete',
|
||||
conditions=dict(method=['DELETE']))
|
||||
|
||||
def _interface_mapper(self, mapper):
|
||||
interface_res = InterfacesController().create_resource()
|
||||
path = "/ipam/interfaces"
|
||||
_connect(mapper,
|
||||
"/ipam/tenants/{tenant_id}/"
|
||||
"interfaces/{virtual_interface_id}",
|
||||
controller=interface_res,
|
||||
action="show",
|
||||
conditions=dict(method=['GET']))
|
||||
_connect(mapper,
|
||||
"/ipam/interfaces/{virtual_interface_id}",
|
||||
controller=interface_res,
|
||||
action="delete",
|
||||
conditions=dict(method=['DELETE']))
|
||||
mapper.resource("interfaces", path, controller=interface_res)
|
||||
|
||||
def _allowed_ips_mapper(self, mapper):
|
||||
interface_allowed_ips = InterfaceAllowedIpsController()
|
||||
mapper.connect("/ipam/tenants/{tenant_id}/"
|
||||
"interfaces/{interface_id}/allowed_ips/{address:.+?}",
|
||||
action="delete",
|
||||
controller=interface_allowed_ips.create_resource(),
|
||||
conditions=dict(method=["DELETE"]))
|
||||
mapper.connect("/ipam/tenants/{tenant_id}/"
|
||||
"interfaces/{interface_id}/allowed_ips/{address:.+?}",
|
||||
action="show",
|
||||
controller=interface_allowed_ips.create_resource(),
|
||||
conditions=dict(method=["GET"]))
|
||||
mapper.resource("allowed_ips",
|
||||
"/allowed_ips",
|
||||
controller=interface_allowed_ips.create_resource(),
|
||||
path_prefix=("/ipam/tenants/{tenant_id}/"
|
||||
"interfaces/{interface_id}"))
|
||||
|
||||
@classmethod
|
||||
def app_factory(cls, global_conf, **local_conf):
|
||||
return APIV01()
|
||||
|
||||
|
||||
class APIV10(wsgi.Router):
|
||||
|
||||
def __init__(self):
|
||||
mapper = routes.Mapper()
|
||||
super(APIV10, self).__init__(mapper)
|
||||
APICommon(mapper)
|
||||
self._instance_interface_ips_mapper(mapper)
|
||||
|
||||
def _instance_interface_ips_mapper(self, mapper):
|
||||
res = InstanceInterfaceIpsController().create_resource()
|
||||
path_prefix = ("/ipam/instances/{device_id}/"
|
||||
"interfaces/{interface_id}")
|
||||
with mapper.submapper(controller=res,
|
||||
path_prefix=path_prefix) as submap:
|
||||
_connect(submap,
|
||||
"/ip_addresses/{address:.+?}",
|
||||
action="delete",
|
||||
conditions=dict(method=["DELETE"]))
|
||||
mapper.resource("ip_addresses",
|
||||
"/ip_addresses",
|
||||
controller=res,
|
||||
path_prefix=path_prefix)
|
||||
|
||||
@classmethod
|
||||
def app_factory(cls, global_conf, **local_conf):
|
||||
return APIV10()
|
||||
|
||||
|
||||
class APICommon():
|
||||
|
||||
def __init__(self, mapper):
|
||||
super(APICommon, self).__init__(mapper)
|
||||
self._natting_mapper(mapper,
|
||||
"inside_globals",
|
||||
InsideGlobalsController().create_resource())
|
||||
@ -816,5 +721,97 @@ class APICommon():
|
||||
conditions=dict(method=["DELETE"]))
|
||||
|
||||
|
||||
class APIV01(APICommon):
|
||||
def __init__(self):
|
||||
super(APIV01, self).__init__()
|
||||
self._networks_maper(self.map)
|
||||
self._interface_ip_allocations_mapper(self.map)
|
||||
self._interface_mapper(self.map)
|
||||
self._allowed_ips_mapper(self.map)
|
||||
|
||||
def _networks_maper(self, mapper):
|
||||
resource = NetworksController().create_resource()
|
||||
path = "/ipam/tenants/{tenant_id}/networks/{network_id}"
|
||||
mapper.resource("networks", path, controller=resource)
|
||||
|
||||
def _interface_ip_allocations_mapper(self, mapper):
|
||||
path = ("/ipam/tenants/{tenant_id}/networks"
|
||||
"/{network_id}/interfaces/{interface_id}")
|
||||
resource = InterfaceIpAllocationsController().create_resource()
|
||||
with mapper.submapper(controller=resource, path_prefix=path) as submap:
|
||||
_connect(submap, "/ip_allocations", action='create',
|
||||
conditions=dict(method=['POST']))
|
||||
_connect(submap,
|
||||
"/ip_allocations",
|
||||
action='index',
|
||||
conditions=dict(method=['GET']))
|
||||
_connect(submap, "/ip_allocations", action='bulk_delete',
|
||||
conditions=dict(method=['DELETE']))
|
||||
|
||||
def _interface_mapper(self, mapper):
|
||||
interface_res = InterfacesController().create_resource()
|
||||
path = "/ipam/interfaces"
|
||||
_connect(mapper,
|
||||
"/ipam/tenants/{tenant_id}/"
|
||||
"interfaces/{virtual_interface_id}",
|
||||
controller=interface_res,
|
||||
action="show",
|
||||
conditions=dict(method=['GET']))
|
||||
_connect(mapper,
|
||||
"/ipam/interfaces/{virtual_interface_id}",
|
||||
controller=interface_res,
|
||||
action="delete",
|
||||
conditions=dict(method=['DELETE']))
|
||||
mapper.resource("interfaces", path, controller=interface_res)
|
||||
|
||||
def _allowed_ips_mapper(self, mapper):
|
||||
interface_allowed_ips = InterfaceAllowedIpsController()
|
||||
mapper.connect("/ipam/tenants/{tenant_id}/"
|
||||
"interfaces/{interface_id}/allowed_ips/{address:.+?}",
|
||||
action="delete",
|
||||
controller=interface_allowed_ips.create_resource(),
|
||||
conditions=dict(method=["DELETE"]))
|
||||
mapper.connect("/ipam/tenants/{tenant_id}/"
|
||||
"interfaces/{interface_id}/allowed_ips/{address:.+?}",
|
||||
action="show",
|
||||
controller=interface_allowed_ips.create_resource(),
|
||||
conditions=dict(method=["GET"]))
|
||||
mapper.resource("allowed_ips",
|
||||
"/allowed_ips",
|
||||
controller=interface_allowed_ips.create_resource(),
|
||||
path_prefix=("/ipam/tenants/{tenant_id}/"
|
||||
"interfaces/{interface_id}"))
|
||||
|
||||
@classmethod
|
||||
def app_factory(cls, global_conf, **local_conf):
|
||||
return APIV01()
|
||||
|
||||
|
||||
class APIV10(APICommon):
|
||||
|
||||
def __init__(self):
|
||||
super(APIV10, self).__init__()
|
||||
self._instance_interface_ips_mapper(self.map)
|
||||
|
||||
def _instance_interface_ips_mapper(self, mapper):
|
||||
res = InstanceInterfaceIpsController().create_resource()
|
||||
path_prefix = ("/ipam/instances/{device_id}/"
|
||||
"interfaces/{interface_id}")
|
||||
with mapper.submapper(controller=res,
|
||||
path_prefix=path_prefix) as submap:
|
||||
_connect(submap,
|
||||
"/ip_addresses/{address:.+?}",
|
||||
action="delete",
|
||||
conditions=dict(method=["DELETE"]))
|
||||
mapper.resource("ip_addresses",
|
||||
"/ip_addresses",
|
||||
controller=res,
|
||||
path_prefix=path_prefix)
|
||||
|
||||
@classmethod
|
||||
def app_factory(cls, global_conf, **local_conf):
|
||||
return APIV10()
|
||||
|
||||
|
||||
def _connect(mapper, path, *args, **kwargs):
|
||||
return mapper.connect(path + "{.format:(json|xml)?}", *args, **kwargs)
|
||||
|
@ -31,12 +31,18 @@ class TestVersionsController(tests.BaseTest):
|
||||
|
||||
def test_versions_index(self):
|
||||
response = self.test_app.get("/")
|
||||
link = [{'href': "http://localhost/v0.1", 'rel': 'self'}]
|
||||
v01link = [{'href': "http://localhost/v0.1", 'rel': 'self'}]
|
||||
v10link = [{'href': "http://localhost/v1.0", 'rel': 'self'}]
|
||||
self.assertEqual(response.json, {'versions':
|
||||
[{
|
||||
'status':'CURRENT',
|
||||
'status':'DEPRECATED',
|
||||
'name': 'v0.1',
|
||||
'links': link,
|
||||
'links': v01link,
|
||||
},
|
||||
{
|
||||
'status':'CURRENT',
|
||||
'name': 'v1.0',
|
||||
'links': v10link,
|
||||
}]
|
||||
})
|
||||
|
||||
@ -48,10 +54,15 @@ class TestVersionsController(tests.BaseTest):
|
||||
self.assertEqual(response.xml.tag, 'versions')
|
||||
self.assertEqual(response.body,
|
||||
"""<versions>
|
||||
<version name="v0.1" status="CURRENT">
|
||||
<version name="v0.1" status="DEPRECATED">
|
||||
<links>
|
||||
<link href="http://localhost/v0.1" rel="self"/>
|
||||
</links>
|
||||
</version>
|
||||
<version name="v1.0" status="CURRENT">
|
||||
<links>
|
||||
<link href="http://localhost/v1.0" rel="self"/>
|
||||
</links>
|
||||
</version>
|
||||
</versions>
|
||||
""")
|
||||
|
@ -26,7 +26,8 @@ class VersionsController(wsgi.Controller):
|
||||
|
||||
def index(self, request):
|
||||
"""Respond to a request for all OpenStack API versions."""
|
||||
versions = [Version("v0.1", "CURRENT", request.application_url)]
|
||||
versions = [Version("v0.1", "DEPRECATED", request.application_url),
|
||||
Version("v1.0", "CURRENT", request.application_url)]
|
||||
return wsgi.Result(VersionsDataView(versions))
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user