Merge pull request #682 from whummer/feature/apigateway-stages
Initial support for apigateway stages
This commit is contained in:
commit
e558a066bb
@ -149,6 +149,26 @@ class Resource(object):
|
||||
return self.resource_methods[method_type].pop('methodIntegration')
|
||||
|
||||
|
||||
class Stage(dict):
|
||||
def __init__(self, name=None, deployment_id=None):
|
||||
super(Stage, self).__init__()
|
||||
self['stageName'] = name
|
||||
self['deploymentId'] = deployment_id
|
||||
self['methodSettings'] = {}
|
||||
self['variables'] = {}
|
||||
self['description'] = ''
|
||||
|
||||
def apply_operations(self, patch_operations):
|
||||
for op in patch_operations:
|
||||
if op['op'] == 'replace':
|
||||
# TODO: match the path against the values hash
|
||||
# (e.g., path could be '/*/*/logging/loglevel')
|
||||
self[op['path']] = op['value']
|
||||
else:
|
||||
raise Exception('Patch operation "%s" not implemented' % op['op'])
|
||||
return self
|
||||
|
||||
|
||||
class RestAPI(object):
|
||||
def __init__(self, id, region_name, name, description):
|
||||
self.id = id
|
||||
@ -158,6 +178,7 @@ class RestAPI(object):
|
||||
self.create_date = datetime.datetime.utcnow()
|
||||
|
||||
self.deployments = {}
|
||||
self.stages = {}
|
||||
|
||||
self.resources = {}
|
||||
self.add_child('/') # Add default child
|
||||
@ -202,6 +223,7 @@ class RestAPI(object):
|
||||
deployment_id = create_id()
|
||||
deployment = Deployment(deployment_id, name)
|
||||
self.deployments[deployment_id] = deployment
|
||||
self.stages[name] = Stage(name=name, deployment_id=deployment_id)
|
||||
|
||||
self.update_integration_mocks(name)
|
||||
|
||||
@ -276,6 +298,17 @@ class APIGatewayBackend(BaseBackend):
|
||||
method = resource.add_method(method_type, authorization_type)
|
||||
return method
|
||||
|
||||
def get_stage(self, function_id, stage_name):
|
||||
api = self.get_rest_api(function_id)
|
||||
return api.stages.get(stage_name)
|
||||
|
||||
def update_stage(self, function_id, stage_name, patch_operations):
|
||||
stage = self.get_stage(function_id, stage_name)
|
||||
if not stage:
|
||||
api = self.get_rest_api(function_id)
|
||||
stage = api.stages[stage_name] = Stage()
|
||||
return stage.apply_operations(patch_operations)
|
||||
|
||||
def get_method_response(self, function_id, resource_id, method_type, response_code):
|
||||
method = self.get_method(function_id, resource_id, method_type)
|
||||
method_response = method.get_response(response_code)
|
||||
|
@ -95,6 +95,19 @@ class APIGatewayResponse(BaseResponse):
|
||||
method_response = self.backend.delete_method_response(function_id, resource_id, method_type, response_code)
|
||||
return 200, headers, json.dumps(method_response)
|
||||
|
||||
def stages(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
url_path_parts = self.path.split("/")
|
||||
function_id = url_path_parts[2]
|
||||
stage_name = url_path_parts[4]
|
||||
|
||||
if self.method == 'GET':
|
||||
stage_response = self.backend.get_stage(function_id, stage_name)
|
||||
elif self.method == 'PATCH':
|
||||
path_operations = self._get_param('patchOperations')
|
||||
stage_response = self.backend.update_stage(function_id, stage_name, path_operations)
|
||||
return 200, headers, json.dumps(stage_response)
|
||||
|
||||
def integrations(self, request, full_url, headers):
|
||||
self.setup_class(request, full_url, headers)
|
||||
url_path_parts = self.path.split("/")
|
||||
|
@ -9,11 +9,12 @@ url_paths = {
|
||||
'{0}/restapis$': APIGatewayResponse().restapis,
|
||||
'{0}/restapis/(?P<function_id>[^/]+)/?$': APIGatewayResponse().restapis_individual,
|
||||
'{0}/restapis/(?P<function_id>[^/]+)/resources$': APIGatewayResponse().resources,
|
||||
'{0}/restapis/(?P<function_id>[^/]+)/stages/(?P<stage_name>[^/]+)/?$': APIGatewayResponse().stages,
|
||||
'{0}/restapis/(?P<function_id>[^/]+)/deployments$': APIGatewayResponse().deployments,
|
||||
'{0}/restapis/(?P<function_id>[^/]+)/deployments/(?P<deployment_id>[^/]+)/?$': APIGatewayResponse().individual_deployment,
|
||||
'{0}/restapis/(?P<function_id>[^/]+)/resources/(?P<resource_id>[^/]+)/?$': APIGatewayResponse().resource_individual,
|
||||
'{0}/restapis/(?P<function_id>[^/]+)/resources/(?P<resource_id>[^/]+)/methods/(?P<method_name>[^/]+)/?$': APIGatewayResponse().resource_methods,
|
||||
'{0}/restapis/(?P<function_id>[^/]+)/resources/(?P<resource_id>[^/]+)/methods/(?P<method_name>[^/]+)/responses/200$': APIGatewayResponse().resource_method_responses,
|
||||
'{0}/restapis/(?P<function_id>[^/]+)/resources/(?P<resource_id>[^/]+)/methods/(?P<method_name>[^/]+)/responses/(?P<status_code>\d+)$': APIGatewayResponse().resource_method_responses,
|
||||
'{0}/restapis/(?P<function_id>[^/]+)/resources/(?P<resource_id>[^/]+)/methods/(?P<method_name>[^/]+)/integration/?$': APIGatewayResponse().integrations,
|
||||
'{0}/restapis/(?P<function_id>[^/]+)/resources/(?P<resource_id>[^/]+)/methods/(?P<method_name>[^/]+)/integration/responses/(?P<status_code>\d+)/?$': APIGatewayResponse().integration_responses,
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ from werkzeug.serving import run_simple
|
||||
from moto.backends import BACKENDS
|
||||
from moto.core.utils import convert_flask_to_httpretty_response
|
||||
|
||||
HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "HEAD"]
|
||||
HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "HEAD", "PATCH"]
|
||||
|
||||
|
||||
class DomainDispatcherApplication(object):
|
||||
|
@ -472,6 +472,7 @@ def test_integration_response():
|
||||
@mock_apigateway
|
||||
def test_deployment():
|
||||
client = boto3.client('apigateway', region_name='us-west-2')
|
||||
stage_name = 'staging'
|
||||
response = client.create_rest_api(
|
||||
name='my_api',
|
||||
description='this is my api',
|
||||
@ -480,7 +481,7 @@ def test_deployment():
|
||||
|
||||
response = client.create_deployment(
|
||||
restApiId=api_id,
|
||||
stageName='staging',
|
||||
stageName=stage_name,
|
||||
)
|
||||
deployment_id = response['id']
|
||||
|
||||
@ -511,6 +512,35 @@ def test_deployment():
|
||||
)
|
||||
len(response['items']).should.equal(0)
|
||||
|
||||
# test deployment stages
|
||||
|
||||
stage = client.get_stage(
|
||||
restApiId=api_id,
|
||||
stageName=stage_name
|
||||
)
|
||||
stage['stageName'].should.equal(stage_name)
|
||||
stage['deploymentId'].should.equal(deployment_id)
|
||||
|
||||
stage = client.update_stage(
|
||||
restApiId=api_id,
|
||||
stageName=stage_name,
|
||||
patchOperations=[
|
||||
{
|
||||
'op': 'replace',
|
||||
'path': 'description',
|
||||
'value': '_new_description_'
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
stage = client.get_stage(
|
||||
restApiId=api_id,
|
||||
stageName=stage_name
|
||||
)
|
||||
stage['stageName'].should.equal(stage_name)
|
||||
stage['deploymentId'].should.equal(deployment_id)
|
||||
stage['description'].should.equal('_new_description_')
|
||||
|
||||
|
||||
@httpretty.activate
|
||||
@mock_apigateway
|
||||
|
Loading…
Reference in New Issue
Block a user