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.utils import iso_8601_datetime_with_milliseconds
 | 
			
		||||
from .utils import create_id
 | 
			
		||||
from .exceptions import StageNotFoundException
 | 
			
		||||
 | 
			
		||||
STAGE_URL = "https://{api_id}.execute-api.{region_name}.amazonaws.com/{stage_name}"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Deployment(dict):
 | 
			
		||||
    def __init__(self, deployment_id, name):
 | 
			
		||||
    def __init__(self, deployment_id, name, description=""):
 | 
			
		||||
        super(Deployment, self).__init__()
 | 
			
		||||
        self['id'] = deployment_id
 | 
			
		||||
        self['stageName'] = name
 | 
			
		||||
        self['description'] = description
 | 
			
		||||
        self['createdDate'] = iso_8601_datetime_with_milliseconds(datetime.datetime.now())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IntegrationResponse(dict):
 | 
			
		||||
@ -150,24 +153,133 @@ class Resource(object):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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__()
 | 
			
		||||
        if variables is None:
 | 
			
		||||
            variables = {}
 | 
			
		||||
        self['stageName'] = name
 | 
			
		||||
        self['deploymentId'] = deployment_id
 | 
			
		||||
        self['methodSettings'] = {}
 | 
			
		||||
        self['variables'] = {}
 | 
			
		||||
        self['description'] = ''
 | 
			
		||||
        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)
 | 
			
		||||
 | 
			
		||||
    def apply_operations(self, patch_operations):
 | 
			
		||||
        for op in patch_operations:
 | 
			
		||||
            if op['op'] == 'replace':
 | 
			
		||||
                # TODO: match the path against the values hash
 | 
			
		||||
            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':
 | 
			
		||||
                # Method Settings drop into here
 | 
			
		||||
                # (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:
 | 
			
		||||
                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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    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):
 | 
			
		||||
    def __init__(self, id, region_name, name, description):
 | 
			
		||||
@ -219,12 +331,22 @@ class RestAPI(object):
 | 
			
		||||
        for method in httpretty.httpretty.METHODS:
 | 
			
		||||
            httpretty.register_uri(method, stage_url, body=self.resource_callback)
 | 
			
		||||
 | 
			
		||||
    def create_deployment(self, name):
 | 
			
		||||
        deployment_id = create_id()
 | 
			
		||||
        deployment = Deployment(deployment_id, name)
 | 
			
		||||
        self.deployments[deployment_id] = deployment
 | 
			
		||||
        self.stages[name] = Stage(name=name, deployment_id=deployment_id)
 | 
			
		||||
    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)
 | 
			
		||||
        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)
 | 
			
		||||
 | 
			
		||||
        return deployment
 | 
			
		||||
@ -232,6 +354,9 @@ class RestAPI(object):
 | 
			
		||||
    def get_deployment(self, deployment_id):
 | 
			
		||||
        return self.deployments[deployment_id]
 | 
			
		||||
 | 
			
		||||
    def get_stages(self):
 | 
			
		||||
            return list(self.stages.values())
 | 
			
		||||
 | 
			
		||||
    def get_deployments(self):
 | 
			
		||||
        return list(self.deployments.values())
 | 
			
		||||
 | 
			
		||||
@ -300,6 +425,25 @@ class APIGatewayBackend(BaseBackend):
 | 
			
		||||
 | 
			
		||||
    def get_stage(self, function_id, stage_name):
 | 
			
		||||
        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)
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
        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)
 | 
			
		||||
        deployment = api.create_deployment(name)
 | 
			
		||||
        deployment = api.create_deployment(name, description,stage_variables)
 | 
			
		||||
        return deployment
 | 
			
		||||
 | 
			
		||||
    def get_deployment(self, function_id, deployment_id):
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ import json
 | 
			
		||||
 | 
			
		||||
from moto.core.responses import BaseResponse
 | 
			
		||||
from .models import apigateway_backends
 | 
			
		||||
from .exceptions import StageNotFoundException
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class APIGatewayResponse(BaseResponse):
 | 
			
		||||
@ -11,6 +12,15 @@ class APIGatewayResponse(BaseResponse):
 | 
			
		||||
    def _get_param(self, 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
 | 
			
		||||
    def backend(self):
 | 
			
		||||
        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)
 | 
			
		||||
        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):
 | 
			
		||||
        self.setup_class(request, full_url, headers)
 | 
			
		||||
        url_path_parts = self.path.split("/")
 | 
			
		||||
@ -102,10 +134,13 @@ class APIGatewayResponse(BaseResponse):
 | 
			
		||||
        stage_name = url_path_parts[4]
 | 
			
		||||
 | 
			
		||||
        if self.method == 'GET':
 | 
			
		||||
            try:
 | 
			
		||||
                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':
 | 
			
		||||
            path_operations = self._get_param('patchOperations')
 | 
			
		||||
            stage_response = self.backend.update_stage(function_id, stage_name, path_operations)
 | 
			
		||||
            patch_operations = self._get_param('patchOperations')
 | 
			
		||||
            stage_response = self.backend.update_stage(function_id, stage_name, patch_operations)
 | 
			
		||||
        return 200, headers, json.dumps(stage_response)
 | 
			
		||||
 | 
			
		||||
    def integrations(self, request, full_url, headers):
 | 
			
		||||
@ -158,7 +193,9 @@ class APIGatewayResponse(BaseResponse):
 | 
			
		||||
            return 200, headers, json.dumps({"item": deployments})
 | 
			
		||||
        elif self.method == 'POST':
 | 
			
		||||
            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)
 | 
			
		||||
 | 
			
		||||
    def individual_deployment(self, request, full_url, headers):
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@ url_paths = {
 | 
			
		||||
    '{0}/restapis$': APIGatewayResponse().restapis,
 | 
			
		||||
    '{0}/restapis/(?P<function_id>[^/]+)/?$': APIGatewayResponse().restapis_individual,
 | 
			
		||||
    '{0}/restapis/(?P<function_id>[^/]+)/resources$': APIGatewayResponse().resources,
 | 
			
		||||
    '{0}/restapis/(?P<function_id>[^/]+)/stages$': APIGatewayResponse().restapis_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/(?P<deployment_id>[^/]+)/?$': APIGatewayResponse().individual_deployment,
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
from dateutil.tz import tzutc
 | 
			
		||||
import boto3
 | 
			
		||||
@ -7,6 +8,7 @@ from freezegun import freeze_time
 | 
			
		||||
import httpretty
 | 
			
		||||
import requests
 | 
			
		||||
import sure  # noqa
 | 
			
		||||
from botocore.exceptions import ClientError
 | 
			
		||||
 | 
			
		||||
from moto import mock_apigateway
 | 
			
		||||
 | 
			
		||||
@ -360,6 +362,7 @@ def test_integrations():
 | 
			
		||||
        uri=test_uri,
 | 
			
		||||
        requestTemplates=templates
 | 
			
		||||
    )
 | 
			
		||||
    response['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
 | 
			
		||||
    response['ResponseMetadata'].should.equal({'HTTPStatusCode': 200})
 | 
			
		||||
 | 
			
		||||
    response = client.get_integration(
 | 
			
		||||
@ -469,6 +472,319 @@ def test_integration_response():
 | 
			
		||||
    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
 | 
			
		||||
def test_deployment():
 | 
			
		||||
    client = boto3.client('apigateway', region_name='us-west-2')
 | 
			
		||||
@ -489,17 +805,21 @@ def test_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}
 | 
			
		||||
        'ResponseMetadata': {'HTTPStatusCode': 200},
 | 
			
		||||
        'description' : ''
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    response = client.get_deployments(
 | 
			
		||||
        restApiId=api_id,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    response['items'][0].pop('createdDate')
 | 
			
		||||
    response['items'].should.equal([
 | 
			
		||||
        {'id': deployment_id}
 | 
			
		||||
        {'id': deployment_id, 'description': ''}
 | 
			
		||||
    ])
 | 
			
		||||
 | 
			
		||||
    response = client.delete_deployment(
 | 
			
		||||
@ -527,7 +847,7 @@ def test_deployment():
 | 
			
		||||
        patchOperations=[
 | 
			
		||||
            {
 | 
			
		||||
                'op': 'replace',
 | 
			
		||||
                'path': 'description',
 | 
			
		||||
                'path': '/description',
 | 
			
		||||
                'value': '_new_description_'
 | 
			
		||||
            },
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user