Run black on moto & test directories.

This commit is contained in:
Asher Foa 2019-10-31 08:44:26 -07:00
commit 96e5b1993d
507 changed files with 52541 additions and 47814 deletions

View file

@ -17,39 +17,33 @@ STAGE_URL = "https://{api_id}.execute-api.{region_name}.amazonaws.com/{stage_nam
class Deployment(BaseModel, dict):
def __init__(self, deployment_id, name, description=""):
super(Deployment, self).__init__()
self['id'] = deployment_id
self['stageName'] = name
self['description'] = description
self['createdDate'] = int(time.time())
self["id"] = deployment_id
self["stageName"] = name
self["description"] = description
self["createdDate"] = int(time.time())
class IntegrationResponse(BaseModel, dict):
def __init__(self, status_code, selection_pattern=None):
self['responseTemplates'] = {"application/json": None}
self['statusCode'] = status_code
self["responseTemplates"] = {"application/json": None}
self["statusCode"] = status_code
if selection_pattern:
self['selectionPattern'] = selection_pattern
self["selectionPattern"] = selection_pattern
class Integration(BaseModel, dict):
def __init__(self, integration_type, uri, http_method, request_templates=None):
super(Integration, self).__init__()
self['type'] = integration_type
self['uri'] = uri
self['httpMethod'] = http_method
self['requestTemplates'] = request_templates
self["integrationResponses"] = {
"200": IntegrationResponse(200)
}
self["type"] = integration_type
self["uri"] = uri
self["httpMethod"] = http_method
self["requestTemplates"] = request_templates
self["integrationResponses"] = {"200": IntegrationResponse(200)}
def create_integration_response(self, status_code, selection_pattern):
integration_response = IntegrationResponse(
status_code, selection_pattern)
integration_response = IntegrationResponse(status_code, selection_pattern)
self["integrationResponses"][status_code] = integration_response
return integration_response
@ -61,25 +55,25 @@ class Integration(BaseModel, dict):
class MethodResponse(BaseModel, dict):
def __init__(self, status_code):
super(MethodResponse, self).__init__()
self['statusCode'] = status_code
self["statusCode"] = status_code
class Method(BaseModel, dict):
def __init__(self, method_type, authorization_type):
super(Method, self).__init__()
self.update(dict(
httpMethod=method_type,
authorizationType=authorization_type,
authorizerId=None,
apiKeyRequired=None,
requestParameters=None,
requestModels=None,
methodIntegration=None,
))
self.update(
dict(
httpMethod=method_type,
authorizationType=authorization_type,
authorizerId=None,
apiKeyRequired=None,
requestParameters=None,
requestModels=None,
methodIntegration=None,
)
)
self.method_responses = {}
def create_response(self, response_code):
@ -95,16 +89,13 @@ class Method(BaseModel, dict):
class Resource(BaseModel):
def __init__(self, id, region_name, api_id, path_part, parent_id):
self.id = id
self.region_name = region_name
self.api_id = api_id
self.path_part = path_part
self.parent_id = parent_id
self.resource_methods = {
'GET': {}
}
self.resource_methods = {"GET": {}}
def to_dict(self):
response = {
@ -113,8 +104,8 @@ class Resource(BaseModel):
"resourceMethods": self.resource_methods,
}
if self.parent_id:
response['parentId'] = self.parent_id
response['pathPart'] = self.path_part
response["parentId"] = self.parent_id
response["pathPart"] = self.path_part
return response
def get_path(self):
@ -125,102 +116,112 @@ class Resource(BaseModel):
backend = apigateway_backends[self.region_name]
parent = backend.get_resource(self.api_id, self.parent_id)
parent_path = parent.get_path()
if parent_path != '/': # Root parent
parent_path += '/'
if parent_path != "/": # Root parent
parent_path += "/"
return parent_path
else:
return ''
return ""
def get_response(self, request):
integration = self.get_integration(request.method)
integration_type = integration['type']
integration_type = integration["type"]
if integration_type == 'HTTP':
uri = integration['uri']
requests_func = getattr(requests, integration[
'httpMethod'].lower())
if integration_type == "HTTP":
uri = integration["uri"]
requests_func = getattr(requests, integration["httpMethod"].lower())
response = requests_func(uri)
else:
raise NotImplementedError(
"The {0} type has not been implemented".format(integration_type))
"The {0} type has not been implemented".format(integration_type)
)
return response.status_code, response.text
def add_method(self, method_type, authorization_type):
method = Method(method_type=method_type,
authorization_type=authorization_type)
method = Method(method_type=method_type, authorization_type=authorization_type)
self.resource_methods[method_type] = method
return method
def get_method(self, method_type):
return self.resource_methods[method_type]
def add_integration(self, method_type, integration_type, uri, request_templates=None):
def add_integration(
self, method_type, integration_type, uri, request_templates=None
):
integration = Integration(
integration_type, uri, method_type, request_templates=request_templates)
self.resource_methods[method_type]['methodIntegration'] = integration
integration_type, uri, method_type, request_templates=request_templates
)
self.resource_methods[method_type]["methodIntegration"] = integration
return integration
def get_integration(self, method_type):
return self.resource_methods[method_type]['methodIntegration']
return self.resource_methods[method_type]["methodIntegration"]
def delete_integration(self, method_type):
return self.resource_methods[method_type].pop('methodIntegration')
return self.resource_methods[method_type].pop("methodIntegration")
class Stage(BaseModel, dict):
def __init__(self, name=None, deployment_id=None, variables=None,
description='', cacheClusterEnabled=False, cacheClusterSize=None):
def __init__(
self,
name=None,
deployment_id=None,
variables=None,
description="",
cacheClusterEnabled=False,
cacheClusterSize=None,
):
super(Stage, self).__init__()
if variables is None:
variables = {}
self['stageName'] = name
self['deploymentId'] = deployment_id
self['methodSettings'] = {}
self['variables'] = variables
self['description'] = description
self['cacheClusterEnabled'] = cacheClusterEnabled
if self['cacheClusterEnabled']:
self['cacheClusterSize'] = str(0.5)
self["stageName"] = name
self["deploymentId"] = deployment_id
self["methodSettings"] = {}
self["variables"] = variables
self["description"] = description
self["cacheClusterEnabled"] = cacheClusterEnabled
if self["cacheClusterEnabled"]:
self["cacheClusterSize"] = str(0.5)
if cacheClusterSize is not None:
self['cacheClusterSize'] = str(cacheClusterSize)
self["cacheClusterSize"] = str(cacheClusterSize)
def apply_operations(self, patch_operations):
for op in patch_operations:
if 'variables/' in op['path']:
if "variables/" in op["path"]:
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':
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')
split_path = op['path'].split('/', 3)
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'])
"/".join(split_path[1:3]), split_path[3], op["value"]
)
else:
raise Exception(
'Patch operation "%s" not implemented' % op['op'])
raise Exception('Patch operation "%s" not implemented' % op["op"])
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)
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 {
@ -232,21 +233,21 @@ class Stage(BaseModel, dict):
"cacheDataEncrypted": True,
"cachingEnabled": False,
"throttlingBurstLimit": 2000,
"requireAuthorizationForCacheControl": True
"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'
"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:
@ -259,26 +260,26 @@ class Stage(BaseModel, dict):
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'
"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':
if type_value == "bool":
return self._str2bool(val)
elif type_value == 'int':
elif type_value == "int":
return int(val)
elif type_value == 'float':
elif type_value == "float":
return float(val)
else:
return str(val)
@ -286,44 +287,55 @@ class Stage(BaseModel, dict):
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']
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'])
raise Exception('Patch operation "%s" not implemented' % op["op"])
class ApiKey(BaseModel, dict):
def __init__(self, name=None, description=None, enabled=True,
generateDistinctId=False, value=None, stageKeys=None, tags=None, customerId=None):
def __init__(
self,
name=None,
description=None,
enabled=True,
generateDistinctId=False,
value=None,
stageKeys=None,
tags=None,
customerId=None,
):
super(ApiKey, self).__init__()
self['id'] = create_id()
self['value'] = value if value else ''.join(random.sample(string.ascii_letters + string.digits, 40))
self['name'] = name
self['customerId'] = customerId
self['description'] = description
self['enabled'] = enabled
self['createdDate'] = self['lastUpdatedDate'] = int(time.time())
self['stageKeys'] = stageKeys
self['tags'] = tags
self["id"] = create_id()
self["value"] = (
value
if value
else "".join(random.sample(string.ascii_letters + string.digits, 40))
)
self["name"] = name
self["customerId"] = customerId
self["description"] = description
self["enabled"] = enabled
self["createdDate"] = self["lastUpdatedDate"] = int(time.time())
self["stageKeys"] = stageKeys
self["tags"] = tags
def update_operations(self, patch_operations):
for op in patch_operations:
if op['op'] == 'replace':
if '/name' in op['path']:
self['name'] = op['value']
elif '/customerId' in op['path']:
self['customerId'] = op['value']
elif '/description' in op['path']:
self['description'] = op['value']
elif '/enabled' in op['path']:
self['enabled'] = self._str2bool(op['value'])
if op["op"] == "replace":
if "/name" in op["path"]:
self["name"] = op["value"]
elif "/customerId" in op["path"]:
self["customerId"] = op["value"]
elif "/description" in op["path"]:
self["description"] = op["value"]
elif "/enabled" in op["path"]:
self["enabled"] = self._str2bool(op["value"])
else:
raise Exception(
'Patch operation "%s" not implemented' % op['op'])
raise Exception('Patch operation "%s" not implemented' % op["op"])
return self
def _str2bool(self, v):
@ -331,31 +343,35 @@ class ApiKey(BaseModel, dict):
class UsagePlan(BaseModel, dict):
def __init__(self, name=None, description=None, apiStages=None,
throttle=None, quota=None, tags=None):
def __init__(
self,
name=None,
description=None,
apiStages=None,
throttle=None,
quota=None,
tags=None,
):
super(UsagePlan, self).__init__()
self['id'] = create_id()
self['name'] = name
self['description'] = description
self['apiStages'] = apiStages if apiStages else []
self['throttle'] = throttle
self['quota'] = quota
self['tags'] = tags
self["id"] = create_id()
self["name"] = name
self["description"] = description
self["apiStages"] = apiStages if apiStages else []
self["throttle"] = throttle
self["quota"] = quota
self["tags"] = tags
class UsagePlanKey(BaseModel, dict):
def __init__(self, id, type, name, value):
super(UsagePlanKey, self).__init__()
self['id'] = id
self['name'] = name
self['type'] = type
self['value'] = value
self["id"] = id
self["name"] = name
self["type"] = type
self["value"] = value
class RestAPI(BaseModel):
def __init__(self, id, region_name, name, description):
self.id = id
self.region_name = region_name
@ -367,7 +383,7 @@ class RestAPI(BaseModel):
self.stages = {}
self.resources = {}
self.add_child('/') # Add default child
self.add_child("/") # Add default child
def __repr__(self):
return str(self.id)
@ -382,8 +398,13 @@ class RestAPI(BaseModel):
def add_child(self, path, parent_id=None):
child_id = create_id()
child = Resource(id=child_id, region_name=self.region_name,
api_id=self.id, path_part=path, parent_id=parent_id)
child = Resource(
id=child_id,
region_name=self.region_name,
api_id=self.id,
path_part=path,
parent_id=parent_id,
)
self.resources[child_id] = child
return child
@ -395,36 +416,53 @@ class RestAPI(BaseModel):
def resource_callback(self, request):
path = path_url(request.url)
path_after_stage_name = '/'.join(path.split("/")[2:])
path_after_stage_name = "/".join(path.split("/")[2:])
if not path_after_stage_name:
path_after_stage_name = '/'
path_after_stage_name = "/"
resource = self.get_resource_for_path(path_after_stage_name)
status_code, response = resource.get_response(request)
return status_code, {}, response
def update_integration_mocks(self, stage_name):
stage_url_lower = STAGE_URL.format(api_id=self.id.lower(),
region_name=self.region_name, stage_name=stage_name)
stage_url_upper = STAGE_URL.format(api_id=self.id.upper(),
region_name=self.region_name, stage_name=stage_name)
stage_url_lower = STAGE_URL.format(
api_id=self.id.lower(), region_name=self.region_name, stage_name=stage_name
)
stage_url_upper = STAGE_URL.format(
api_id=self.id.upper(), region_name=self.region_name, stage_name=stage_name
)
for url in [stage_url_lower, stage_url_upper]:
responses._default_mock._matches.insert(0,
responses._default_mock._matches.insert(
0,
responses.CallbackResponse(
url=url,
method=responses.GET,
callback=self.resource_callback,
content_type="text/plain",
match_querystring=False,
)
),
)
def create_stage(self, name, deployment_id, variables=None, description='', cacheClusterEnabled=None, cacheClusterSize=None):
def create_stage(
self,
name,
deployment_id,
variables=None,
description="",
cacheClusterEnabled=None,
cacheClusterSize=None,
):
if variables is None:
variables = {}
stage = Stage(name=name, deployment_id=deployment_id, variables=variables,
description=description, cacheClusterSize=cacheClusterSize, cacheClusterEnabled=cacheClusterEnabled)
stage = Stage(
name=name,
deployment_id=deployment_id,
variables=variables,
description=description,
cacheClusterSize=cacheClusterSize,
cacheClusterEnabled=cacheClusterEnabled,
)
self.stages[name] = stage
self.update_integration_mocks(name)
return stage
@ -436,7 +474,8 @@ class RestAPI(BaseModel):
deployment = Deployment(deployment_id, name, description)
self.deployments[deployment_id] = deployment
self.stages[name] = Stage(
name=name, deployment_id=deployment_id, variables=stage_variables)
name=name, deployment_id=deployment_id, variables=stage_variables
)
self.update_integration_mocks(name)
return deployment
@ -455,7 +494,6 @@ class RestAPI(BaseModel):
class APIGatewayBackend(BaseBackend):
def __init__(self, region_name):
super(APIGatewayBackend, self).__init__()
self.apis = {}
@ -497,10 +535,7 @@ class APIGatewayBackend(BaseBackend):
def create_resource(self, function_id, parent_resource_id, path_part):
api = self.get_rest_api(function_id)
child = api.add_child(
path=path_part,
parent_id=parent_resource_id,
)
child = api.add_child(path=path_part, parent_id=parent_resource_id)
return child
def delete_resource(self, function_id, resource_id):
@ -529,13 +564,27 @@ class APIGatewayBackend(BaseBackend):
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):
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)
api.create_stage(
stage_name,
deploymentId,
variables=variables,
description=description,
cacheClusterEnabled=cacheClusterEnabled,
cacheClusterSize=cacheClusterSize,
)
return api.stages.get(stage_name)
def update_stage(self, function_id, stage_name, patch_operations):
@ -550,21 +599,33 @@ class APIGatewayBackend(BaseBackend):
method_response = method.get_response(response_code)
return method_response
def create_method_response(self, function_id, resource_id, method_type, response_code):
def create_method_response(
self, function_id, resource_id, method_type, response_code
):
method = self.get_method(function_id, resource_id, method_type)
method_response = method.create_response(response_code)
return method_response
def delete_method_response(self, function_id, resource_id, method_type, response_code):
def delete_method_response(
self, function_id, resource_id, method_type, response_code
):
method = self.get_method(function_id, resource_id, method_type)
method_response = method.delete_response(response_code)
return method_response
def create_integration(self, function_id, resource_id, method_type, integration_type, uri,
request_templates=None):
def create_integration(
self,
function_id,
resource_id,
method_type,
integration_type,
uri,
request_templates=None,
):
resource = self.get_resource(function_id, resource_id)
integration = resource.add_integration(method_type, integration_type, uri,
request_templates=request_templates)
integration = resource.add_integration(
method_type, integration_type, uri, request_templates=request_templates
)
return integration
def get_integration(self, function_id, resource_id, method_type):
@ -575,28 +636,32 @@ class APIGatewayBackend(BaseBackend):
resource = self.get_resource(function_id, resource_id)
return resource.delete_integration(method_type)
def create_integration_response(self, function_id, resource_id, method_type, status_code, selection_pattern):
integration = self.get_integration(
function_id, resource_id, method_type)
def create_integration_response(
self, function_id, resource_id, method_type, status_code, selection_pattern
):
integration = self.get_integration(function_id, resource_id, method_type)
integration_response = integration.create_integration_response(
status_code, selection_pattern)
status_code, selection_pattern
)
return integration_response
def get_integration_response(self, function_id, resource_id, method_type, status_code):
integration = self.get_integration(
function_id, resource_id, method_type)
integration_response = integration.get_integration_response(
status_code)
def get_integration_response(
self, function_id, resource_id, method_type, status_code
):
integration = self.get_integration(function_id, resource_id, method_type)
integration_response = integration.get_integration_response(status_code)
return integration_response
def delete_integration_response(self, function_id, resource_id, method_type, status_code):
integration = self.get_integration(
function_id, resource_id, method_type)
integration_response = integration.delete_integration_response(
status_code)
def delete_integration_response(
self, function_id, resource_id, method_type, status_code
):
integration = self.get_integration(function_id, resource_id, method_type)
integration_response = integration.delete_integration_response(status_code)
return integration_response
def create_deployment(self, function_id, name, description="", stage_variables=None):
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)
@ -617,7 +682,7 @@ class APIGatewayBackend(BaseBackend):
def create_apikey(self, payload):
key = ApiKey(**payload)
self.keys[key['id']] = key
self.keys[key["id"]] = key
return key
def get_apikeys(self):
@ -636,7 +701,7 @@ class APIGatewayBackend(BaseBackend):
def create_usage_plan(self, payload):
plan = UsagePlan(**payload)
self.usage_plans[plan['id']] = plan
self.usage_plans[plan["id"]] = plan
return plan
def get_usage_plans(self, api_key_id=None):
@ -645,7 +710,7 @@ class APIGatewayBackend(BaseBackend):
plans = [
plan
for plan in plans
if self.usage_plan_keys.get(plan['id'], {}).get(api_key_id, False)
if self.usage_plan_keys.get(plan["id"], {}).get(api_key_id, False)
]
return plans
@ -666,8 +731,13 @@ class APIGatewayBackend(BaseBackend):
api_key = self.keys[key_id]
usage_plan_key = UsagePlanKey(id=key_id, type=payload["keyType"], name=api_key["name"], value=api_key["value"])
self.usage_plan_keys[usage_plan_id][usage_plan_key['id']] = usage_plan_key
usage_plan_key = UsagePlanKey(
id=key_id,
type=payload["keyType"],
name=api_key["name"],
value=api_key["value"],
)
self.usage_plan_keys[usage_plan_id][usage_plan_key["id"]] = usage_plan_key
return usage_plan_key
def get_usage_plan_keys(self, usage_plan_id):
@ -685,5 +755,5 @@ class APIGatewayBackend(BaseBackend):
apigateway_backends = {}
for region_name in Session().get_available_regions('apigateway'):
for region_name in Session().get_available_regions("apigateway"):
apigateway_backends[region_name] = APIGatewayBackend(region_name)