Add API versioning
- All OpenStack projects have API versioning - Existing endpoints are now prefixed with /v1 - Still fully backward compatible with old endpoints - No HTTP redirects is used to avoid unexpected behaviors with existing clients Change-Id: If51f3291c44615991b3378b711dffacc1bd2591f
This commit is contained in:
parent
3392b59188
commit
ef8897f58b
@ -24,7 +24,7 @@ from werkzeug import wrappers
|
||||
from almanach.core import exception
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
api = flask.Blueprint("api", __name__)
|
||||
api = flask.Blueprint('v1', __name__)
|
||||
instance_ctl = None
|
||||
volume_ctl = None
|
||||
volume_type_ctl = None
|
||||
@ -85,12 +85,14 @@ def authenticated(api_call):
|
||||
return decorator
|
||||
|
||||
|
||||
@api.route("/v1/info", methods=["GET"])
|
||||
@api.route("/info", methods=["GET"])
|
||||
@to_json
|
||||
def get_info():
|
||||
return app_ctl.get_application_info()
|
||||
|
||||
|
||||
@api.route("/v1/project/<project_id>/instance", methods=["POST"])
|
||||
@api.route("/project/<project_id>/instance", methods=["POST"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -112,6 +114,7 @@ def create_instance(project_id):
|
||||
return flask.Response(status=201)
|
||||
|
||||
|
||||
@api.route("/v1/instance/<instance_id>", methods=["DELETE"])
|
||||
@api.route("/instance/<instance_id>", methods=["DELETE"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -126,6 +129,7 @@ def delete_instance(instance_id):
|
||||
return flask.Response(status=202)
|
||||
|
||||
|
||||
@api.route("/v1/instance/<instance_id>/resize", methods=["PUT"])
|
||||
@api.route("/instance/<instance_id>/resize", methods=["PUT"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -141,6 +145,7 @@ def resize_instance(instance_id):
|
||||
return flask.Response(status=200)
|
||||
|
||||
|
||||
@api.route("/v1/instance/<instance_id>/rebuild", methods=["PUT"])
|
||||
@api.route("/instance/<instance_id>/rebuild", methods=["PUT"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -158,6 +163,7 @@ def rebuild_instance(instance_id):
|
||||
return flask.Response(status=200)
|
||||
|
||||
|
||||
@api.route("/v1/project/<project_id>/instances", methods=["GET"])
|
||||
@api.route("/project/<project_id>/instances", methods=["GET"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -167,6 +173,7 @@ def list_instances(project_id):
|
||||
return instance_ctl.list_instances(project_id, start, end)
|
||||
|
||||
|
||||
@api.route("/v1/project/<project_id>/volume", methods=["POST"])
|
||||
@api.route("/project/<project_id>/volume", methods=["POST"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -186,6 +193,7 @@ def create_volume(project_id):
|
||||
return flask.Response(status=201)
|
||||
|
||||
|
||||
@api.route("/v1/volume/<volume_id>", methods=["DELETE"])
|
||||
@api.route("/volume/<volume_id>", methods=["DELETE"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -200,6 +208,7 @@ def delete_volume(volume_id):
|
||||
return flask.Response(status=202)
|
||||
|
||||
|
||||
@api.route("/v1/volume/<volume_id>/resize", methods=["PUT"])
|
||||
@api.route("/volume/<volume_id>/resize", methods=["PUT"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -215,6 +224,7 @@ def resize_volume(volume_id):
|
||||
return flask.Response(status=200)
|
||||
|
||||
|
||||
@api.route("/v1/volume/<volume_id>/attach", methods=["PUT"])
|
||||
@api.route("/volume/<volume_id>/attach", methods=["PUT"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -230,6 +240,7 @@ def attach_volume(volume_id):
|
||||
return flask.Response(status=200)
|
||||
|
||||
|
||||
@api.route("/v1/volume/<volume_id>/detach", methods=["PUT"])
|
||||
@api.route("/volume/<volume_id>/detach", methods=["PUT"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -245,6 +256,7 @@ def detach_volume(volume_id):
|
||||
return flask.Response(status=200)
|
||||
|
||||
|
||||
@api.route("/v1/project/<project_id>/volumes", methods=["GET"])
|
||||
@api.route("/project/<project_id>/volumes", methods=["GET"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -254,6 +266,7 @@ def list_volumes(project_id):
|
||||
return volume_ctl.list_volumes(project_id, start, end)
|
||||
|
||||
|
||||
@api.route("/v1/project/<project_id>/entities", methods=["GET"])
|
||||
@api.route("/project/<project_id>/entities", methods=["GET"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -263,6 +276,7 @@ def list_entity(project_id):
|
||||
return entity_ctl.list_entities(project_id, start, end)
|
||||
|
||||
|
||||
@api.route("/v1/entity/instance/<instance_id>", methods=["PUT"])
|
||||
@api.route("/entity/instance/<instance_id>", methods=["PUT"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -277,6 +291,7 @@ def update_instance_entity(instance_id):
|
||||
return result
|
||||
|
||||
|
||||
@api.route("/v1/entity/<entity_id>", methods=["HEAD"])
|
||||
@api.route("/entity/<entity_id>", methods=["HEAD"])
|
||||
@authenticated
|
||||
def entity_exists(entity_id):
|
||||
@ -287,6 +302,7 @@ def entity_exists(entity_id):
|
||||
return response
|
||||
|
||||
|
||||
@api.route("/v1/entity/<entity_id>", methods=["GET"])
|
||||
@api.route("/entity/<entity_id>", methods=["GET"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -294,6 +310,7 @@ def get_entity(entity_id):
|
||||
return entity_ctl.get_all_entities_by_id(entity_id)
|
||||
|
||||
|
||||
@api.route("/v1/volume_types", methods=["GET"])
|
||||
@api.route("/volume_types", methods=["GET"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -302,6 +319,7 @@ def list_volume_types():
|
||||
return volume_type_ctl.list_volume_types()
|
||||
|
||||
|
||||
@api.route("/v1/volume_type/<volume_type_id>", methods=["GET"])
|
||||
@api.route("/volume_type/<volume_type_id>", methods=["GET"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -310,6 +328,7 @@ def get_volume_type(volume_type_id):
|
||||
return volume_type_ctl.get_volume_type(volume_type_id)
|
||||
|
||||
|
||||
@api.route("/v1/volume_type", methods=["POST"])
|
||||
@api.route("/volume_type", methods=["POST"])
|
||||
@authenticated
|
||||
@to_json
|
||||
@ -323,6 +342,7 @@ def create_volume_type():
|
||||
return flask.Response(status=201)
|
||||
|
||||
|
||||
@api.route("/v1/volume_type/<volume_type_id>", methods=["DELETE"])
|
||||
@api.route("/volume_type/<volume_type_id>", methods=["DELETE"])
|
||||
@authenticated
|
||||
@to_json
|
||||
|
@ -19,6 +19,7 @@ CONF = config.CONF
|
||||
|
||||
|
||||
class AlmanachClient(rest_client.RestClient):
|
||||
api_version = 'v1'
|
||||
|
||||
def __init__(self, auth_provider):
|
||||
super(AlmanachClient, self).__init__(
|
||||
@ -32,11 +33,11 @@ class AlmanachClient(rest_client.RestClient):
|
||||
return resp, response_body
|
||||
|
||||
def create_server(self, tenant_id, body):
|
||||
resp, response_body = self.post('/project/{}/instance'.format(tenant_id), body=body)
|
||||
resp, response_body = self.post('project/{}/instance'.format(tenant_id), body=body)
|
||||
return resp, response_body
|
||||
|
||||
def delete_server(self, instance_id, body):
|
||||
resp, response_body = self.delete('/instance/{}'.format(instance_id), body=body)
|
||||
resp, response_body = self.delete('instance/{}'.format(instance_id), body=body)
|
||||
return resp, response_body
|
||||
|
||||
def get_volume_type(self, volume_type_id):
|
||||
@ -44,28 +45,28 @@ class AlmanachClient(rest_client.RestClient):
|
||||
return resp, response_body
|
||||
|
||||
def create_volume_type(self, body):
|
||||
resp, response_body = self.post('/volume_type', body)
|
||||
resp, response_body = self.post('volume_type', body)
|
||||
return resp, response_body
|
||||
|
||||
def create_volume(self, tenant_id, body):
|
||||
url = '/project/{}/volume'.format(tenant_id)
|
||||
url = 'project/{}/volume'.format(tenant_id)
|
||||
resp, response_body = self.post(url, body)
|
||||
return resp, response_body
|
||||
|
||||
def delete_volume(self, volume_id, body):
|
||||
resp, response_body = self.delete('/volume/{}'.format(volume_id), body=body)
|
||||
resp, response_body = self.delete('volume/{}'.format(volume_id), body=body)
|
||||
return resp, response_body
|
||||
|
||||
def resize_volume(self, volume_id, body):
|
||||
resp, response_body = self.put('/volume/{}/resize'.format(volume_id), body)
|
||||
resp, response_body = self.put('volume/{}/resize'.format(volume_id), body)
|
||||
return resp, response_body
|
||||
|
||||
def attach_volume(self, volume_id, body):
|
||||
resp, response_body = self.put('/volume/{}/attach'.format(volume_id), body)
|
||||
resp, response_body = self.put('volume/{}/attach'.format(volume_id), body)
|
||||
return resp, response_body
|
||||
|
||||
def detach_volume(self, volume_id, body):
|
||||
resp, response_body = self.put('/volume/{}/detach'.format(volume_id), body)
|
||||
resp, response_body = self.put('volume/{}/detach'.format(volume_id), body)
|
||||
return resp, response_body
|
||||
|
||||
def get_tenant_entities(self, tenant_id):
|
||||
@ -74,16 +75,16 @@ class AlmanachClient(rest_client.RestClient):
|
||||
return resp, response_body
|
||||
|
||||
def update_server(self, instance_id, body):
|
||||
url = '/entity/instance/{}'.format(instance_id)
|
||||
url = 'entity/instance/{}'.format(instance_id)
|
||||
resp, response_body = self.put(url, body)
|
||||
return resp, response_body
|
||||
|
||||
def rebuild(self, instance_id, body):
|
||||
update_instance_rebuild_query = "/instance/{}/rebuild".format(instance_id)
|
||||
update_instance_rebuild_query = "instance/{}/rebuild".format(instance_id)
|
||||
resp, response_body = self.put(update_instance_rebuild_query, body)
|
||||
return resp, response_body
|
||||
|
||||
def resize(self, instance_id, body):
|
||||
url = "/instance/{}/resize".format(instance_id)
|
||||
url = "instance/{}/resize".format(instance_id)
|
||||
resp, response_body = self.put(url, body)
|
||||
return resp, response_body
|
||||
|
@ -26,7 +26,7 @@ class TestApiAuthentication(base_api.BaseApi):
|
||||
self.auth_adapter.validate.side_effect = exception.AuthenticationFailureException('Unauthorized')
|
||||
query_string = {'start': '2014-01-01 00:00:00.0000', 'end': '2014-02-01 00:00:00.0000'}
|
||||
|
||||
code, result = self.api_get(url='/project/TENANT_ID/entities',
|
||||
code, result = self.api_get(url='/v1/project/TENANT_ID/entities',
|
||||
query_string=query_string,
|
||||
headers={'X-Auth-Token': 'wrong token'})
|
||||
|
||||
|
@ -35,7 +35,7 @@ class TestApiEntity(base_api.BaseApi):
|
||||
end = '2016-03-03 00:00:00.000000'
|
||||
|
||||
code, result = self.api_put(
|
||||
'/entity/instance/INSTANCE_ID',
|
||||
'/v1/entity/instance/INSTANCE_ID',
|
||||
headers={'X-Auth-Token': 'some token value'},
|
||||
query_string={
|
||||
'start': start,
|
||||
@ -63,7 +63,7 @@ class TestApiEntity(base_api.BaseApi):
|
||||
self.entity_ctl.update_active_instance_entity.return_value = an_instance
|
||||
|
||||
code, result = self.api_put(
|
||||
'/entity/instance/INSTANCE_ID',
|
||||
'/v1/entity/instance/INSTANCE_ID',
|
||||
headers={'X-Auth-Token': 'some token value'},
|
||||
data=data,
|
||||
)
|
||||
@ -87,11 +87,9 @@ class TestApiEntity(base_api.BaseApi):
|
||||
'flavor': 'A_FLAVOR',
|
||||
}
|
||||
|
||||
code, result = self.api_put(
|
||||
'/entity/instance/INSTANCE_ID',
|
||||
code, result = self.api_put('/v1/entity/instance/INSTANCE_ID',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.entity_ctl.update_active_instance_entity.assert_called_once_with(instance_id=instance_id, **data)
|
||||
self.assertIn("error", result)
|
||||
@ -115,11 +113,9 @@ class TestApiEntity(base_api.BaseApi):
|
||||
'flavor': 'A_FLAVOR',
|
||||
}
|
||||
|
||||
code, result = self.api_put(
|
||||
'/entity/instance/INSTANCE_ID',
|
||||
code, result = self.api_put('/v1/entity/instance/INSTANCE_ID',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.entity_ctl.update_active_instance_entity.assert_called_once_with(instance_id=instance_id, **data)
|
||||
self.assertIn("error", result)
|
||||
@ -130,7 +126,8 @@ class TestApiEntity(base_api.BaseApi):
|
||||
self.entity_ctl.entity_exists.return_value = True
|
||||
entity_id = "entity_id"
|
||||
|
||||
code, result = self.api_head('/entity/{id}'.format(id=entity_id), headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_head('/v1/entity/{id}'.format(id=entity_id),
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.entity_ctl.entity_exists.assert_called_once_with(entity_id=entity_id)
|
||||
self.assertEqual(code, 200)
|
||||
@ -139,7 +136,8 @@ class TestApiEntity(base_api.BaseApi):
|
||||
self.entity_ctl.entity_exists.return_value = False
|
||||
entity_id = "entity_id"
|
||||
|
||||
code, result = self.api_head('/entity/{id}'.format(id=entity_id), headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_head('/v1/entity/{id}'.format(id=entity_id),
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.entity_ctl.entity_exists.assert_called_once_with(entity_id=entity_id)
|
||||
self.assertEqual(code, 404)
|
||||
|
@ -18,10 +18,16 @@ from almanach.tests.unit.api.v1 import base_api
|
||||
class TestApiInfo(base_api.BaseApi):
|
||||
|
||||
def test_info(self):
|
||||
self.assert_info_call('/v1/info')
|
||||
|
||||
def test_info_with_legacy_url(self):
|
||||
self.assert_info_call('/info')
|
||||
|
||||
def assert_info_call(self, url):
|
||||
info = {'info': {'version': '1.0'}, 'database': {'all_entities': 10, 'active_entities': 2}}
|
||||
self.app_ctl.get_application_info.return_value = info
|
||||
|
||||
code, result = self.api_get('/info')
|
||||
code, result = self.api_get(url)
|
||||
|
||||
self.app_ctl.get_application_info.assert_called_once()
|
||||
self.assertEqual(code, 200)
|
||||
|
@ -22,7 +22,7 @@ class TestApiInstance(base_api.BaseApi):
|
||||
|
||||
def test_get_instances(self):
|
||||
self.instance_ctl.list_instances.return_value = [a(instance().with_id('123'))]
|
||||
code, result = self.api_get('/project/TENANT_ID/instances',
|
||||
code, result = self.api_get('/v1/project/TENANT_ID/instances',
|
||||
query_string={
|
||||
'start': '2014-01-01 00:00:00.0000',
|
||||
'end': '2014-02-01 00:00:00.0000'
|
||||
@ -47,11 +47,9 @@ class TestApiInstance(base_api.BaseApi):
|
||||
os_distro="A_DISTRIBUTION",
|
||||
os_version="AN_OS_VERSION")
|
||||
|
||||
code, result = self.api_post(
|
||||
'/project/PROJECT_ID/instance',
|
||||
code, result = self.api_post('/v1/project/PROJECT_ID/instance',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.instance_ctl.create_instance.assert_called_once_with(
|
||||
tenant_id="PROJECT_ID",
|
||||
@ -73,11 +71,9 @@ class TestApiInstance(base_api.BaseApi):
|
||||
os_type="AN_OS_TYPE",
|
||||
os_version="AN_OS_VERSION")
|
||||
|
||||
code, result = self.api_post(
|
||||
'/project/PROJECT_ID/instance',
|
||||
code, result = self.api_post('/v1/project/PROJECT_ID/instance',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.instance_ctl.create_instance.assert_not_called()
|
||||
self.assertEqual(result["error"], "The 'os_distro' param is mandatory for the request you have made.")
|
||||
@ -93,11 +89,9 @@ class TestApiInstance(base_api.BaseApi):
|
||||
os_distro="A_DISTRIBUTION",
|
||||
os_version="AN_OS_VERSION")
|
||||
|
||||
code, result = self.api_post(
|
||||
'/project/PROJECT_ID/instance',
|
||||
code, result = self.api_post('/v1/project/PROJECT_ID/instance',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.instance_ctl.create_instance.assert_called_once_with(
|
||||
tenant_id="PROJECT_ID",
|
||||
@ -122,7 +116,7 @@ class TestApiInstance(base_api.BaseApi):
|
||||
flavor="A_FLAVOR")
|
||||
|
||||
code, result = self.api_put(
|
||||
'/instance/INSTANCE_ID/resize',
|
||||
'/v1/instance/INSTANCE_ID/resize',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
@ -137,7 +131,9 @@ class TestApiInstance(base_api.BaseApi):
|
||||
def test_successfull_instance_delete(self):
|
||||
data = dict(date="DELETE_DATE")
|
||||
|
||||
code, result = self.api_delete('/instance/INSTANCE_ID', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_delete('/v1/instance/INSTANCE_ID',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.instance_ctl.delete_instance.assert_called_once_with(
|
||||
instance_id="INSTANCE_ID",
|
||||
@ -147,7 +143,7 @@ class TestApiInstance(base_api.BaseApi):
|
||||
|
||||
def test_instance_delete_missing_a_param_returns_bad_request_code(self):
|
||||
code, result = self.api_delete(
|
||||
'/instance/INSTANCE_ID',
|
||||
'/v1/instance/INSTANCE_ID',
|
||||
data=dict(),
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
@ -160,7 +156,7 @@ class TestApiInstance(base_api.BaseApi):
|
||||
self.assertEqual(code, 400)
|
||||
|
||||
def test_instance_delete_no_data_bad_request_code(self):
|
||||
code, result = self.api_delete('/instance/INSTANCE_ID', headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_delete('/v1/instance/INSTANCE_ID', headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.instance_ctl.delete_instance.assert_not_called()
|
||||
self.assertIn(
|
||||
@ -173,7 +169,9 @@ class TestApiInstance(base_api.BaseApi):
|
||||
data = dict(date="A_BAD_DATE")
|
||||
self.instance_ctl.delete_instance.side_effect = exception.DateFormatException
|
||||
|
||||
code, result = self.api_delete('/instance/INSTANCE_ID', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_delete('/v1/instance/INSTANCE_ID',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.instance_ctl.delete_instance.assert_called_once_with(
|
||||
instance_id="INSTANCE_ID",
|
||||
@ -189,7 +187,7 @@ class TestApiInstance(base_api.BaseApi):
|
||||
def test_instance_resize_missing_a_param_returns_bad_request_code(self):
|
||||
data = dict(date="UPDATED_AT")
|
||||
code, result = self.api_put(
|
||||
'/instance/INSTANCE_ID/resize',
|
||||
'/v1/instance/INSTANCE_ID/resize',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
@ -206,7 +204,7 @@ class TestApiInstance(base_api.BaseApi):
|
||||
data = dict(date="A_BAD_DATE",
|
||||
flavor="A_FLAVOR")
|
||||
code, result = self.api_put(
|
||||
'/instance/INSTANCE_ID/resize',
|
||||
'/v1/instance/INSTANCE_ID/resize',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
@ -231,11 +229,9 @@ class TestApiInstance(base_api.BaseApi):
|
||||
'os_type': 'AN_OS_TYPE',
|
||||
'rebuild_date': 'UPDATE_DATE',
|
||||
}
|
||||
code, result = self.api_put(
|
||||
'/instance/INSTANCE_ID/rebuild',
|
||||
code, result = self.api_put('/v1/instance/INSTANCE_ID/rebuild',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.instance_ctl.rebuild_instance.assert_called_once_with(
|
||||
instance_id=instance_id,
|
||||
@ -251,11 +247,9 @@ class TestApiInstance(base_api.BaseApi):
|
||||
'distro': 'A_DISTRIBUTION',
|
||||
'rebuild_date': 'UPDATE_DATE',
|
||||
}
|
||||
code, result = self.api_put(
|
||||
'/instance/INSTANCE_ID/rebuild',
|
||||
code, result = self.api_put('/v1/instance/INSTANCE_ID/rebuild',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.instance_ctl.rebuild_instance.assert_not_called()
|
||||
self.assertIn(
|
||||
@ -273,11 +267,9 @@ class TestApiInstance(base_api.BaseApi):
|
||||
'os_type': 'AN_OS_TYPE',
|
||||
'rebuild_date': 'A_BAD_UPDATE_DATE',
|
||||
}
|
||||
code, result = self.api_put(
|
||||
'/instance/INSTANCE_ID/rebuild',
|
||||
code, result = self.api_put('/v1/instance/INSTANCE_ID/rebuild',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.instance_ctl.rebuild_instance.assert_called_once_with(
|
||||
instance_id=instance_id,
|
||||
|
@ -29,7 +29,7 @@ class TestApiVolume(base_api.BaseApi):
|
||||
attached_to=["INSTANCE_ID"])
|
||||
|
||||
code, result = self.api_post(
|
||||
'/project/PROJECT_ID/volume',
|
||||
'/v1/project/PROJECT_ID/volume',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
@ -48,7 +48,7 @@ class TestApiVolume(base_api.BaseApi):
|
||||
attached_to=[])
|
||||
|
||||
code, result = self.api_post(
|
||||
'/project/PROJECT_ID/volume',
|
||||
'/v1/project/PROJECT_ID/volume',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
@ -70,7 +70,7 @@ class TestApiVolume(base_api.BaseApi):
|
||||
attached_to=["INSTANCE_ID"])
|
||||
|
||||
code, result = self.api_post(
|
||||
'/project/PROJECT_ID/volume',
|
||||
'/v1/project/PROJECT_ID/volume',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
@ -89,7 +89,9 @@ class TestApiVolume(base_api.BaseApi):
|
||||
def test_successful_volume_delete(self):
|
||||
data = dict(date="DELETE_DATE")
|
||||
|
||||
code, result = self.api_delete('/volume/VOLUME_ID', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_delete('/v1/volume/VOLUME_ID',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.volume_ctl.delete_volume.assert_called_once_with(
|
||||
volume_id="VOLUME_ID",
|
||||
@ -98,7 +100,9 @@ class TestApiVolume(base_api.BaseApi):
|
||||
self.assertEqual(code, 202)
|
||||
|
||||
def test_volume_delete_missing_a_param_returns_bad_request_code(self):
|
||||
code, result = self.api_delete('/volume/VOLUME_ID', data=dict(), headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_delete('/v1/volume/VOLUME_ID',
|
||||
data=dict(),
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.assertIn(
|
||||
"The 'date' param is mandatory for the request you have made.",
|
||||
@ -108,7 +112,8 @@ class TestApiVolume(base_api.BaseApi):
|
||||
self.assertEqual(code, 400)
|
||||
|
||||
def test_volume_delete_no_data_bad_request_code(self):
|
||||
code, result = self.api_delete('/volume/VOLUME_ID', headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_delete('/v1/volume/VOLUME_ID',
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.assertIn(
|
||||
"Invalid parameter or payload",
|
||||
@ -121,7 +126,9 @@ class TestApiVolume(base_api.BaseApi):
|
||||
self.volume_ctl.delete_volume.side_effect = exception.DateFormatException
|
||||
data = dict(date="A_BAD_DATE")
|
||||
|
||||
code, result = self.api_delete('/volume/VOLUME_ID', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_delete('/v1/volume/VOLUME_ID',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.assertIn(
|
||||
"The provided date has an invalid format. "
|
||||
@ -138,7 +145,9 @@ class TestApiVolume(base_api.BaseApi):
|
||||
data = dict(date="UPDATED_AT",
|
||||
size="NEW_SIZE")
|
||||
|
||||
code, result = self.api_put('/volume/VOLUME_ID/resize', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_put('/v1/volume/VOLUME_ID/resize',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.volume_ctl.resize_volume.assert_called_once_with(
|
||||
volume_id="VOLUME_ID",
|
||||
@ -150,7 +159,9 @@ class TestApiVolume(base_api.BaseApi):
|
||||
def test_volume_resize_missing_a_param_returns_bad_request_code(self):
|
||||
data = dict(date="A_DATE")
|
||||
|
||||
code, result = self.api_put('/volume/VOLUME_ID/resize', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_put('/v1/volume/VOLUME_ID/resize',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.assertIn(
|
||||
"The 'size' param is mandatory for the request you have made.",
|
||||
@ -164,7 +175,9 @@ class TestApiVolume(base_api.BaseApi):
|
||||
data = dict(date="BAD_DATE",
|
||||
size="NEW_SIZE")
|
||||
|
||||
code, result = self.api_put('/volume/VOLUME_ID/resize', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_put('/v1/volume/VOLUME_ID/resize',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.assertIn(
|
||||
"The provided date has an invalid format. "
|
||||
@ -182,7 +195,9 @@ class TestApiVolume(base_api.BaseApi):
|
||||
data = dict(date="UPDATED_AT",
|
||||
attachments=[uuidutils.generate_uuid()])
|
||||
|
||||
code, result = self.api_put('/volume/VOLUME_ID/attach', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_put('/v1/volume/VOLUME_ID/attach',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.volume_ctl.attach_volume.assert_called_once_with(
|
||||
volume_id="VOLUME_ID",
|
||||
@ -195,7 +210,7 @@ class TestApiVolume(base_api.BaseApi):
|
||||
data = dict(date="A_DATE")
|
||||
|
||||
code, result = self.api_put(
|
||||
'/volume/VOLUME_ID/attach',
|
||||
'/v1/volume/VOLUME_ID/attach',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'}
|
||||
)
|
||||
@ -212,7 +227,9 @@ class TestApiVolume(base_api.BaseApi):
|
||||
data = dict(date="A_BAD_DATE",
|
||||
attachments=[uuidutils.generate_uuid()])
|
||||
|
||||
code, result = self.api_put('/volume/VOLUME_ID/attach', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_put('/v1/volume/VOLUME_ID/attach',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.assertIn(
|
||||
"The provided date has an invalid format. "
|
||||
@ -230,7 +247,9 @@ class TestApiVolume(base_api.BaseApi):
|
||||
data = dict(date="UPDATED_AT",
|
||||
attachments=[uuidutils.generate_uuid()])
|
||||
|
||||
code, result = self.api_put('/volume/VOLUME_ID/detach', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_put('/v1/volume/VOLUME_ID/detach',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.volume_ctl.detach_volume.assert_called_once_with(
|
||||
volume_id="VOLUME_ID",
|
||||
@ -242,7 +261,9 @@ class TestApiVolume(base_api.BaseApi):
|
||||
def test_volume_detach_missing_a_param_returns_bad_request_code(self):
|
||||
data = dict(date="A_DATE")
|
||||
|
||||
code, result = self.api_put('/volume/VOLUME_ID/detach', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_put('/v1/volume/VOLUME_ID/detach',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.assertIn(
|
||||
"The 'attachments' param is mandatory for the request you have made.",
|
||||
@ -256,7 +277,9 @@ class TestApiVolume(base_api.BaseApi):
|
||||
data = dict(date="A_BAD_DATE",
|
||||
attachments=[uuidutils.generate_uuid()])
|
||||
|
||||
code, result = self.api_put('/volume/VOLUME_ID/detach', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_put('/v1/volume/VOLUME_ID/detach',
|
||||
data=data,
|
||||
headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.assertIn(
|
||||
"The provided date has an invalid format. "
|
||||
|
@ -25,7 +25,7 @@ class TestApiVolumeType(base_api.BaseApi):
|
||||
a(volume_type().with_volume_type_name('some_volume_type_name'))
|
||||
]
|
||||
|
||||
code, result = self.api_get('/volume_types', headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_get('/v1/volume_types', headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.volume_type_ctl.list_volume_types.assert_called_once()
|
||||
self.assertEqual(code, 200)
|
||||
@ -39,7 +39,7 @@ class TestApiVolumeType(base_api.BaseApi):
|
||||
type_name="A_VOLUME_TYPE_NAME"
|
||||
)
|
||||
|
||||
code, result = self.api_post('/volume_type', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_post('/v1/volume_type', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.volume_type_ctl.create_volume_type.assert_called_once_with(
|
||||
volume_type_id=data['type_id'],
|
||||
@ -50,14 +50,14 @@ class TestApiVolumeType(base_api.BaseApi):
|
||||
def test_volume_type_create_missing_a_param_returns_bad_request_code(self):
|
||||
data = dict(type_name="A_VOLUME_TYPE_NAME")
|
||||
|
||||
code, result = self.api_post('/volume_type', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_post('/v1/volume_type', data=data, headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.volume_type_ctl.create_volume_type.assert_not_called()
|
||||
self.assertEqual(result["error"], "The 'type_id' param is mandatory for the request you have made.")
|
||||
self.assertEqual(code, 400)
|
||||
|
||||
def test_volume_type_delete_with_authentication(self):
|
||||
code, result = self.api_delete('/volume_type/A_VOLUME_TYPE_ID', headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_delete('/v1/volume_type/A_VOLUME_TYPE_ID', headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.volume_type_ctl.delete_volume_type.assert_called_once_with('A_VOLUME_TYPE_ID')
|
||||
self.assertEqual(code, 202)
|
||||
@ -65,7 +65,7 @@ class TestApiVolumeType(base_api.BaseApi):
|
||||
def test_volume_type_delete_not_in_database(self):
|
||||
self.volume_type_ctl.delete_volume_type.side_effect = exception.AlmanachException("An exception occurred")
|
||||
|
||||
code, result = self.api_delete('/volume_type/A_VOLUME_TYPE_ID', headers={'X-Auth-Token': 'some token value'})
|
||||
code, result = self.api_delete('/v1/volume_type/A_VOLUME_TYPE_ID', headers={'X-Auth-Token': 'some token value'})
|
||||
|
||||
self.volume_type_ctl.delete_volume_type.assert_called_once_with('A_VOLUME_TYPE_ID')
|
||||
self.assertIn("An exception occurred", result["error"])
|
||||
|
@ -244,10 +244,10 @@ Almanach will process those events:
|
||||
- :code:`volume.exists`
|
||||
- :code:`volume_type.create`
|
||||
|
||||
API documentation
|
||||
-----------------
|
||||
API v1 Documentation
|
||||
--------------------
|
||||
|
||||
:code:`GET /volume_types`
|
||||
:code:`GET /v1/volume_types`
|
||||
|
||||
List volume types.
|
||||
|
||||
@ -260,7 +260,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/output/volume_types.json
|
||||
:language: json
|
||||
|
||||
:code:`GET /volume_type/<volume_type_id>`
|
||||
:code:`GET /v1/volume_type/<volume_type_id>`
|
||||
|
||||
Get a volume type.
|
||||
|
||||
@ -291,7 +291,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/output/volume_type.json
|
||||
:language: json
|
||||
|
||||
:code:`POST /volume_type`
|
||||
:code:`POST /v1/volume_type`
|
||||
|
||||
Create a volume type.
|
||||
|
||||
@ -324,7 +324,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/input/create_volume_type-body.json
|
||||
:language: json
|
||||
|
||||
:code:`DELETE /volume_type/<volume_type_id>`
|
||||
:code:`DELETE /v1/volume_type/<volume_type_id>`
|
||||
|
||||
Delete a volume type.
|
||||
|
||||
@ -348,7 +348,7 @@ API documentation
|
||||
- uuid
|
||||
- The Volume Type Uuid
|
||||
|
||||
:code:`GET /info`
|
||||
:code:`GET /v1/info`
|
||||
|
||||
Display information about the current version and entity counts.
|
||||
|
||||
@ -361,7 +361,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/output/info.json
|
||||
:language: json
|
||||
|
||||
:code:`POST /project/<project_id>/instance`
|
||||
:code:`POST /v1/project/<project_id>/instance`
|
||||
|
||||
Create an instance.
|
||||
|
||||
@ -419,7 +419,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/input/create_instance-body.json
|
||||
:language: json
|
||||
|
||||
:code:`DELETE /instance/<instance_id>`
|
||||
:code:`DELETE /v1/instance/<instance_id>`
|
||||
|
||||
Delete an instance.
|
||||
|
||||
@ -453,7 +453,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/input/delete_instance-body.json
|
||||
:language: json
|
||||
|
||||
:code:`PUT /instance/<instance_id>/resize`
|
||||
:code:`PUT /v1/instance/<instance_id>/resize`
|
||||
|
||||
Re-size an instance.
|
||||
|
||||
@ -491,7 +491,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/input/resize_instance-body.json
|
||||
:language: json
|
||||
|
||||
:code:`PUT /instance/<instance_id>/rebuild`
|
||||
:code:`PUT /v1/instance/<instance_id>/rebuild`
|
||||
|
||||
Rebuild an instance.
|
||||
|
||||
@ -537,7 +537,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/input/rebuild_instance-body.json
|
||||
:language: json
|
||||
|
||||
:code:`GET /project/<project_id>/instances`
|
||||
:code:`GET /v1/project/<project_id>/instances`
|
||||
|
||||
List instances for a tenant.
|
||||
|
||||
@ -575,7 +575,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/output/instances.json
|
||||
:language: json
|
||||
|
||||
:code:`POST /project/<project_id>/volume`
|
||||
:code:`POST /v1/project/<project_id>/volume`
|
||||
|
||||
Create a volume.
|
||||
|
||||
@ -629,7 +629,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/input/create_volume-body.json
|
||||
:language: json
|
||||
|
||||
:code:`DELETE /volume/<volume_id>`
|
||||
:code:`DELETE /v1/volume/<volume_id>`
|
||||
|
||||
Delete a volume.
|
||||
|
||||
@ -663,7 +663,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/input/delete_volume-body.json
|
||||
:language: json
|
||||
|
||||
:code:`PUT /volume/<volume_id>/resize`
|
||||
:code:`PUT /v1/volume/<volume_id>/resize`
|
||||
|
||||
Re-size a volume.
|
||||
|
||||
@ -701,7 +701,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/input/resize_volume-body.json
|
||||
:language: json
|
||||
|
||||
:code:`PUT /volume/<volume_id>/attach`
|
||||
:code:`PUT /v1/volume/<volume_id>/attach`
|
||||
|
||||
Update the attachments for a volume.
|
||||
|
||||
@ -739,7 +739,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/input/attach_volume-body.json
|
||||
:language: json
|
||||
|
||||
:code:`PUT /volume/<volume_id>/detach`
|
||||
:code:`PUT /v1/volume/<volume_id>/detach`
|
||||
|
||||
Detach a volume.
|
||||
|
||||
@ -777,7 +777,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/input/detach_volume-body.json
|
||||
:language: json
|
||||
|
||||
:code:`GET /project/<project_id>/volumes`
|
||||
:code:`GET /v1/project/<project_id>/volumes`
|
||||
|
||||
List volumes for a tenant.
|
||||
|
||||
@ -815,7 +815,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/output/volumes.json
|
||||
:language: json
|
||||
|
||||
:code:`GET /project/<project_id>/entities`
|
||||
:code:`GET /v1/project/<project_id>/entities`
|
||||
|
||||
List entities for a tenant.
|
||||
|
||||
@ -853,7 +853,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/output/entities.json
|
||||
:language: json
|
||||
|
||||
:code:`PUT /entity/instance/<instance_id>`
|
||||
:code:`PUT /v1/entity/instance/<instance_id>`
|
||||
|
||||
Update an instance.
|
||||
|
||||
@ -896,7 +896,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/output/update_instance_entity.json
|
||||
:language: json
|
||||
|
||||
:code:`HEAD /entity/<entity_id>`
|
||||
:code:`HEAD /v1/entity/<entity_id>`
|
||||
|
||||
Verify that an entity exists.
|
||||
|
||||
@ -925,7 +925,7 @@ API documentation
|
||||
.. literalinclude:: api_examples/output/entity.json
|
||||
:language: json
|
||||
|
||||
:code:`GET /entity/<entity_id>`
|
||||
:code:`GET /v1/entity/<entity_id>`
|
||||
|
||||
Get an entity.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user