Merge pull request #699 from tootedom/apigateway
added more api gateway coverage
This commit is contained in:
commit
ea0b587791
12
moto/apigateway/exceptions.py
Normal file
12
moto/apigateway/exceptions.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from moto.core.exceptions import RESTError
|
||||||
|
|
||||||
|
|
||||||
|
class StageNotFoundException(RESTError):
|
||||||
|
code = 404
|
||||||
|
def __init__(self):
|
||||||
|
super(StageNotFoundException, self).__init__(
|
||||||
|
"NotFoundException", "Invalid stage identifier specified")
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -7,15 +7,18 @@ import requests
|
|||||||
from moto.core import BaseBackend
|
from moto.core import BaseBackend
|
||||||
from moto.core.utils import iso_8601_datetime_with_milliseconds
|
from moto.core.utils import iso_8601_datetime_with_milliseconds
|
||||||
from .utils import create_id
|
from .utils import create_id
|
||||||
|
from .exceptions import StageNotFoundException
|
||||||
|
|
||||||
STAGE_URL = "https://{api_id}.execute-api.{region_name}.amazonaws.com/{stage_name}"
|
STAGE_URL = "https://{api_id}.execute-api.{region_name}.amazonaws.com/{stage_name}"
|
||||||
|
|
||||||
|
|
||||||
class Deployment(dict):
|
class Deployment(dict):
|
||||||
def __init__(self, deployment_id, name):
|
def __init__(self, deployment_id, name, description=""):
|
||||||
super(Deployment, self).__init__()
|
super(Deployment, self).__init__()
|
||||||
self['id'] = deployment_id
|
self['id'] = deployment_id
|
||||||
self['stageName'] = name
|
self['stageName'] = name
|
||||||
|
self['description'] = description
|
||||||
|
self['createdDate'] = iso_8601_datetime_with_milliseconds(datetime.datetime.now())
|
||||||
|
|
||||||
|
|
||||||
class IntegrationResponse(dict):
|
class IntegrationResponse(dict):
|
||||||
@ -150,24 +153,133 @@ class Resource(object):
|
|||||||
|
|
||||||
|
|
||||||
class Stage(dict):
|
class Stage(dict):
|
||||||
def __init__(self, name=None, deployment_id=None):
|
|
||||||
|
|
||||||
|
def __init__(self, name=None, deployment_id=None, variables=None,
|
||||||
|
description='',cacheClusterEnabled=False,cacheClusterSize=None):
|
||||||
super(Stage, self).__init__()
|
super(Stage, self).__init__()
|
||||||
|
if variables is None:
|
||||||
|
variables = {}
|
||||||
self['stageName'] = name
|
self['stageName'] = name
|
||||||
self['deploymentId'] = deployment_id
|
self['deploymentId'] = deployment_id
|
||||||
self['methodSettings'] = {}
|
self['methodSettings'] = {}
|
||||||
self['variables'] = {}
|
self['variables'] = variables
|
||||||
self['description'] = ''
|
self['description'] = description
|
||||||
|
self['cacheClusterEnabled'] = cacheClusterEnabled
|
||||||
|
if self['cacheClusterEnabled']:
|
||||||
|
self['cacheClusterSize'] = str(0.5)
|
||||||
|
|
||||||
|
if cacheClusterSize is not None:
|
||||||
|
self['cacheClusterSize'] = str(cacheClusterSize)
|
||||||
|
|
||||||
def apply_operations(self, patch_operations):
|
def apply_operations(self, patch_operations):
|
||||||
for op in patch_operations:
|
for op in patch_operations:
|
||||||
if op['op'] == 'replace':
|
if 'variables/' in op['path']:
|
||||||
# TODO: match the path against the values hash
|
self._apply_operation_to_variables(op)
|
||||||
|
elif '/cacheClusterEnabled' in op['path']:
|
||||||
|
self['cacheClusterEnabled'] = self._str2bool(op['value'])
|
||||||
|
if 'cacheClusterSize' not in self and self['cacheClusterEnabled']:
|
||||||
|
self['cacheClusterSize'] = str(0.5)
|
||||||
|
elif '/cacheClusterSize' in op['path']:
|
||||||
|
self['cacheClusterSize'] = str(float(op['value']))
|
||||||
|
elif '/description' in op['path']:
|
||||||
|
self['description'] = op['value']
|
||||||
|
elif '/deploymentId' in op['path']:
|
||||||
|
self['deploymentId'] = op['value']
|
||||||
|
elif op['op'] == 'replace':
|
||||||
|
# Method Settings drop into here
|
||||||
# (e.g., path could be '/*/*/logging/loglevel')
|
# (e.g., path could be '/*/*/logging/loglevel')
|
||||||
self[op['path']] = op['value']
|
split_path = op['path'].split('/',3)
|
||||||
|
if len(split_path)!=4:
|
||||||
|
continue
|
||||||
|
self._patch_method_setting('/'.join(split_path[1:3]),split_path[3],op['value'])
|
||||||
else:
|
else:
|
||||||
raise Exception('Patch operation "%s" not implemented' % op['op'])
|
raise Exception('Patch operation "%s" not implemented' % op['op'])
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def _patch_method_setting(self,resource_path_and_method,key,value):
|
||||||
|
updated_key = self._method_settings_translations(key)
|
||||||
|
if updated_key is not None:
|
||||||
|
if resource_path_and_method not in self['methodSettings']:
|
||||||
|
self['methodSettings'][resource_path_and_method] = self._get_default_method_settings()
|
||||||
|
self['methodSettings'][resource_path_and_method][updated_key] = self._convert_to_type(updated_key,value)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_default_method_settings(self):
|
||||||
|
return {
|
||||||
|
"throttlingRateLimit": 1000.0,
|
||||||
|
"dataTraceEnabled": False,
|
||||||
|
"metricsEnabled": False,
|
||||||
|
"unauthorizedCacheControlHeaderStrategy": "SUCCEED_WITH_RESPONSE_HEADER",
|
||||||
|
"cacheTtlInSeconds": 300,
|
||||||
|
"cacheDataEncrypted": True,
|
||||||
|
"cachingEnabled": False,
|
||||||
|
"throttlingBurstLimit": 2000,
|
||||||
|
"requireAuthorizationForCacheControl": True
|
||||||
|
}
|
||||||
|
|
||||||
|
def _method_settings_translations(self,key):
|
||||||
|
mappings = {
|
||||||
|
'metrics/enabled' :'metricsEnabled',
|
||||||
|
'logging/loglevel' : 'loggingLevel',
|
||||||
|
'logging/dataTrace' : 'dataTraceEnabled' ,
|
||||||
|
'throttling/burstLimit' : 'throttlingBurstLimit',
|
||||||
|
'throttling/rateLimit' : 'throttlingRateLimit',
|
||||||
|
'caching/enabled' : 'cachingEnabled',
|
||||||
|
'caching/ttlInSeconds' : 'cacheTtlInSeconds',
|
||||||
|
'caching/dataEncrypted' : 'cacheDataEncrypted',
|
||||||
|
'caching/requireAuthorizationForCacheControl' : 'requireAuthorizationForCacheControl',
|
||||||
|
'caching/unauthorizedCacheControlHeaderStrategy' : 'unauthorizedCacheControlHeaderStrategy'
|
||||||
|
}
|
||||||
|
|
||||||
|
if key in mappings:
|
||||||
|
return mappings[key]
|
||||||
|
else:
|
||||||
|
None
|
||||||
|
|
||||||
|
def _str2bool(self,v):
|
||||||
|
return v.lower() == "true"
|
||||||
|
|
||||||
|
def _convert_to_type(self,key,val):
|
||||||
|
type_mappings = {
|
||||||
|
'metricsEnabled' : 'bool',
|
||||||
|
'loggingLevel' : 'str',
|
||||||
|
'dataTraceEnabled' : 'bool',
|
||||||
|
'throttlingBurstLimit' : 'int',
|
||||||
|
'throttlingRateLimit' : 'float',
|
||||||
|
'cachingEnabled' : 'bool',
|
||||||
|
'cacheTtlInSeconds' : 'int',
|
||||||
|
'cacheDataEncrypted' : 'bool',
|
||||||
|
'requireAuthorizationForCacheControl' :'bool',
|
||||||
|
'unauthorizedCacheControlHeaderStrategy' : 'str'
|
||||||
|
}
|
||||||
|
|
||||||
|
if key in type_mappings:
|
||||||
|
type_value = type_mappings[key]
|
||||||
|
|
||||||
|
if type_value == 'bool':
|
||||||
|
return self._str2bool(val)
|
||||||
|
elif type_value == 'int':
|
||||||
|
return int(val)
|
||||||
|
elif type_value == 'float':
|
||||||
|
return float(val)
|
||||||
|
else:
|
||||||
|
return str(val)
|
||||||
|
else:
|
||||||
|
return str(val)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _apply_operation_to_variables(self,op):
|
||||||
|
key = op['path'][op['path'].rindex("variables/")+10:]
|
||||||
|
if op['op'] == 'remove':
|
||||||
|
self['variables'].pop(key, None)
|
||||||
|
elif op['op'] == 'replace':
|
||||||
|
self['variables'][key] = op['value']
|
||||||
|
else:
|
||||||
|
raise Exception('Patch operation "%s" not implemented' % op['op'])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RestAPI(object):
|
class RestAPI(object):
|
||||||
def __init__(self, id, region_name, name, description):
|
def __init__(self, id, region_name, name, description):
|
||||||
@ -219,12 +331,22 @@ class RestAPI(object):
|
|||||||
for method in httpretty.httpretty.METHODS:
|
for method in httpretty.httpretty.METHODS:
|
||||||
httpretty.register_uri(method, stage_url, body=self.resource_callback)
|
httpretty.register_uri(method, stage_url, body=self.resource_callback)
|
||||||
|
|
||||||
def create_deployment(self, name):
|
def create_stage(self, name, deployment_id,variables=None,description='',cacheClusterEnabled=None,cacheClusterSize=None):
|
||||||
deployment_id = create_id()
|
if variables is None:
|
||||||
deployment = Deployment(deployment_id, name)
|
variables = {}
|
||||||
self.deployments[deployment_id] = deployment
|
stage = Stage(name=name, deployment_id=deployment_id,variables=variables,
|
||||||
self.stages[name] = Stage(name=name, deployment_id=deployment_id)
|
description=description,cacheClusterSize=cacheClusterSize,cacheClusterEnabled=cacheClusterEnabled)
|
||||||
|
self.stages[name] = stage
|
||||||
|
self.update_integration_mocks(name)
|
||||||
|
return stage
|
||||||
|
|
||||||
|
def create_deployment(self, name, description="",stage_variables=None):
|
||||||
|
if stage_variables is None:
|
||||||
|
stage_variables = {}
|
||||||
|
deployment_id = create_id()
|
||||||
|
deployment = Deployment(deployment_id, name, description)
|
||||||
|
self.deployments[deployment_id] = deployment
|
||||||
|
self.stages[name] = Stage(name=name, deployment_id=deployment_id,variables=stage_variables)
|
||||||
self.update_integration_mocks(name)
|
self.update_integration_mocks(name)
|
||||||
|
|
||||||
return deployment
|
return deployment
|
||||||
@ -232,6 +354,9 @@ class RestAPI(object):
|
|||||||
def get_deployment(self, deployment_id):
|
def get_deployment(self, deployment_id):
|
||||||
return self.deployments[deployment_id]
|
return self.deployments[deployment_id]
|
||||||
|
|
||||||
|
def get_stages(self):
|
||||||
|
return list(self.stages.values())
|
||||||
|
|
||||||
def get_deployments(self):
|
def get_deployments(self):
|
||||||
return list(self.deployments.values())
|
return list(self.deployments.values())
|
||||||
|
|
||||||
@ -300,6 +425,25 @@ class APIGatewayBackend(BaseBackend):
|
|||||||
|
|
||||||
def get_stage(self, function_id, stage_name):
|
def get_stage(self, function_id, stage_name):
|
||||||
api = self.get_rest_api(function_id)
|
api = self.get_rest_api(function_id)
|
||||||
|
stage = api.stages.get(stage_name)
|
||||||
|
if stage is None:
|
||||||
|
raise StageNotFoundException()
|
||||||
|
else:
|
||||||
|
return stage
|
||||||
|
|
||||||
|
|
||||||
|
def get_stages(self, function_id):
|
||||||
|
api = self.get_rest_api(function_id)
|
||||||
|
return api.get_stages()
|
||||||
|
|
||||||
|
|
||||||
|
def create_stage(self, function_id, stage_name, deploymentId,
|
||||||
|
variables=None,description='',cacheClusterEnabled=None,cacheClusterSize=None):
|
||||||
|
if variables is None:
|
||||||
|
variables = {}
|
||||||
|
api = self.get_rest_api(function_id)
|
||||||
|
api.create_stage(stage_name,deploymentId,variables=variables,
|
||||||
|
description=description,cacheClusterEnabled=cacheClusterEnabled,cacheClusterSize=cacheClusterSize)
|
||||||
return api.stages.get(stage_name)
|
return api.stages.get(stage_name)
|
||||||
|
|
||||||
def update_stage(self, function_id, stage_name, patch_operations):
|
def update_stage(self, function_id, stage_name, patch_operations):
|
||||||
@ -354,9 +498,11 @@ class APIGatewayBackend(BaseBackend):
|
|||||||
integration_response = integration.delete_integration_response(status_code)
|
integration_response = integration.delete_integration_response(status_code)
|
||||||
return integration_response
|
return integration_response
|
||||||
|
|
||||||
def create_deployment(self, function_id, name):
|
def create_deployment(self, function_id, name, description ="", stage_variables=None):
|
||||||
|
if stage_variables is None:
|
||||||
|
stage_variables = {}
|
||||||
api = self.get_rest_api(function_id)
|
api = self.get_rest_api(function_id)
|
||||||
deployment = api.create_deployment(name)
|
deployment = api.create_deployment(name, description,stage_variables)
|
||||||
return deployment
|
return deployment
|
||||||
|
|
||||||
def get_deployment(self, function_id, deployment_id):
|
def get_deployment(self, function_id, deployment_id):
|
||||||
|
@ -4,6 +4,7 @@ import json
|
|||||||
|
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
from .models import apigateway_backends
|
from .models import apigateway_backends
|
||||||
|
from .exceptions import StageNotFoundException
|
||||||
|
|
||||||
|
|
||||||
class APIGatewayResponse(BaseResponse):
|
class APIGatewayResponse(BaseResponse):
|
||||||
@ -11,6 +12,15 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
def _get_param(self, key):
|
def _get_param(self, key):
|
||||||
return json.loads(self.body.decode("ascii")).get(key)
|
return json.loads(self.body.decode("ascii")).get(key)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_param_with_default_value(self, key, default):
|
||||||
|
jsonbody = json.loads(self.body.decode("ascii"))
|
||||||
|
|
||||||
|
if key in jsonbody:
|
||||||
|
return jsonbody.get(key)
|
||||||
|
else:
|
||||||
|
return default
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def backend(self):
|
def backend(self):
|
||||||
return apigateway_backends[self.region]
|
return apigateway_backends[self.region]
|
||||||
@ -95,6 +105,28 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
method_response = self.backend.delete_method_response(function_id, resource_id, method_type, response_code)
|
method_response = self.backend.delete_method_response(function_id, resource_id, method_type, response_code)
|
||||||
return 200, headers, json.dumps(method_response)
|
return 200, headers, json.dumps(method_response)
|
||||||
|
|
||||||
|
def restapis_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]
|
||||||
|
|
||||||
|
if self.method == 'POST':
|
||||||
|
stage_name = self._get_param("stageName")
|
||||||
|
deployment_id = self._get_param("deploymentId")
|
||||||
|
stage_variables = self._get_param_with_default_value('variables',{})
|
||||||
|
description = self._get_param_with_default_value('description','')
|
||||||
|
cacheClusterEnabled = self._get_param_with_default_value('cacheClusterEnabled',False)
|
||||||
|
cacheClusterSize = self._get_param_with_default_value('cacheClusterSize',None)
|
||||||
|
|
||||||
|
stage_response = self.backend.create_stage(function_id, stage_name, deployment_id,
|
||||||
|
variables=stage_variables, description=description,
|
||||||
|
cacheClusterEnabled=cacheClusterEnabled, cacheClusterSize=cacheClusterSize)
|
||||||
|
elif self.method == 'GET':
|
||||||
|
stages = self.backend.get_stages(function_id)
|
||||||
|
return 200, headers, json.dumps({"item": stages})
|
||||||
|
|
||||||
|
return 200, headers, json.dumps(stage_response)
|
||||||
|
|
||||||
def stages(self, request, full_url, headers):
|
def stages(self, request, full_url, headers):
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
url_path_parts = self.path.split("/")
|
url_path_parts = self.path.split("/")
|
||||||
@ -102,10 +134,13 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
stage_name = url_path_parts[4]
|
stage_name = url_path_parts[4]
|
||||||
|
|
||||||
if self.method == 'GET':
|
if self.method == 'GET':
|
||||||
|
try:
|
||||||
stage_response = self.backend.get_stage(function_id, stage_name)
|
stage_response = self.backend.get_stage(function_id, stage_name)
|
||||||
|
except StageNotFoundException as error:
|
||||||
|
return error.code, headers,'{{"message":"{0}","code":"{1}"}}'.format(error.message,error.error_type)
|
||||||
elif self.method == 'PATCH':
|
elif self.method == 'PATCH':
|
||||||
path_operations = self._get_param('patchOperations')
|
patch_operations = self._get_param('patchOperations')
|
||||||
stage_response = self.backend.update_stage(function_id, stage_name, path_operations)
|
stage_response = self.backend.update_stage(function_id, stage_name, patch_operations)
|
||||||
return 200, headers, json.dumps(stage_response)
|
return 200, headers, json.dumps(stage_response)
|
||||||
|
|
||||||
def integrations(self, request, full_url, headers):
|
def integrations(self, request, full_url, headers):
|
||||||
@ -158,7 +193,9 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
return 200, headers, json.dumps({"item": deployments})
|
return 200, headers, json.dumps({"item": deployments})
|
||||||
elif self.method == 'POST':
|
elif self.method == 'POST':
|
||||||
name = self._get_param("stageName")
|
name = self._get_param("stageName")
|
||||||
deployment = self.backend.create_deployment(function_id, name)
|
description = self._get_param_with_default_value("description","")
|
||||||
|
stage_variables = self._get_param_with_default_value('variables',{})
|
||||||
|
deployment = self.backend.create_deployment(function_id, name, description,stage_variables)
|
||||||
return 200, headers, json.dumps(deployment)
|
return 200, headers, json.dumps(deployment)
|
||||||
|
|
||||||
def individual_deployment(self, request, full_url, headers):
|
def individual_deployment(self, request, full_url, headers):
|
||||||
|
@ -9,6 +9,7 @@ url_paths = {
|
|||||||
'{0}/restapis$': APIGatewayResponse().restapis,
|
'{0}/restapis$': APIGatewayResponse().restapis,
|
||||||
'{0}/restapis/(?P<function_id>[^/]+)/?$': APIGatewayResponse().restapis_individual,
|
'{0}/restapis/(?P<function_id>[^/]+)/?$': APIGatewayResponse().restapis_individual,
|
||||||
'{0}/restapis/(?P<function_id>[^/]+)/resources$': APIGatewayResponse().resources,
|
'{0}/restapis/(?P<function_id>[^/]+)/resources$': APIGatewayResponse().resources,
|
||||||
|
'{0}/restapis/(?P<function_id>[^/]+)/stages$': APIGatewayResponse().restapis_stages,
|
||||||
'{0}/restapis/(?P<function_id>[^/]+)/stages/(?P<stage_name>[^/]+)/?$': APIGatewayResponse().stages,
|
'{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$': APIGatewayResponse().deployments,
|
||||||
'{0}/restapis/(?P<function_id>[^/]+)/deployments/(?P<deployment_id>[^/]+)/?$': APIGatewayResponse().individual_deployment,
|
'{0}/restapis/(?P<function_id>[^/]+)/deployments/(?P<deployment_id>[^/]+)/?$': APIGatewayResponse().individual_deployment,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from dateutil.tz import tzutc
|
from dateutil.tz import tzutc
|
||||||
import boto3
|
import boto3
|
||||||
@ -7,6 +8,7 @@ from freezegun import freeze_time
|
|||||||
import httpretty
|
import httpretty
|
||||||
import requests
|
import requests
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
from botocore.exceptions import ClientError
|
||||||
|
|
||||||
from moto import mock_apigateway
|
from moto import mock_apigateway
|
||||||
|
|
||||||
@ -360,6 +362,7 @@ def test_integrations():
|
|||||||
uri=test_uri,
|
uri=test_uri,
|
||||||
requestTemplates=templates
|
requestTemplates=templates
|
||||||
)
|
)
|
||||||
|
response['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
response['ResponseMetadata'].should.equal({'HTTPStatusCode': 200})
|
response['ResponseMetadata'].should.equal({'HTTPStatusCode': 200})
|
||||||
|
|
||||||
response = client.get_integration(
|
response = client.get_integration(
|
||||||
@ -469,6 +472,319 @@ def test_integration_response():
|
|||||||
response['methodIntegration']['integrationResponses'].should.equal({})
|
response['methodIntegration']['integrationResponses'].should.equal({})
|
||||||
|
|
||||||
|
|
||||||
|
@mock_apigateway
|
||||||
|
def test_update_stage_configuration():
|
||||||
|
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',
|
||||||
|
)
|
||||||
|
api_id = response['id']
|
||||||
|
|
||||||
|
response = client.create_deployment(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=stage_name,
|
||||||
|
description="1.0.1"
|
||||||
|
)
|
||||||
|
deployment_id = response['id']
|
||||||
|
|
||||||
|
response = client.get_deployment(
|
||||||
|
restApiId=api_id,
|
||||||
|
deploymentId=deployment_id,
|
||||||
|
)
|
||||||
|
response.pop('createdDate',None) # createdDate is hard to match against, remove it
|
||||||
|
response['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
|
response.should.equal({
|
||||||
|
'id': deployment_id,
|
||||||
|
'ResponseMetadata': {'HTTPStatusCode': 200},
|
||||||
|
'description' : '1.0.1'
|
||||||
|
})
|
||||||
|
|
||||||
|
response = client.create_deployment(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=stage_name,
|
||||||
|
description="1.0.2"
|
||||||
|
)
|
||||||
|
deployment_id2 = response['id']
|
||||||
|
|
||||||
|
|
||||||
|
stage = client.get_stage(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=stage_name
|
||||||
|
)
|
||||||
|
stage['stageName'].should.equal(stage_name)
|
||||||
|
stage['deploymentId'].should.equal(deployment_id2)
|
||||||
|
stage.shouldnt.have.key('cacheClusterSize')
|
||||||
|
|
||||||
|
client.update_stage(restApiId=api_id,stageName=stage_name,
|
||||||
|
patchOperations=[
|
||||||
|
{
|
||||||
|
"op" : "replace",
|
||||||
|
"path" : "/cacheClusterEnabled",
|
||||||
|
"value": "True"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
stage = client.get_stage(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=stage_name
|
||||||
|
)
|
||||||
|
|
||||||
|
stage.should.have.key('cacheClusterSize').which.should.equal("0.5")
|
||||||
|
|
||||||
|
client.update_stage(restApiId=api_id,stageName=stage_name,
|
||||||
|
patchOperations=[
|
||||||
|
{
|
||||||
|
"op" : "replace",
|
||||||
|
"path" : "/cacheClusterSize",
|
||||||
|
"value": "1.6"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
stage = client.get_stage(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=stage_name
|
||||||
|
)
|
||||||
|
|
||||||
|
stage.should.have.key('cacheClusterSize').which.should.equal("1.6")
|
||||||
|
|
||||||
|
|
||||||
|
client.update_stage(restApiId=api_id,stageName=stage_name,
|
||||||
|
patchOperations=[
|
||||||
|
{
|
||||||
|
"op" : "replace",
|
||||||
|
"path" : "/deploymentId",
|
||||||
|
"value": deployment_id
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op" : "replace",
|
||||||
|
"path" : "/variables/environment",
|
||||||
|
"value" : "dev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op" : "replace",
|
||||||
|
"path" : "/variables/region",
|
||||||
|
"value" : "eu-west-1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op" : "replace",
|
||||||
|
"path" : "/*/*/caching/dataEncrypted",
|
||||||
|
"value" : "True"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op" : "replace",
|
||||||
|
"path" : "/cacheClusterEnabled",
|
||||||
|
"value" : "True"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op" : "replace",
|
||||||
|
"path" : "/description",
|
||||||
|
"value" : "stage description update"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"op" : "replace",
|
||||||
|
"path" : "/cacheClusterSize",
|
||||||
|
"value" : "1.6"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
client.update_stage(restApiId=api_id,stageName=stage_name,
|
||||||
|
patchOperations=[
|
||||||
|
{
|
||||||
|
"op" : "remove",
|
||||||
|
"path" : "/variables/region",
|
||||||
|
"value" : "eu-west-1"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
stage = client.get_stage(restApiId=api_id,stageName=stage_name)
|
||||||
|
|
||||||
|
stage['description'].should.match('stage description update')
|
||||||
|
stage['cacheClusterSize'].should.equal("1.6")
|
||||||
|
stage['variables']['environment'].should.match('dev')
|
||||||
|
stage['variables'].should_not.have.key('region')
|
||||||
|
stage['cacheClusterEnabled'].should.be.true
|
||||||
|
stage['deploymentId'].should.match(deployment_id)
|
||||||
|
stage['methodSettings'].should.have.key('*/*')
|
||||||
|
stage['methodSettings']['*/*'].should.have.key('cacheDataEncrypted').which.should.be.true
|
||||||
|
|
||||||
|
try:
|
||||||
|
client.update_stage(restApiId=api_id,stageName=stage_name,
|
||||||
|
patchOperations=[
|
||||||
|
{
|
||||||
|
"op" : "add",
|
||||||
|
"path" : "/notasetting",
|
||||||
|
"value" : "eu-west-1"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
assert False.should.be.ok #Fail, should not be here
|
||||||
|
except Exception:
|
||||||
|
assert True.should.be.ok
|
||||||
|
|
||||||
|
@mock_apigateway
|
||||||
|
def test_non_existent_stage():
|
||||||
|
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']
|
||||||
|
|
||||||
|
|
||||||
|
client.get_stage.when.called_with(restApiId=api_id,stageName='xxx').should.throw(ClientError)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@mock_apigateway
|
||||||
|
def test_create_stage():
|
||||||
|
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',
|
||||||
|
)
|
||||||
|
api_id = response['id']
|
||||||
|
|
||||||
|
response = client.create_deployment(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=stage_name,
|
||||||
|
)
|
||||||
|
deployment_id = response['id']
|
||||||
|
|
||||||
|
response = client.get_deployment(
|
||||||
|
restApiId=api_id,
|
||||||
|
deploymentId=deployment_id,
|
||||||
|
)
|
||||||
|
response.pop('createdDate',None) # createdDate is hard to match against, remove it
|
||||||
|
response['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
|
response.should.equal({
|
||||||
|
'id': deployment_id,
|
||||||
|
'ResponseMetadata': {'HTTPStatusCode': 200},
|
||||||
|
'description' : ''
|
||||||
|
})
|
||||||
|
|
||||||
|
response = client.create_deployment(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=stage_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
deployment_id2 = response['id']
|
||||||
|
|
||||||
|
|
||||||
|
response = client.get_deployments(
|
||||||
|
restApiId=api_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
response['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
|
|
||||||
|
response['items'][0].pop('createdDate')
|
||||||
|
response['items'][1].pop('createdDate')
|
||||||
|
response['items'][0]['id'].should.match(r"{0}|{1}".format(deployment_id2,deployment_id))
|
||||||
|
response['items'][1]['id'].should.match(r"{0}|{1}".format(deployment_id2,deployment_id))
|
||||||
|
|
||||||
|
|
||||||
|
new_stage_name = 'current'
|
||||||
|
response = client.create_stage(restApiId=api_id,stageName=new_stage_name,deploymentId=deployment_id2)
|
||||||
|
|
||||||
|
response['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
|
|
||||||
|
response.should.equal({
|
||||||
|
'stageName':new_stage_name,
|
||||||
|
'deploymentId':deployment_id2,
|
||||||
|
'methodSettings':{},
|
||||||
|
'variables':{},
|
||||||
|
'ResponseMetadata': {'HTTPStatusCode': 200},
|
||||||
|
'description':'',
|
||||||
|
'cacheClusterEnabled':False
|
||||||
|
})
|
||||||
|
|
||||||
|
stage = client.get_stage(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=new_stage_name
|
||||||
|
)
|
||||||
|
stage['stageName'].should.equal(new_stage_name)
|
||||||
|
stage['deploymentId'].should.equal(deployment_id2)
|
||||||
|
|
||||||
|
new_stage_name_with_vars = 'stage_with_vars'
|
||||||
|
response = client.create_stage(restApiId=api_id,stageName=new_stage_name_with_vars,deploymentId=deployment_id2,variables={
|
||||||
|
"env" : "dev"
|
||||||
|
})
|
||||||
|
|
||||||
|
response['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
|
|
||||||
|
response.should.equal({
|
||||||
|
'stageName':new_stage_name_with_vars,
|
||||||
|
'deploymentId':deployment_id2,
|
||||||
|
'methodSettings':{},
|
||||||
|
'variables':{ "env" : "dev" },
|
||||||
|
'ResponseMetadata': {'HTTPStatusCode': 200},
|
||||||
|
'description':'',
|
||||||
|
'cacheClusterEnabled': False
|
||||||
|
})
|
||||||
|
|
||||||
|
stage = client.get_stage(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=new_stage_name_with_vars
|
||||||
|
)
|
||||||
|
stage['stageName'].should.equal(new_stage_name_with_vars)
|
||||||
|
stage['deploymentId'].should.equal(deployment_id2)
|
||||||
|
stage['variables'].should.have.key('env').which.should.match("dev")
|
||||||
|
|
||||||
|
new_stage_name = 'stage_with_vars_and_cache_settings'
|
||||||
|
response = client.create_stage(restApiId=api_id,stageName=new_stage_name,deploymentId=deployment_id2,variables={
|
||||||
|
"env" : "dev"
|
||||||
|
}, cacheClusterEnabled=True,description="hello moto")
|
||||||
|
|
||||||
|
response['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
|
|
||||||
|
response.should.equal({
|
||||||
|
'stageName':new_stage_name,
|
||||||
|
'deploymentId':deployment_id2,
|
||||||
|
'methodSettings':{},
|
||||||
|
'variables':{ "env" : "dev" },
|
||||||
|
'ResponseMetadata': {'HTTPStatusCode': 200},
|
||||||
|
'description':'hello moto',
|
||||||
|
'cacheClusterEnabled': True,
|
||||||
|
'cacheClusterSize' : "0.5"
|
||||||
|
})
|
||||||
|
|
||||||
|
stage = client.get_stage(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=new_stage_name
|
||||||
|
)
|
||||||
|
|
||||||
|
stage['cacheClusterSize'].should.equal("0.5")
|
||||||
|
|
||||||
|
new_stage_name = 'stage_with_vars_and_cache_settings_and_size'
|
||||||
|
response = client.create_stage(restApiId=api_id,stageName=new_stage_name,deploymentId=deployment_id2,variables={
|
||||||
|
"env" : "dev"
|
||||||
|
}, cacheClusterEnabled=True,cacheClusterSize="1.6",description="hello moto")
|
||||||
|
|
||||||
|
response['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
|
|
||||||
|
response.should.equal({
|
||||||
|
'stageName':new_stage_name,
|
||||||
|
'deploymentId':deployment_id2,
|
||||||
|
'methodSettings':{},
|
||||||
|
'variables':{ "env" : "dev" },
|
||||||
|
'ResponseMetadata': {'HTTPStatusCode': 200},
|
||||||
|
'description':'hello moto',
|
||||||
|
'cacheClusterEnabled': True,
|
||||||
|
'cacheClusterSize' : "1.6"
|
||||||
|
})
|
||||||
|
|
||||||
|
stage = client.get_stage(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=new_stage_name
|
||||||
|
)
|
||||||
|
stage['stageName'].should.equal(new_stage_name)
|
||||||
|
stage['deploymentId'].should.equal(deployment_id2)
|
||||||
|
stage['variables'].should.have.key('env').which.should.match("dev")
|
||||||
|
stage['cacheClusterSize'].should.equal("1.6")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@mock_apigateway
|
@mock_apigateway
|
||||||
def test_deployment():
|
def test_deployment():
|
||||||
client = boto3.client('apigateway', region_name='us-west-2')
|
client = boto3.client('apigateway', region_name='us-west-2')
|
||||||
@ -489,17 +805,21 @@ def test_deployment():
|
|||||||
restApiId=api_id,
|
restApiId=api_id,
|
||||||
deploymentId=deployment_id,
|
deploymentId=deployment_id,
|
||||||
)
|
)
|
||||||
|
response.pop('createdDate',None) # createdDate is hard to match against, remove it
|
||||||
response['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
response['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
response.should.equal({
|
response.should.equal({
|
||||||
'id': deployment_id,
|
'id': deployment_id,
|
||||||
'ResponseMetadata': {'HTTPStatusCode': 200}
|
'ResponseMetadata': {'HTTPStatusCode': 200},
|
||||||
|
'description' : ''
|
||||||
})
|
})
|
||||||
|
|
||||||
response = client.get_deployments(
|
response = client.get_deployments(
|
||||||
restApiId=api_id,
|
restApiId=api_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
response['items'][0].pop('createdDate')
|
||||||
response['items'].should.equal([
|
response['items'].should.equal([
|
||||||
{'id': deployment_id}
|
{'id': deployment_id, 'description': ''}
|
||||||
])
|
])
|
||||||
|
|
||||||
response = client.delete_deployment(
|
response = client.delete_deployment(
|
||||||
@ -527,7 +847,7 @@ def test_deployment():
|
|||||||
patchOperations=[
|
patchOperations=[
|
||||||
{
|
{
|
||||||
'op': 'replace',
|
'op': 'replace',
|
||||||
'path': 'description',
|
'path': '/description',
|
||||||
'value': '_new_description_'
|
'value': '_new_description_'
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user