Merge pull request #2531 from bblommers/feature/2521
API Gateway - Implement Stage deletion
This commit is contained in:
commit
740dedc664
@ -2,6 +2,89 @@ from __future__ import unicode_literals
|
|||||||
from moto.core.exceptions import RESTError
|
from moto.core.exceptions import RESTError
|
||||||
|
|
||||||
|
|
||||||
|
class BadRequestException(RESTError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AwsProxyNotAllowed(BadRequestException):
|
||||||
|
def __init__(self):
|
||||||
|
super(AwsProxyNotAllowed, self).__init__(
|
||||||
|
"BadRequestException",
|
||||||
|
"Integrations of type 'AWS_PROXY' currently only supports Lambda function and Firehose stream invocations.",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CrossAccountNotAllowed(RESTError):
|
||||||
|
def __init__(self):
|
||||||
|
super(CrossAccountNotAllowed, self).__init__(
|
||||||
|
"AccessDeniedException", "Cross-account pass role is not allowed."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RoleNotSpecified(BadRequestException):
|
||||||
|
def __init__(self):
|
||||||
|
super(RoleNotSpecified, self).__init__(
|
||||||
|
"BadRequestException", "Role ARN must be specified for AWS integrations"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class IntegrationMethodNotDefined(BadRequestException):
|
||||||
|
def __init__(self):
|
||||||
|
super(IntegrationMethodNotDefined, self).__init__(
|
||||||
|
"BadRequestException", "Enumeration value for HttpMethod must be non-empty"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidResourcePathException(BadRequestException):
|
||||||
|
def __init__(self):
|
||||||
|
super(InvalidResourcePathException, self).__init__(
|
||||||
|
"BadRequestException",
|
||||||
|
"Resource's path part only allow a-zA-Z0-9._- and curly braces at the beginning and the end.",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidHttpEndpoint(BadRequestException):
|
||||||
|
def __init__(self):
|
||||||
|
super(InvalidHttpEndpoint, self).__init__(
|
||||||
|
"BadRequestException", "Invalid HTTP endpoint specified for URI"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidArn(BadRequestException):
|
||||||
|
def __init__(self):
|
||||||
|
super(InvalidArn, self).__init__(
|
||||||
|
"BadRequestException", "Invalid ARN specified in the request"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidIntegrationArn(BadRequestException):
|
||||||
|
def __init__(self):
|
||||||
|
super(InvalidIntegrationArn, self).__init__(
|
||||||
|
"BadRequestException", "AWS ARN for integration must contain path or action"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidRequestInput(BadRequestException):
|
||||||
|
def __init__(self):
|
||||||
|
super(InvalidRequestInput, self).__init__(
|
||||||
|
"BadRequestException", "Invalid request input"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NoIntegrationDefined(BadRequestException):
|
||||||
|
def __init__(self):
|
||||||
|
super(NoIntegrationDefined, self).__init__(
|
||||||
|
"BadRequestException", "No integration defined for method"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NoMethodDefined(BadRequestException):
|
||||||
|
def __init__(self):
|
||||||
|
super(NoMethodDefined, self).__init__(
|
||||||
|
"BadRequestException", "The REST API doesn't contain any methods"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class StageNotFoundException(RESTError):
|
class StageNotFoundException(RESTError):
|
||||||
code = 404
|
code = 404
|
||||||
|
|
||||||
|
@ -3,15 +3,36 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
import re
|
||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from boto3.session import Session
|
from boto3.session import Session
|
||||||
|
|
||||||
|
try:
|
||||||
|
from urlparse import urlparse
|
||||||
|
except ImportError:
|
||||||
|
from urllib.parse import urlparse
|
||||||
import responses
|
import responses
|
||||||
from moto.core import BaseBackend, BaseModel
|
from moto.core import BaseBackend, BaseModel
|
||||||
from .utils import create_id
|
from .utils import create_id
|
||||||
from moto.core.utils import path_url
|
from moto.core.utils import path_url
|
||||||
from .exceptions import StageNotFoundException, ApiKeyNotFoundException
|
from moto.sts.models import ACCOUNT_ID
|
||||||
|
from .exceptions import (
|
||||||
|
ApiKeyNotFoundException,
|
||||||
|
AwsProxyNotAllowed,
|
||||||
|
CrossAccountNotAllowed,
|
||||||
|
IntegrationMethodNotDefined,
|
||||||
|
InvalidArn,
|
||||||
|
InvalidIntegrationArn,
|
||||||
|
InvalidHttpEndpoint,
|
||||||
|
InvalidResourcePathException,
|
||||||
|
InvalidRequestInput,
|
||||||
|
StageNotFoundException,
|
||||||
|
RoleNotSpecified,
|
||||||
|
NoIntegrationDefined,
|
||||||
|
NoMethodDefined,
|
||||||
|
)
|
||||||
|
|
||||||
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}"
|
||||||
|
|
||||||
@ -534,6 +555,8 @@ class APIGatewayBackend(BaseBackend):
|
|||||||
return resource
|
return resource
|
||||||
|
|
||||||
def create_resource(self, function_id, parent_resource_id, path_part):
|
def create_resource(self, function_id, parent_resource_id, path_part):
|
||||||
|
if not re.match("^\\{?[a-zA-Z0-9._-]+\\}?$", path_part):
|
||||||
|
raise InvalidResourcePathException()
|
||||||
api = self.get_rest_api(function_id)
|
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
|
return child
|
||||||
@ -594,6 +617,10 @@ class APIGatewayBackend(BaseBackend):
|
|||||||
stage = api.stages[stage_name] = Stage()
|
stage = api.stages[stage_name] = Stage()
|
||||||
return stage.apply_operations(patch_operations)
|
return stage.apply_operations(patch_operations)
|
||||||
|
|
||||||
|
def delete_stage(self, function_id, stage_name):
|
||||||
|
api = self.get_rest_api(function_id)
|
||||||
|
del api.stages[stage_name]
|
||||||
|
|
||||||
def get_method_response(self, function_id, resource_id, method_type, response_code):
|
def get_method_response(self, function_id, resource_id, method_type, response_code):
|
||||||
method = self.get_method(function_id, resource_id, method_type)
|
method = self.get_method(function_id, resource_id, method_type)
|
||||||
method_response = method.get_response(response_code)
|
method_response = method.get_response(response_code)
|
||||||
@ -620,9 +647,40 @@ class APIGatewayBackend(BaseBackend):
|
|||||||
method_type,
|
method_type,
|
||||||
integration_type,
|
integration_type,
|
||||||
uri,
|
uri,
|
||||||
|
integration_method=None,
|
||||||
|
credentials=None,
|
||||||
request_templates=None,
|
request_templates=None,
|
||||||
):
|
):
|
||||||
resource = self.get_resource(function_id, resource_id)
|
resource = self.get_resource(function_id, resource_id)
|
||||||
|
if credentials and not re.match(
|
||||||
|
"^arn:aws:iam::" + str(ACCOUNT_ID), credentials
|
||||||
|
):
|
||||||
|
raise CrossAccountNotAllowed()
|
||||||
|
if not integration_method and integration_type in [
|
||||||
|
"HTTP",
|
||||||
|
"HTTP_PROXY",
|
||||||
|
"AWS",
|
||||||
|
"AWS_PROXY",
|
||||||
|
]:
|
||||||
|
raise IntegrationMethodNotDefined()
|
||||||
|
if integration_type in ["AWS_PROXY"] and re.match(
|
||||||
|
"^arn:aws:apigateway:[a-zA-Z0-9-]+:s3", uri
|
||||||
|
):
|
||||||
|
raise AwsProxyNotAllowed()
|
||||||
|
if (
|
||||||
|
integration_type in ["AWS"]
|
||||||
|
and re.match("^arn:aws:apigateway:[a-zA-Z0-9-]+:s3", uri)
|
||||||
|
and not credentials
|
||||||
|
):
|
||||||
|
raise RoleNotSpecified()
|
||||||
|
if integration_type in ["HTTP", "HTTP_PROXY"] and not self._uri_validator(uri):
|
||||||
|
raise InvalidHttpEndpoint()
|
||||||
|
if integration_type in ["AWS", "AWS_PROXY"] and not re.match("^arn:aws:", uri):
|
||||||
|
raise InvalidArn()
|
||||||
|
if integration_type in ["AWS", "AWS_PROXY"] and not re.match(
|
||||||
|
"^arn:aws:apigateway:[a-zA-Z0-9-]+:[a-zA-Z0-9-]+:(path|action)/", uri
|
||||||
|
):
|
||||||
|
raise InvalidIntegrationArn()
|
||||||
integration = resource.add_integration(
|
integration = resource.add_integration(
|
||||||
method_type, integration_type, uri, request_templates=request_templates
|
method_type, integration_type, uri, request_templates=request_templates
|
||||||
)
|
)
|
||||||
@ -637,8 +695,16 @@ class APIGatewayBackend(BaseBackend):
|
|||||||
return resource.delete_integration(method_type)
|
return resource.delete_integration(method_type)
|
||||||
|
|
||||||
def create_integration_response(
|
def create_integration_response(
|
||||||
self, function_id, resource_id, method_type, status_code, selection_pattern
|
self,
|
||||||
|
function_id,
|
||||||
|
resource_id,
|
||||||
|
method_type,
|
||||||
|
status_code,
|
||||||
|
selection_pattern,
|
||||||
|
response_templates,
|
||||||
):
|
):
|
||||||
|
if response_templates is None:
|
||||||
|
raise InvalidRequestInput()
|
||||||
integration = self.get_integration(function_id, resource_id, method_type)
|
integration = self.get_integration(function_id, resource_id, method_type)
|
||||||
integration_response = integration.create_integration_response(
|
integration_response = integration.create_integration_response(
|
||||||
status_code, selection_pattern
|
status_code, selection_pattern
|
||||||
@ -665,6 +731,18 @@ class APIGatewayBackend(BaseBackend):
|
|||||||
if stage_variables is None:
|
if stage_variables is None:
|
||||||
stage_variables = {}
|
stage_variables = {}
|
||||||
api = self.get_rest_api(function_id)
|
api = self.get_rest_api(function_id)
|
||||||
|
methods = [
|
||||||
|
list(res.resource_methods.values())
|
||||||
|
for res in self.list_resources(function_id)
|
||||||
|
][0]
|
||||||
|
if not any(methods):
|
||||||
|
raise NoMethodDefined()
|
||||||
|
method_integrations = [
|
||||||
|
method["methodIntegration"] if "methodIntegration" in method else None
|
||||||
|
for method in methods
|
||||||
|
]
|
||||||
|
if not any(method_integrations):
|
||||||
|
raise NoIntegrationDefined()
|
||||||
deployment = api.create_deployment(name, description, stage_variables)
|
deployment = api.create_deployment(name, description, stage_variables)
|
||||||
return deployment
|
return deployment
|
||||||
|
|
||||||
@ -753,6 +831,13 @@ class APIGatewayBackend(BaseBackend):
|
|||||||
self.usage_plan_keys[usage_plan_id].pop(key_id)
|
self.usage_plan_keys[usage_plan_id].pop(key_id)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
def _uri_validator(self, uri):
|
||||||
|
try:
|
||||||
|
result = urlparse(uri)
|
||||||
|
return all([result.scheme, result.netloc, result.path])
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
apigateway_backends = {}
|
apigateway_backends = {}
|
||||||
for region_name in Session().get_available_regions("apigateway"):
|
for region_name in Session().get_available_regions("apigateway"):
|
||||||
|
@ -4,12 +4,24 @@ 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, ApiKeyNotFoundException
|
from .exceptions import (
|
||||||
|
ApiKeyNotFoundException,
|
||||||
|
BadRequestException,
|
||||||
|
CrossAccountNotAllowed,
|
||||||
|
StageNotFoundException,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class APIGatewayResponse(BaseResponse):
|
class APIGatewayResponse(BaseResponse):
|
||||||
|
def error(self, type_, message, status=400):
|
||||||
|
return (
|
||||||
|
status,
|
||||||
|
self.response_headers,
|
||||||
|
json.dumps({"__type": type_, "message": message}),
|
||||||
|
)
|
||||||
|
|
||||||
def _get_param(self, key):
|
def _get_param(self, key):
|
||||||
return json.loads(self.body).get(key)
|
return json.loads(self.body).get(key) if self.body else None
|
||||||
|
|
||||||
def _get_param_with_default_value(self, key, default):
|
def _get_param_with_default_value(self, key, default):
|
||||||
jsonbody = json.loads(self.body)
|
jsonbody = json.loads(self.body)
|
||||||
@ -63,14 +75,21 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
function_id = self.path.replace("/restapis/", "", 1).split("/")[0]
|
function_id = self.path.replace("/restapis/", "", 1).split("/")[0]
|
||||||
resource_id = self.path.split("/")[-1]
|
resource_id = self.path.split("/")[-1]
|
||||||
|
|
||||||
|
try:
|
||||||
if self.method == "GET":
|
if self.method == "GET":
|
||||||
resource = self.backend.get_resource(function_id, resource_id)
|
resource = self.backend.get_resource(function_id, resource_id)
|
||||||
elif self.method == "POST":
|
elif self.method == "POST":
|
||||||
path_part = self._get_param("pathPart")
|
path_part = self._get_param("pathPart")
|
||||||
resource = self.backend.create_resource(function_id, resource_id, path_part)
|
resource = self.backend.create_resource(
|
||||||
|
function_id, resource_id, path_part
|
||||||
|
)
|
||||||
elif self.method == "DELETE":
|
elif self.method == "DELETE":
|
||||||
resource = self.backend.delete_resource(function_id, resource_id)
|
resource = self.backend.delete_resource(function_id, resource_id)
|
||||||
return 200, {}, json.dumps(resource.to_dict())
|
return 200, {}, json.dumps(resource.to_dict())
|
||||||
|
except BadRequestException as e:
|
||||||
|
return self.error(
|
||||||
|
"com.amazonaws.dynamodb.v20111205#BadRequestException", e.message
|
||||||
|
)
|
||||||
|
|
||||||
def resource_methods(self, request, full_url, headers):
|
def resource_methods(self, request, full_url, headers):
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
@ -165,6 +184,9 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
stage_response = self.backend.update_stage(
|
stage_response = self.backend.update_stage(
|
||||||
function_id, stage_name, patch_operations
|
function_id, stage_name, patch_operations
|
||||||
)
|
)
|
||||||
|
elif self.method == "DELETE":
|
||||||
|
self.backend.delete_stage(function_id, stage_name)
|
||||||
|
return 202, {}, "{}"
|
||||||
return 200, {}, json.dumps(stage_response)
|
return 200, {}, json.dumps(stage_response)
|
||||||
|
|
||||||
def integrations(self, request, full_url, headers):
|
def integrations(self, request, full_url, headers):
|
||||||
@ -174,6 +196,7 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
resource_id = url_path_parts[4]
|
resource_id = url_path_parts[4]
|
||||||
method_type = url_path_parts[6]
|
method_type = url_path_parts[6]
|
||||||
|
|
||||||
|
try:
|
||||||
if self.method == "GET":
|
if self.method == "GET":
|
||||||
integration_response = self.backend.get_integration(
|
integration_response = self.backend.get_integration(
|
||||||
function_id, resource_id, method_type
|
function_id, resource_id, method_type
|
||||||
@ -181,6 +204,8 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
elif self.method == "PUT":
|
elif self.method == "PUT":
|
||||||
integration_type = self._get_param("type")
|
integration_type = self._get_param("type")
|
||||||
uri = self._get_param("uri")
|
uri = self._get_param("uri")
|
||||||
|
integration_http_method = self._get_param("httpMethod")
|
||||||
|
creds = self._get_param("credentials")
|
||||||
request_templates = self._get_param("requestTemplates")
|
request_templates = self._get_param("requestTemplates")
|
||||||
integration_response = self.backend.create_integration(
|
integration_response = self.backend.create_integration(
|
||||||
function_id,
|
function_id,
|
||||||
@ -188,6 +213,8 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
method_type,
|
method_type,
|
||||||
integration_type,
|
integration_type,
|
||||||
uri,
|
uri,
|
||||||
|
credentials=creds,
|
||||||
|
integration_method=integration_http_method,
|
||||||
request_templates=request_templates,
|
request_templates=request_templates,
|
||||||
)
|
)
|
||||||
elif self.method == "DELETE":
|
elif self.method == "DELETE":
|
||||||
@ -195,6 +222,14 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
function_id, resource_id, method_type
|
function_id, resource_id, method_type
|
||||||
)
|
)
|
||||||
return 200, {}, json.dumps(integration_response)
|
return 200, {}, json.dumps(integration_response)
|
||||||
|
except BadRequestException as e:
|
||||||
|
return self.error(
|
||||||
|
"com.amazonaws.dynamodb.v20111205#BadRequestException", e.message
|
||||||
|
)
|
||||||
|
except CrossAccountNotAllowed as e:
|
||||||
|
return self.error(
|
||||||
|
"com.amazonaws.dynamodb.v20111205#AccessDeniedException", e.message
|
||||||
|
)
|
||||||
|
|
||||||
def integration_responses(self, request, full_url, headers):
|
def integration_responses(self, request, full_url, headers):
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
@ -204,25 +239,37 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
method_type = url_path_parts[6]
|
method_type = url_path_parts[6]
|
||||||
status_code = url_path_parts[9]
|
status_code = url_path_parts[9]
|
||||||
|
|
||||||
|
try:
|
||||||
if self.method == "GET":
|
if self.method == "GET":
|
||||||
integration_response = self.backend.get_integration_response(
|
integration_response = self.backend.get_integration_response(
|
||||||
function_id, resource_id, method_type, status_code
|
function_id, resource_id, method_type, status_code
|
||||||
)
|
)
|
||||||
elif self.method == "PUT":
|
elif self.method == "PUT":
|
||||||
selection_pattern = self._get_param("selectionPattern")
|
selection_pattern = self._get_param("selectionPattern")
|
||||||
|
response_templates = self._get_param("responseTemplates")
|
||||||
integration_response = self.backend.create_integration_response(
|
integration_response = self.backend.create_integration_response(
|
||||||
function_id, resource_id, method_type, status_code, selection_pattern
|
function_id,
|
||||||
|
resource_id,
|
||||||
|
method_type,
|
||||||
|
status_code,
|
||||||
|
selection_pattern,
|
||||||
|
response_templates,
|
||||||
)
|
)
|
||||||
elif self.method == "DELETE":
|
elif self.method == "DELETE":
|
||||||
integration_response = self.backend.delete_integration_response(
|
integration_response = self.backend.delete_integration_response(
|
||||||
function_id, resource_id, method_type, status_code
|
function_id, resource_id, method_type, status_code
|
||||||
)
|
)
|
||||||
return 200, {}, json.dumps(integration_response)
|
return 200, {}, json.dumps(integration_response)
|
||||||
|
except BadRequestException as e:
|
||||||
|
return self.error(
|
||||||
|
"com.amazonaws.dynamodb.v20111205#BadRequestException", e.message
|
||||||
|
)
|
||||||
|
|
||||||
def deployments(self, request, full_url, headers):
|
def deployments(self, request, full_url, headers):
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
function_id = self.path.replace("/restapis/", "", 1).split("/")[0]
|
function_id = self.path.replace("/restapis/", "", 1).split("/")[0]
|
||||||
|
|
||||||
|
try:
|
||||||
if self.method == "GET":
|
if self.method == "GET":
|
||||||
deployments = self.backend.get_deployments(function_id)
|
deployments = self.backend.get_deployments(function_id)
|
||||||
return 200, {}, json.dumps({"item": deployments})
|
return 200, {}, json.dumps({"item": deployments})
|
||||||
@ -234,6 +281,10 @@ class APIGatewayResponse(BaseResponse):
|
|||||||
function_id, name, description, stage_variables
|
function_id, name, description, stage_variables
|
||||||
)
|
)
|
||||||
return 200, {}, json.dumps(deployment)
|
return 200, {}, json.dumps(deployment)
|
||||||
|
except BadRequestException as e:
|
||||||
|
return self.error(
|
||||||
|
"com.amazonaws.dynamodb.v20111205#BadRequestException", e.message
|
||||||
|
)
|
||||||
|
|
||||||
def individual_deployment(self, request, full_url, headers):
|
def individual_deployment(self, request, full_url, headers):
|
||||||
self.setup_class(request, full_url, headers)
|
self.setup_class(request, full_url, headers)
|
||||||
|
@ -9,6 +9,7 @@ from botocore.exceptions import ClientError
|
|||||||
|
|
||||||
import responses
|
import responses
|
||||||
from moto import mock_apigateway, settings
|
from moto import mock_apigateway, settings
|
||||||
|
from nose.tools import assert_raises
|
||||||
|
|
||||||
|
|
||||||
@freeze_time("2015-01-01")
|
@freeze_time("2015-01-01")
|
||||||
@ -45,6 +46,32 @@ def test_list_and_delete_apis():
|
|||||||
len(response["items"]).should.equal(1)
|
len(response["items"]).should.equal(1)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_apigateway
|
||||||
|
def test_create_resource__validate_name():
|
||||||
|
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"]
|
||||||
|
|
||||||
|
resources = client.get_resources(restApiId=api_id)
|
||||||
|
root_id = [resource for resource in resources["items"] if resource["path"] == "/"][
|
||||||
|
0
|
||||||
|
]["id"]
|
||||||
|
|
||||||
|
invalid_names = ["/users", "users/", "users/{user_id}", "us{er"]
|
||||||
|
valid_names = ["users", "{user_id}", "user_09", "good-dog"]
|
||||||
|
# All invalid names should throw an exception
|
||||||
|
for name in invalid_names:
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.create_resource(restApiId=api_id, parentId=root_id, pathPart=name)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("BadRequestException")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Resource's path part only allow a-zA-Z0-9._- and curly braces at the beginning and the end."
|
||||||
|
)
|
||||||
|
# All valid names should go through
|
||||||
|
for name in valid_names:
|
||||||
|
client.create_resource(restApiId=api_id, parentId=root_id, pathPart=name)
|
||||||
|
|
||||||
|
|
||||||
@mock_apigateway
|
@mock_apigateway
|
||||||
def test_create_resource():
|
def test_create_resource():
|
||||||
client = boto3.client("apigateway", region_name="us-west-2")
|
client = boto3.client("apigateway", region_name="us-west-2")
|
||||||
@ -69,9 +96,7 @@ def test_create_resource():
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
response = client.create_resource(
|
client.create_resource(restApiId=api_id, parentId=root_id, pathPart="users")
|
||||||
restApiId=api_id, parentId=root_id, pathPart="/users"
|
|
||||||
)
|
|
||||||
|
|
||||||
resources = client.get_resources(restApiId=api_id)["items"]
|
resources = client.get_resources(restApiId=api_id)["items"]
|
||||||
len(resources).should.equal(2)
|
len(resources).should.equal(2)
|
||||||
@ -79,9 +104,7 @@ def test_create_resource():
|
|||||||
0
|
0
|
||||||
]
|
]
|
||||||
|
|
||||||
response = client.delete_resource(
|
client.delete_resource(restApiId=api_id, resourceId=non_root_resource["id"])
|
||||||
restApiId=api_id, resourceId=non_root_resource["id"]
|
|
||||||
)
|
|
||||||
|
|
||||||
len(client.get_resources(restApiId=api_id)["items"]).should.equal(1)
|
len(client.get_resources(restApiId=api_id)["items"]).should.equal(1)
|
||||||
|
|
||||||
@ -223,6 +246,7 @@ def test_integrations():
|
|||||||
httpMethod="GET",
|
httpMethod="GET",
|
||||||
type="HTTP",
|
type="HTTP",
|
||||||
uri="http://httpbin.org/robots.txt",
|
uri="http://httpbin.org/robots.txt",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
)
|
)
|
||||||
# this is hard to match against, so remove it
|
# this is hard to match against, so remove it
|
||||||
response["ResponseMetadata"].pop("HTTPHeaders", None)
|
response["ResponseMetadata"].pop("HTTPHeaders", None)
|
||||||
@ -308,6 +332,7 @@ def test_integrations():
|
|||||||
type="HTTP",
|
type="HTTP",
|
||||||
uri=test_uri,
|
uri=test_uri,
|
||||||
requestTemplates=templates,
|
requestTemplates=templates,
|
||||||
|
integrationHttpMethod="POST",
|
||||||
)
|
)
|
||||||
# this is hard to match against, so remove it
|
# this is hard to match against, so remove it
|
||||||
response["ResponseMetadata"].pop("HTTPHeaders", None)
|
response["ResponseMetadata"].pop("HTTPHeaders", None)
|
||||||
@ -340,12 +365,13 @@ def test_integration_response():
|
|||||||
restApiId=api_id, resourceId=root_id, httpMethod="GET", statusCode="200"
|
restApiId=api_id, resourceId=root_id, httpMethod="GET", statusCode="200"
|
||||||
)
|
)
|
||||||
|
|
||||||
response = client.put_integration(
|
client.put_integration(
|
||||||
restApiId=api_id,
|
restApiId=api_id,
|
||||||
resourceId=root_id,
|
resourceId=root_id,
|
||||||
httpMethod="GET",
|
httpMethod="GET",
|
||||||
type="HTTP",
|
type="HTTP",
|
||||||
uri="http://httpbin.org/robots.txt",
|
uri="http://httpbin.org/robots.txt",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
)
|
)
|
||||||
|
|
||||||
response = client.put_integration_response(
|
response = client.put_integration_response(
|
||||||
@ -354,6 +380,7 @@ def test_integration_response():
|
|||||||
httpMethod="GET",
|
httpMethod="GET",
|
||||||
statusCode="200",
|
statusCode="200",
|
||||||
selectionPattern="foobar",
|
selectionPattern="foobar",
|
||||||
|
responseTemplates={},
|
||||||
)
|
)
|
||||||
# this is hard to match against, so remove it
|
# this is hard to match against, so remove it
|
||||||
response["ResponseMetadata"].pop("HTTPHeaders", None)
|
response["ResponseMetadata"].pop("HTTPHeaders", None)
|
||||||
@ -410,6 +437,7 @@ def test_update_stage_configuration():
|
|||||||
stage_name = "staging"
|
stage_name = "staging"
|
||||||
response = client.create_rest_api(name="my_api", description="this is my api")
|
response = client.create_rest_api(name="my_api", description="this is my api")
|
||||||
api_id = response["id"]
|
api_id = response["id"]
|
||||||
|
create_method_integration(client, api_id)
|
||||||
|
|
||||||
response = client.create_deployment(
|
response = client.create_deployment(
|
||||||
restApiId=api_id, stageName=stage_name, description="1.0.1"
|
restApiId=api_id, stageName=stage_name, description="1.0.1"
|
||||||
@ -534,7 +562,8 @@ def test_create_stage():
|
|||||||
response = client.create_rest_api(name="my_api", description="this is my api")
|
response = client.create_rest_api(name="my_api", description="this is my api")
|
||||||
api_id = response["id"]
|
api_id = response["id"]
|
||||||
|
|
||||||
response = client.create_deployment(restApiId=api_id, stageName=stage_name)
|
create_method_integration(client, api_id)
|
||||||
|
response = client.create_deployment(restApiId=api_id, stageName=stage_name,)
|
||||||
deployment_id = response["id"]
|
deployment_id = response["id"]
|
||||||
|
|
||||||
response = client.get_deployment(restApiId=api_id, deploymentId=deployment_id)
|
response = client.get_deployment(restApiId=api_id, deploymentId=deployment_id)
|
||||||
@ -690,12 +719,325 @@ def test_create_stage():
|
|||||||
stage["cacheClusterSize"].should.equal("1.6")
|
stage["cacheClusterSize"].should.equal("1.6")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_apigateway
|
||||||
|
def test_create_deployment_requires_REST_methods():
|
||||||
|
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"]
|
||||||
|
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.create_deployment(restApiId=api_id, stageName=stage_name)["id"]
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("BadRequestException")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"The REST API doesn't contain any methods"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_apigateway
|
||||||
|
def test_create_deployment_requires_REST_method_integrations():
|
||||||
|
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"]
|
||||||
|
resources = client.get_resources(restApiId=api_id)
|
||||||
|
root_id = [resource for resource in resources["items"] if resource["path"] == "/"][
|
||||||
|
0
|
||||||
|
]["id"]
|
||||||
|
|
||||||
|
client.put_method(
|
||||||
|
restApiId=api_id, resourceId=root_id, httpMethod="GET", authorizationType="NONE"
|
||||||
|
)
|
||||||
|
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.create_deployment(restApiId=api_id, stageName=stage_name)["id"]
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("BadRequestException")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"No integration defined for method"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_apigateway
|
||||||
|
def test_create_simple_deployment_with_get_method():
|
||||||
|
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"]
|
||||||
|
create_method_integration(client, api_id)
|
||||||
|
deployment = client.create_deployment(restApiId=api_id, stageName=stage_name)
|
||||||
|
assert "id" in deployment
|
||||||
|
|
||||||
|
|
||||||
|
@mock_apigateway
|
||||||
|
def test_create_simple_deployment_with_post_method():
|
||||||
|
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"]
|
||||||
|
create_method_integration(client, api_id, httpMethod="POST")
|
||||||
|
deployment = client.create_deployment(restApiId=api_id, stageName=stage_name)
|
||||||
|
assert "id" in deployment
|
||||||
|
|
||||||
|
|
||||||
|
@mock_apigateway
|
||||||
|
# https://github.com/aws/aws-sdk-js/issues/2588
|
||||||
|
def test_put_integration_response_requires_responseTemplate():
|
||||||
|
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"]
|
||||||
|
resources = client.get_resources(restApiId=api_id)
|
||||||
|
root_id = [resource for resource in resources["items"] if resource["path"] == "/"][
|
||||||
|
0
|
||||||
|
]["id"]
|
||||||
|
|
||||||
|
client.put_method(
|
||||||
|
restApiId=api_id, resourceId=root_id, httpMethod="GET", authorizationType="NONE"
|
||||||
|
)
|
||||||
|
client.put_method_response(
|
||||||
|
restApiId=api_id, resourceId=root_id, httpMethod="GET", statusCode="200"
|
||||||
|
)
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod="GET",
|
||||||
|
type="HTTP",
|
||||||
|
uri="http://httpbin.org/robots.txt",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
|
)
|
||||||
|
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.put_integration_response(
|
||||||
|
restApiId=api_id, resourceId=root_id, httpMethod="GET", statusCode="200"
|
||||||
|
)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("BadRequestException")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal("Invalid request input")
|
||||||
|
# Works fine if responseTemplate is defined
|
||||||
|
client.put_integration_response(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod="GET",
|
||||||
|
statusCode="200",
|
||||||
|
responseTemplates={},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_apigateway
|
||||||
|
def test_put_integration_validation():
|
||||||
|
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"]
|
||||||
|
resources = client.get_resources(restApiId=api_id)
|
||||||
|
root_id = [resource for resource in resources["items"] if resource["path"] == "/"][
|
||||||
|
0
|
||||||
|
]["id"]
|
||||||
|
|
||||||
|
client.put_method(
|
||||||
|
restApiId=api_id, resourceId=root_id, httpMethod="GET", authorizationType="NONE"
|
||||||
|
)
|
||||||
|
client.put_method_response(
|
||||||
|
restApiId=api_id, resourceId=root_id, httpMethod="GET", statusCode="200"
|
||||||
|
)
|
||||||
|
|
||||||
|
http_types = ["HTTP", "HTTP_PROXY"]
|
||||||
|
aws_types = ["AWS", "AWS_PROXY"]
|
||||||
|
types_requiring_integration_method = http_types + aws_types
|
||||||
|
types_not_requiring_integration_method = ["MOCK"]
|
||||||
|
|
||||||
|
for type in types_requiring_integration_method:
|
||||||
|
# Ensure that integrations of these types fail if no integrationHttpMethod is provided
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod="GET",
|
||||||
|
type=type,
|
||||||
|
uri="http://httpbin.org/robots.txt",
|
||||||
|
)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("BadRequestException")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Enumeration value for HttpMethod must be non-empty"
|
||||||
|
)
|
||||||
|
for type in types_not_requiring_integration_method:
|
||||||
|
# Ensure that integrations of these types do not need the integrationHttpMethod
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod="GET",
|
||||||
|
type=type,
|
||||||
|
uri="http://httpbin.org/robots.txt",
|
||||||
|
)
|
||||||
|
for type in http_types:
|
||||||
|
# Ensure that it works fine when providing the integrationHttpMethod-argument
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod="GET",
|
||||||
|
type=type,
|
||||||
|
uri="http://httpbin.org/robots.txt",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
|
)
|
||||||
|
for type in ["AWS"]:
|
||||||
|
# Ensure that it works fine when providing the integrationHttpMethod + credentials
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
credentials="arn:aws:iam::123456789012:role/service-role/testfunction-role-oe783psq",
|
||||||
|
httpMethod="GET",
|
||||||
|
type=type,
|
||||||
|
uri="arn:aws:apigateway:us-west-2:s3:path/b/k",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
|
)
|
||||||
|
for type in aws_types:
|
||||||
|
# Ensure that credentials are not required when URI points to a Lambda stream
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod="GET",
|
||||||
|
type=type,
|
||||||
|
uri="arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/arn:aws:lambda:eu-west-1:012345678901:function:MyLambda/invocations",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
|
)
|
||||||
|
for type in ["AWS_PROXY"]:
|
||||||
|
# Ensure that aws_proxy does not support S3
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
credentials="arn:aws:iam::123456789012:role/service-role/testfunction-role-oe783psq",
|
||||||
|
httpMethod="GET",
|
||||||
|
type=type,
|
||||||
|
uri="arn:aws:apigateway:us-west-2:s3:path/b/k",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
|
)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("BadRequestException")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Integrations of type 'AWS_PROXY' currently only supports Lambda function and Firehose stream invocations."
|
||||||
|
)
|
||||||
|
for type in aws_types:
|
||||||
|
# Ensure that the Role ARN is for the current account
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
credentials="arn:aws:iam::000000000000:role/service-role/testrole",
|
||||||
|
httpMethod="GET",
|
||||||
|
type=type,
|
||||||
|
uri="arn:aws:apigateway:us-west-2:s3:path/b/k",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
|
)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("AccessDeniedException")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Cross-account pass role is not allowed."
|
||||||
|
)
|
||||||
|
for type in ["AWS"]:
|
||||||
|
# Ensure that the Role ARN is specified for aws integrations
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod="GET",
|
||||||
|
type=type,
|
||||||
|
uri="arn:aws:apigateway:us-west-2:s3:path/b/k",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
|
)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("BadRequestException")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Role ARN must be specified for AWS integrations"
|
||||||
|
)
|
||||||
|
for type in http_types:
|
||||||
|
# Ensure that the URI is valid HTTP
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod="GET",
|
||||||
|
type=type,
|
||||||
|
uri="non-valid-http",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
|
)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("BadRequestException")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Invalid HTTP endpoint specified for URI"
|
||||||
|
)
|
||||||
|
for type in aws_types:
|
||||||
|
# Ensure that the URI is an ARN
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod="GET",
|
||||||
|
type=type,
|
||||||
|
uri="non-valid-arn",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
|
)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("BadRequestException")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"Invalid ARN specified in the request"
|
||||||
|
)
|
||||||
|
for type in aws_types:
|
||||||
|
# Ensure that the URI is a valid ARN
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod="GET",
|
||||||
|
type=type,
|
||||||
|
uri="arn:aws:iam::0000000000:role/service-role/asdf",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
|
)
|
||||||
|
ex.exception.response["Error"]["Code"].should.equal("BadRequestException")
|
||||||
|
ex.exception.response["Error"]["Message"].should.equal(
|
||||||
|
"AWS ARN for integration must contain path or action"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_apigateway
|
||||||
|
def test_delete_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"]
|
||||||
|
create_method_integration(client, api_id)
|
||||||
|
deployment_id1 = client.create_deployment(restApiId=api_id, stageName=stage_name)[
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
deployment_id2 = client.create_deployment(restApiId=api_id, stageName=stage_name)[
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
|
||||||
|
new_stage_name = "current"
|
||||||
|
client.create_stage(
|
||||||
|
restApiId=api_id, stageName=new_stage_name, deploymentId=deployment_id1
|
||||||
|
)
|
||||||
|
|
||||||
|
new_stage_name_with_vars = "stage_with_vars"
|
||||||
|
client.create_stage(
|
||||||
|
restApiId=api_id,
|
||||||
|
stageName=new_stage_name_with_vars,
|
||||||
|
deploymentId=deployment_id2,
|
||||||
|
variables={"env": "dev"},
|
||||||
|
)
|
||||||
|
stages = client.get_stages(restApiId=api_id)["item"]
|
||||||
|
sorted([stage["stageName"] for stage in stages]).should.equal(
|
||||||
|
sorted([new_stage_name, new_stage_name_with_vars, stage_name])
|
||||||
|
)
|
||||||
|
# delete stage
|
||||||
|
response = client.delete_stage(restApiId=api_id, stageName=new_stage_name_with_vars)
|
||||||
|
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(202)
|
||||||
|
# verify other stage still exists
|
||||||
|
stages = client.get_stages(restApiId=api_id)["item"]
|
||||||
|
sorted([stage["stageName"] for stage in stages]).should.equal(
|
||||||
|
sorted([new_stage_name, stage_name])
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@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")
|
||||||
stage_name = "staging"
|
stage_name = "staging"
|
||||||
response = client.create_rest_api(name="my_api", description="this is my api")
|
response = client.create_rest_api(name="my_api", description="this is my api")
|
||||||
api_id = response["id"]
|
api_id = response["id"]
|
||||||
|
create_method_integration(client, api_id)
|
||||||
|
|
||||||
response = client.create_deployment(restApiId=api_id, stageName=stage_name)
|
response = client.create_deployment(restApiId=api_id, stageName=stage_name)
|
||||||
deployment_id = response["id"]
|
deployment_id = response["id"]
|
||||||
@ -719,7 +1061,7 @@ def test_deployment():
|
|||||||
response["items"][0].pop("createdDate")
|
response["items"][0].pop("createdDate")
|
||||||
response["items"].should.equal([{"id": deployment_id, "description": ""}])
|
response["items"].should.equal([{"id": deployment_id, "description": ""}])
|
||||||
|
|
||||||
response = client.delete_deployment(restApiId=api_id, deploymentId=deployment_id)
|
client.delete_deployment(restApiId=api_id, deploymentId=deployment_id)
|
||||||
|
|
||||||
response = client.get_deployments(restApiId=api_id)
|
response = client.get_deployments(restApiId=api_id)
|
||||||
len(response["items"]).should.equal(0)
|
len(response["items"]).should.equal(0)
|
||||||
@ -730,7 +1072,7 @@ def test_deployment():
|
|||||||
stage["stageName"].should.equal(stage_name)
|
stage["stageName"].should.equal(stage_name)
|
||||||
stage["deploymentId"].should.equal(deployment_id)
|
stage["deploymentId"].should.equal(deployment_id)
|
||||||
|
|
||||||
stage = client.update_stage(
|
client.update_stage(
|
||||||
restApiId=api_id,
|
restApiId=api_id,
|
||||||
stageName=stage_name,
|
stageName=stage_name,
|
||||||
patchOperations=[
|
patchOperations=[
|
||||||
@ -774,6 +1116,7 @@ def test_http_proxying_integration():
|
|||||||
httpMethod="GET",
|
httpMethod="GET",
|
||||||
type="HTTP",
|
type="HTTP",
|
||||||
uri="http://httpbin.org/robots.txt",
|
uri="http://httpbin.org/robots.txt",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
)
|
)
|
||||||
|
|
||||||
stage_name = "staging"
|
stage_name = "staging"
|
||||||
@ -888,7 +1231,6 @@ def test_usage_plans():
|
|||||||
@mock_apigateway
|
@mock_apigateway
|
||||||
def test_usage_plan_keys():
|
def test_usage_plan_keys():
|
||||||
region_name = "us-west-2"
|
region_name = "us-west-2"
|
||||||
usage_plan_id = "test_usage_plan_id"
|
|
||||||
client = boto3.client("apigateway", region_name=region_name)
|
client = boto3.client("apigateway", region_name=region_name)
|
||||||
usage_plan_id = "test"
|
usage_plan_id = "test"
|
||||||
|
|
||||||
@ -932,7 +1274,6 @@ def test_usage_plan_keys():
|
|||||||
@mock_apigateway
|
@mock_apigateway
|
||||||
def test_create_usage_plan_key_non_existent_api_key():
|
def test_create_usage_plan_key_non_existent_api_key():
|
||||||
region_name = "us-west-2"
|
region_name = "us-west-2"
|
||||||
usage_plan_id = "test_usage_plan_id"
|
|
||||||
client = boto3.client("apigateway", region_name=region_name)
|
client = boto3.client("apigateway", region_name=region_name)
|
||||||
usage_plan_id = "test"
|
usage_plan_id = "test"
|
||||||
|
|
||||||
@ -976,3 +1317,34 @@ def test_get_usage_plans_using_key_id():
|
|||||||
len(only_plans_with_key["items"]).should.equal(1)
|
len(only_plans_with_key["items"]).should.equal(1)
|
||||||
only_plans_with_key["items"][0]["name"].should.equal(attached_plan["name"])
|
only_plans_with_key["items"][0]["name"].should.equal(attached_plan["name"])
|
||||||
only_plans_with_key["items"][0]["id"].should.equal(attached_plan["id"])
|
only_plans_with_key["items"][0]["id"].should.equal(attached_plan["id"])
|
||||||
|
|
||||||
|
|
||||||
|
def create_method_integration(client, api_id, httpMethod="GET"):
|
||||||
|
resources = client.get_resources(restApiId=api_id)
|
||||||
|
root_id = [resource for resource in resources["items"] if resource["path"] == "/"][
|
||||||
|
0
|
||||||
|
]["id"]
|
||||||
|
client.put_method(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod=httpMethod,
|
||||||
|
authorizationType="NONE",
|
||||||
|
)
|
||||||
|
client.put_method_response(
|
||||||
|
restApiId=api_id, resourceId=root_id, httpMethod=httpMethod, statusCode="200"
|
||||||
|
)
|
||||||
|
client.put_integration(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod=httpMethod,
|
||||||
|
type="HTTP",
|
||||||
|
uri="http://httpbin.org/robots.txt",
|
||||||
|
integrationHttpMethod="POST",
|
||||||
|
)
|
||||||
|
client.put_integration_response(
|
||||||
|
restApiId=api_id,
|
||||||
|
resourceId=root_id,
|
||||||
|
httpMethod=httpMethod,
|
||||||
|
statusCode="200",
|
||||||
|
responseTemplates={},
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user