def test_provider_parse_stage_name(self): template = { "Resources": { "Stage": {"Type": "AWS::ApiGateway::Stage", "Properties": {"StageName": "dev", "RestApiId": "TestApi"}}, "TestApi": { "Type": "AWS::ApiGateway::RestApi", "Properties": { "Body": { "paths": { "/path": { "get": { "x-amazon-apigateway-integration": { "httpMethod": "POST", "type": "aws_proxy", "uri": { "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31" "/functions/${NoApiEventFunction.Arn}/invocations" }, "responses": {}, } } } } } }, }, } } provider = ApiProvider(template) route1 = Route(path="/path", methods=["GET"], function_name="NoApiEventFunction") self.assertIn(route1, provider.routes) self.assertEqual(provider.api.stage_name, "dev") self.assertEqual(provider.api.stage_variables, None)
def test_resource_with_method_correct_routes(self): template = { "Resources": { "TestApi": {"Type": "AWS::ApiGateway::Resource", "Properties": {"StageName": "Prod"}}, "BetaApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "beta", "ResourceId": "TestApi"}, }, "BetaAlphaApiMethod": { "Type": "AWS::ApiGateway::Method", "Properties": {"HttpMethod": "ANY", "RestApiId": "TestApi", "ResourceId": "BetaApiResource"}, }, } } provider = ApiProvider(template) self.assertCountEqual( provider.routes, [ Route( path="/beta", methods=["POST", "GET", "DELETE", "HEAD", "OPTIONS", "PATCH", "PUT"], function_name=None, ) ], )
def test_with_inline_swagger_apis(self): template = { "Resources": { "Api1": {"Type": "AWS::ApiGateway::RestApi", "Properties": {"Body": make_swagger(self.input_routes)}} } } provider = ApiProvider(template) self.assertCountEqual(self.input_routes, provider.routes)
def test_provider_with_valid_template(self, SamBaseProviderMock, extract_api_mock): extract_api_mock.return_value = Api(routes={"set", "of", "values"}) template = {"Resources": {"a": "b"}} SamBaseProviderMock.get_template.return_value = template provider = ApiProvider(template) self.assertEqual(len(provider.routes), 3) self.assertEqual(provider.routes, set(["set", "of", "values"])) self.assertEqual(provider.template_dict, {"Resources": {"a": "b"}}) self.assertEqual(provider.resources, {"a": "b"})
def test_basic_rest_api_resource_method(self): template = { "Resources": { "TestApi": {"Type": "AWS::ApiGateway::RestApi", "Properties": {"StageName": "Prod"}}, "ApiResource": {"Properties": {"PathPart": "{proxy+}", "RestApiId": "TestApi"}}, "ApiMethod": { "Type": "AWS::ApiGateway::Method", "Properties": {"HttpMethod": "POST", "RestApiId": "TestApi", "ResourceId": "ApiResource"}, }, } } provider = ApiProvider(template) self.assertEqual(provider.routes, [Route(function_name=None, path="/{proxy+}", methods=["POST"])])
def test_with_swagger_as_local_file(self): with tempfile.NamedTemporaryFile(mode="w", delete=False) as fp: filename = fp.name swagger = make_swagger(self.input_routes) json.dump(swagger, fp) fp.flush() template = { "Resources": {"Api1": {"Type": "AWS::ApiGateway::RestApi", "Properties": {"BodyS3Location": filename}}} } provider = ApiProvider(template) self.assertCountEqual(self.input_routes, provider.routes)
def test_with_swagger_as_both_body_and_uri_called(self, SwaggerReaderMock): body = {"some": "body"} filename = "somefile.txt" template = { "Resources": { "Api1": {"Type": "AWS::ApiGateway::RestApi", "Properties": {"BodyS3Location": filename, "Body": body}} } } SwaggerReaderMock.return_value.read.return_value = make_swagger(self.input_routes) cwd = "foo" provider = ApiProvider(template, cwd=cwd) self.assertCountEqual(self.input_routes, provider.routes) SwaggerReaderMock.assert_called_with(definition_body=body, definition_uri=filename, working_dir=cwd)
def test_swagger_with_any_method(self): routes = [Route(path="/path", methods=["any"], function_name="SamFunc1")] expected_routes = [ Route( path="/path", methods=["GET", "DELETE", "PUT", "POST", "HEAD", "OPTIONS", "PATCH"], function_name="SamFunc1", ) ] template = { "Resources": {"Api1": {"Type": "AWS::ApiGateway::RestApi", "Properties": {"Body": make_swagger(routes)}}} } provider = ApiProvider(template) self.assertCountEqual(expected_routes, provider.routes)
def test_with_binary_media_types(self): template = { "Resources": { "Api1": { "Type": "AWS::ApiGateway::RestApi", "Properties": {"Body": make_swagger(self.input_routes, binary_media_types=self.binary_types)}, } } } expected_binary_types = sorted(self.binary_types) expected_apis = [ Route(path="/path1", methods=["GET", "POST"], function_name="SamFunc1"), Route(path="/path2", methods=["PUT", "GET"], function_name="SamFunc1"), Route(path="/path3", methods=["DELETE"], function_name="SamFunc1"), ] provider = ApiProvider(template) self.assertCountEqual(expected_apis, provider.routes) self.assertCountEqual(provider.api.binary_media_types, expected_binary_types)
def test_resolve_correct_multi_parent_resource_path(self): template = { "Resources": { "TestApi": {"Type": "AWS::ApiGateway::Resource", "Properties": {"StageName": "Prod"}}, "RootApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "root", "ResourceId": "TestApi"}, }, "V1ApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "v1", "ResourceId": "TestApi", "ParentId": "RootApiResource"}, }, "AlphaApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "alpha", "ResourceId": "TestApi", "ParentId": "V1ApiResource"}, }, "BetaApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "beta", "ResourceId": "TestApi", "ParentId": "V1ApiResource"}, }, "AlphaApiMethod": { "Type": "AWS::ApiGateway::Method", "Properties": {"HttpMethod": "GET", "RestApiId": "TestApi", "ResourceId": "AlphaApiResource"}, }, "BetaAlphaApiMethod": { "Type": "AWS::ApiGateway::Method", "Properties": {"HttpMethod": "POST", "RestApiId": "TestApi", "ResourceId": "BetaApiResource"}, }, } } provider = ApiProvider(template) assertCountEqual( self, provider.routes, [ Route(path="/root/v1/beta", methods=["POST"], function_name=None), Route(path="/root/v1/alpha", methods=["GET"], function_name=None), ], )
def __init__(self, lambda_invoke_context, port, host, static_dir): """ Initialize the local API service. :param samcli.commands.local.cli_common.invoke_context.InvokeContext lambda_invoke_context: Context object that can help with Lambda invocation :param int port: Port to listen on :param string host: Local hostname or IP address to bind to :param string static_dir: Optional, directory from which static files will be mounted """ self.port = port self.host = host self.static_dir = static_dir self.cwd = lambda_invoke_context.get_cwd() self.api_provider = ApiProvider( lambda_invoke_context.template, parameter_overrides=lambda_invoke_context.parameter_overrides, cwd=self.cwd) self.lambda_runner = lambda_invoke_context.local_lambda_runner self.stderr_stream = lambda_invoke_context.stderr
def test_with_binary_media_types_in_swagger_and_on_resource(self): input_routes = [Route(path="/path", methods=["OPTIONS"], function_name="SamFunc1")] extra_binary_types = ["text/html"] template = { "Resources": { "Api1": { "Type": "AWS::ApiGateway::RestApi", "Properties": { "BinaryMediaTypes": extra_binary_types, "Body": make_swagger(input_routes, binary_media_types=self.binary_types), }, } } } expected_binary_types = sorted(self.binary_types + extra_binary_types) expected_routes = [Route(path="/path", methods=["OPTIONS"], function_name="SamFunc1")] provider = ApiProvider(template) self.assertCountEqual(expected_routes, provider.routes) self.assertCountEqual(provider.api.binary_media_types, expected_binary_types)
def test_cdk(self): template = { "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "HelloHandler2E4FBA4D": { "Type": "AWS::Lambda::Function", "Properties": {"Code": ".", "Handler": "main.handler", "Runtime": "python3.6"}, "DependsOn": ["HelloHandlerServiceRole11EF7C63"], }, "EndpointEEF1FD8F": {"Type": "AWS::ApiGateway::RestApi", "Properties": {"Name": "Endpoint"}}, "EndpointDeploymentStageprodB78BEEA0": { "Type": "AWS::ApiGateway::Stage", "Properties": { "RestApiId": {"Ref": "EndpointEEF1FD8F"}, "DeploymentId": {"Ref": "EndpointDeployment318525DA37c0e38727e25b4317827bf43e918fbf"}, "StageName": "prod", }, }, "Endpointproxy39E2174E": { "Type": "AWS::ApiGateway::Resource", "Properties": { "ParentId": {"Fn::GetAtt": ["EndpointEEF1FD8F", "RootResourceId"]}, "PathPart": "{proxy+}", "RestApiId": {"Ref": "EndpointEEF1FD8F"}, }, }, "EndpointproxyANYC09721C5": { "Type": "AWS::ApiGateway::Method", "Properties": { "HttpMethod": "ANY", "ResourceId": {"Ref": "Endpointproxy39E2174E"}, "RestApiId": {"Ref": "EndpointEEF1FD8F"}, "AuthorizationType": "NONE", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", "Uri": { "Fn::Join": [ "", [ "arn:", {"Ref": "AWS::Partition"}, ":apigateway:", {"Ref": "AWS::Region"}, "lambda:path/2015-03-31/functions/", {"Fn::GetAtt": ["HelloHandler2E4FBA4D", "Arn"]}, "/invocations", ], ] }, }, }, }, "EndpointANY485C938B": { "Type": "AWS::ApiGateway::Method", "Properties": { "HttpMethod": "ANY", "ResourceId": {"Fn::GetAtt": ["EndpointEEF1FD8F", "RootResourceId"]}, "RestApiId": {"Ref": "EndpointEEF1FD8F"}, "AuthorizationType": "NONE", "Integration": { "IntegrationHttpMethod": "POST", "Type": "AWS_PROXY", "Uri": { "Fn::Join": [ "", [ "arn:", {"Ref": "AWS::Partition"}, ":apigateway:", {"Ref": "AWS::Region"}, "lambda:path/2015-03-31/functions/", {"Fn::GetAtt": ["HelloHandler2E4FBA4D", "Arn"]}, "/invocations", ], ] }, }, }, }, }, "Parameters": { "HelloHandlerCodeS3Bucket4359A483": { "Type": "String", "Description": 'S3 bucket for asset "CdkWorkshopStack/HelloHandler/Code"', }, "HelloHandlerCodeS3VersionKey07D12610": { "Type": "String", "Description": 'S3 key for asset version "CdkWorkshopStack/HelloHandler/Code"', }, }, "Outputs": { "Endpoint8024A810": { "Value": { "Fn::Join": [ "", [ "https://", {"Ref": "EndpointEEF1FD8F"}, ".execute-api.", {"Ref": "AWS::Region"}, ".", {"Ref": "AWS::URLSuffix"}, "/", {"Ref": "EndpointDeploymentStageprodB78BEEA0"}, "/", ], ] }, "Export": {"Name": "CdkWorkshopStack:Endpoint8024A810"}, } }, } provider = ApiProvider(template) proxy_paths = [Route(path="/{proxy+}", methods=Route.ANY_HTTP_METHODS, function_name="HelloHandler2E4FBA4D")] root_paths = [Route(path="/", methods=Route.ANY_HTTP_METHODS, function_name="HelloHandler2E4FBA4D")] self.assertCountEqual(provider.routes, proxy_paths + root_paths)
def test_binary_media_types_method(self): template = { "Resources": { "TestApi": {"Type": "AWS::ApiGateway::Resource", "Properties": {"StageName": "Prod"}}, "RootApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "root", "ResourceId": "TestApi"}, }, "V1ApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "v1", "ResourceId": "TestApi", "ParentId": "RootApiResource"}, }, "AlphaApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "alpha", "ResourceId": "TestApi", "ParentId": "V1ApiResource"}, }, "BetaApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "beta", "ResourceId": "TestApi", "ParentId": "V1ApiResource"}, }, "AlphaApiMethod": { "Type": "AWS::ApiGateway::Method", "Properties": { "HttpMethod": "GET", "RestApiId": "TestApi", "ResourceId": "AlphaApiResource", "Integration": { "Uri": { "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/" "functions" "/${AWSBetaLambdaFunction.Arn}/invocations} " }, "ContentHandling": "CONVERT_TO_BINARY", "ContentType": "image~1jpg", }, }, }, "BetaAlphaApiMethod": { "Type": "AWS::ApiGateway::Method", "Properties": { "HttpMethod": "POST", "RestApiId": "TestApi", "ResourceId": "BetaApiResource", "Integration": { "Uri": { "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/" "functions" "/${AWSLambdaFunction.Arn}/invocations}" }, "ContentHandling": "CONVERT_TO_BINARY", "ContentType": "image~1png", }, }, }, "AWSAlphaLambdaFunction": { "Type": "AWS::Lambda::Function", "Properties": {"Code": ".", "Handler": "main.run_test", "Runtime": "Python3.6"}, }, "AWSBetaLambdaFunction": { "Type": "AWS::Lambda::Function", "Properties": {"Code": ".", "Handler": "main.run_test", "Runtime": "Python3.6"}, }, } } provider = ApiProvider(template) self.assertCountEqual(provider.api.binary_media_types, ["image/png", "image/jpg"])
def test_method_integration_uri(self): template = { "Resources": { "TestApi": {"Type": "AWS::ApiGateway::Resource", "Properties": {"StageName": "Prod"}}, "RootApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "root", "ResourceId": "TestApi"}, }, "V1ApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "v1", "ResourceId": "TestApi", "ParentId": "RootApiResource"}, }, "AlphaApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "alpha", "ResourceId": "TestApi", "ParentId": "V1ApiResource"}, }, "BetaApiResource": { "Type": "AWS::ApiGateway::Resource", "Properties": {"PathPart": "beta", "ResourceId": "TestApi", "ParentId": "V1ApiResource"}, }, "AlphaApiMethod": { "Type": "AWS::ApiGateway::Method", "Properties": { "HttpMethod": "GET", "RestApiId": "TestApi", "ResourceId": "AlphaApiResource", "Integration": { "Uri": { "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/" "functions" "/${AWSBetaLambdaFunction.Arn}/invocations} " } }, }, }, "BetaAlphaApiMethod": { "Type": "AWS::ApiGateway::Method", "Properties": { "HttpMethod": "POST", "RestApiId": "TestApi", "ResourceId": "BetaApiResource", "Integration": { "Uri": { "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/" "functions" "/${AWSLambdaFunction.Arn}/invocations}" } }, }, }, "AWSAlphaLambdaFunction": { "Type": "AWS::Lambda::Function", "Properties": {"Code": ".", "Handler": "main.run_test", "Runtime": "Python3.6"}, }, "AWSBetaLambdaFunction": { "Type": "AWS::Lambda::Function", "Properties": {"Code": ".", "Handler": "main.run_test", "Runtime": "Python3.6"}, }, } } provider = ApiProvider(template) self.assertCountEqual( provider.routes, [ Route(path="/root/v1/beta", methods=["POST"], function_name="AWSLambdaFunction"), Route(path="/root/v1/alpha", methods=["GET"], function_name="AWSBetaLambdaFunction"), ], )
def test_multi_stage_get_all(self): resources = OrderedDict( { "ProductionApi": { "Type": "AWS::ApiGateway::RestApi", "Properties": { "Body": { "paths": { "/path": { "get": { "x-amazon-apigateway-integration": { "httpMethod": "POST", "type": "aws_proxy", "uri": { "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31" "/functions/${NoApiEventFunction.Arn}/invocations" }, "responses": {}, } } }, "/anotherpath": { "post": { "x-amazon-apigateway-integration": { "httpMethod": "POST", "type": "aws_proxy", "uri": { "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31" "/functions/${NoApiEventFunction.Arn}/invocations" }, "responses": {}, } } }, } } }, } } ) resources["StageDev"] = { "Type": "AWS::ApiGateway::Stage", "Properties": { "StageName": "dev", "Variables": {"vis": "data", "random": "test", "foo": "bar"}, "RestApiId": "ProductionApi", }, } resources["StageProd"] = { "Type": "AWS::ApiGateway::Stage", "Properties": { "StageName": "Production", "Variables": {"vis": "prod data", "random": "test", "foo": "bar"}, "RestApiId": "ProductionApi", }, } template = {"Resources": resources} provider = ApiProvider(template) result = [f for f in provider.get_all()] routes = result[0].routes route1 = Route(path="/path", methods=["GET"], function_name="NoApiEventFunction") route2 = Route(path="/anotherpath", methods=["POST"], function_name="NoApiEventFunction") self.assertEqual(len(routes), 2) self.assertIn(route1, routes) self.assertIn(route2, routes) self.assertEqual(provider.api.stage_name, "Production") self.assertEqual(provider.api.stage_variables, {"vis": "prod data", "random": "test", "foo": "bar"})
def test_with_no_apis(self): template = {"Resources": {"Api1": {"Type": "AWS::ApiGateway::RestApi", "Properties": {}}}} provider = ApiProvider(template) self.assertEqual(provider.routes, [])