diff --git a/moto/apigateway/models.py b/moto/apigateway/models.py index a26b3c0f8..e9f8e5470 100644 --- a/moto/apigateway/models.py +++ b/moto/apigateway/models.py @@ -6,6 +6,13 @@ from moto.core.utils import iso_8601_datetime_with_milliseconds from .utils import create_id +class Deployment(dict): + def __init__(self, deployment_id, name): + super(Deployment, self).__init__() + self['id'] = deployment_id + self['stageName'] = name + + class Integration(dict): def __init__(self, integration_type, uri): super(Integration, self).__init__() @@ -91,6 +98,8 @@ class RestAPI(object): self.description = description self.create_date = datetime.datetime.utcnow() + self.deployments = {} + self.resources = {} self.add_child('/') # Add default child @@ -108,6 +117,21 @@ class RestAPI(object): self.resources[child_id] = child return child + def create_deployment(self, name): + deployment_id = create_id() + deployment = Deployment(deployment_id, name) + self.deployments[deployment_id] = deployment + return deployment + + def get_deployment(self, deployment_id): + return self.deployments[deployment_id] + + def get_deployments(self): + return self.deployments.values() + + def delete_deployment(self, deployment_id): + return self.deployments.pop(deployment_id) + class APIGatewayBackend(BaseBackend): def __init__(self, region_name): @@ -196,6 +220,23 @@ class APIGatewayBackend(BaseBackend): resource = self.get_resource(function_id, resource_id) return resource.delete_integration(method_type) + def create_deployment(self, function_id, name): + api = self.get_rest_api(function_id) + deployment = api.create_deployment(name) + return deployment + + def get_deployment(self, function_id, deployment_id): + api = self.get_rest_api(function_id) + return api.get_deployment(deployment_id) + + def get_deployments(self, function_id): + api = self.get_rest_api(function_id) + return api.get_deployments() + + def delete_deployment(self, function_id, deployment_id): + api = self.get_rest_api(function_id) + return api.delete_deployment(deployment_id) + apigateway_backends = {} for region_name in ['us-east-1', 'us-west-2', 'eu-west-1', 'ap-northeast-1']: # Not available in boto yet apigateway_backends[region_name] = APIGatewayBackend(region_name) diff --git a/moto/apigateway/responses.py b/moto/apigateway/responses.py index e11cfac90..cebd2c7dd 100644 --- a/moto/apigateway/responses.py +++ b/moto/apigateway/responses.py @@ -117,3 +117,28 @@ class APIGatewayResponse(BaseResponse): elif self.method == 'DELETE': integration_response = self.backend.delete_integration(function_id, resource_id, method_type) return 200, headers, json.dumps(integration_response) + + def deployments(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + function_id = self.path.replace("/restapis/", "", 1).split("/")[0] + + if self.method == 'GET': + deployments = self.backend.get_deployments(function_id) + return 200, headers, json.dumps({"item": deployments}) + elif self.method == 'POST': + name = self._get_param("stageName") + deployment = self.backend.create_deployment(function_id, name) + return 200, headers, json.dumps(deployment) + + def individual_deployment(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + url_path_parts = self.path.split("/") + function_id = url_path_parts[2] + deployment_id = url_path_parts[4] + + if self.method == 'GET': + deployment = self.backend.get_deployment(function_id, deployment_id) + return 200, headers, json.dumps(deployment) + elif self.method == 'DELETE': + deployment = self.backend.delete_deployment(function_id, deployment_id) + return 200, headers, json.dumps(deployment) diff --git a/moto/apigateway/urls.py b/moto/apigateway/urls.py index a42c30cfd..731c01319 100644 --- a/moto/apigateway/urls.py +++ b/moto/apigateway/urls.py @@ -9,6 +9,8 @@ url_paths = { '{0}/restapis$': APIGatewayResponse().restapis, '{0}/restapis/(?P[^/]+)/?$': APIGatewayResponse().restapis_individual, '{0}/restapis/(?P[^/]+)/resources$': APIGatewayResponse().resources, + '{0}/restapis/(?P[^/]+)/deployments$': APIGatewayResponse().deployments, + '{0}/restapis/(?P[^/]+)/deployments/(?P[^/]+)/?$': APIGatewayResponse().individual_deployment, '{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/?$': APIGatewayResponse().resource_individual, '{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/?$': APIGatewayResponse().resource_methods, '{0}/restapis/(?P[^/]+)/resources/(?P[^/]+)/methods/(?P[^/]+)/responses/200$': APIGatewayResponse().resource_method_responses, diff --git a/tests/test_apigateway/test_apigateway.py b/tests/test_apigateway/test_apigateway.py index cac502cc9..e7ac11670 100644 --- a/tests/test_apigateway/test_apigateway.py +++ b/tests/test_apigateway/test_apigateway.py @@ -259,3 +259,45 @@ def test_integrations(): resourceId=root_id, ) response['resourceMethods']['GET'].shouldnt.contain("methodIntegration") + + +@mock_apigateway +def test_deployment(): + client = boto3.client('apigateway', region_name='us-west-2') + response = client.create_rest_api( + name='my_api', + description='this is my api', + ) + api_id = response['id'] + + response = client.create_deployment( + restApiId=api_id, + stageName='staging', + ) + deployment_id = response['id'] + + response = client.get_deployment( + restApiId=api_id, + deploymentId=deployment_id, + ) + response.should.equal({ + 'id': deployment_id, + 'ResponseMetadata': {'HTTPStatusCode': 200} + }) + + response = client.get_deployments( + restApiId=api_id, + ) + response['items'].should.equal([ + {'id': deployment_id} + ]) + + response = client.delete_deployment( + restApiId=api_id, + deploymentId=deployment_id, + ) + + response = client.get_deployments( + restApiId=api_id, + ) + len(response['items']).should.equal(0)