def test_must_print_routes(self):
        host = "host"
        port = 123

        api_provider = Mock()
        apis = [
            Api(path="/1", method="GET", function_name="name1", cors="CORS1"),
            Api(path="/1", method="POST", function_name="name1", cors="CORS1"),
            Api(path="/1",
                method="DELETE",
                function_name="othername1",
                cors="CORS1"),
            Api(path="/2", method="GET2", function_name="name2", cors="CORS2"),
            Api(path="/3", method="GET3", function_name="name3", cors="CORS3"),
        ]
        api_provider.get_all.return_value = apis

        expected = {
            "Mounting name1 at http://host:123/1 [GET, POST]",
            "Mounting othername1 at http://host:123/1 [DELETE]",
            "Mounting name2 at http://host:123/2 [GET2]",
            "Mounting name3 at http://host:123/3 [GET3]"
        }

        actual = LocalApiService._print_routes(api_provider, host, port)
        self.assertEquals(expected, set(actual))
    def test_with_binary_media_types(self):
        template = {
            "Resources": {

                "Api1": {
                    "Type": "AWS::Serverless::Api",
                    "Properties": {
                        "StageName": "Prod",
                        "DefinitionBody": make_swagger(self.input_apis, binary_media_types=self.binary_types)
                    }
                }
            }
        }

        expected_binary_types = sorted(self.binary_types)
        expected_apis = [
            Api(path="/path1", method="GET", function_name="SamFunc1", cors=None,
                binary_media_types=expected_binary_types, stage_name="Prod"),
            Api(path="/path1", method="POST", function_name="SamFunc1", cors=None,
                binary_media_types=expected_binary_types, stage_name="Prod"),

            Api(path="/path2", method="PUT", function_name="SamFunc1", cors=None,
                binary_media_types=expected_binary_types, stage_name="Prod"),
            Api(path="/path2", method="GET", function_name="SamFunc1", cors=None,
                binary_media_types=expected_binary_types, stage_name="Prod"),

            Api(path="/path3", method="DELETE", function_name="SamFunc1", cors=None,
                binary_media_types=expected_binary_types, stage_name="Prod")
        ]

        provider = SamApiProvider(template)
        assertCountEqual(self, expected_apis, provider.apis)
    def test_binary_media_types_with_rest_api_id_reference(self):
        events = {
            "Event1": {
                "Type": "Api",
                "Properties": {
                    "Path": "/connected-to-explicit-path",
                    "Method": "POST",
                    "RestApiId": "Api1"
                }
            },

            "Event2": {
                "Type": "Api",
                "Properties": {
                    "Path": "/true-implicit-path",
                    "Method": "POST"
                }
            }
        }

        # Binary type for implicit
        self.template["Globals"] = {
            "Api": {
                "BinaryMediaTypes": ["image~1gif", "image~1png"]
            }
        }
        self.template["Resources"]["ImplicitFunc"]["Properties"]["Events"] = events

        self.template["Resources"]["Api1"]["Properties"]["DefinitionBody"] = self.swagger
        # Binary type for explicit
        self.template["Resources"]["Api1"]["Properties"]["BinaryMediaTypes"] = ["explicit/type1", "explicit/type2"]

        # Because of Globals, binary types will be concatenated on the explicit API
        expected_explicit_binary_types = ["explicit/type1", "explicit/type2", "image/gif", "image/png"]
        expected_implicit_binary_types = ["image/gif", "image/png"]

        expected_apis = [
            # From Explicit APIs
            Api(path="/path1", method="GET", function_name="explicitfunction",
                binary_media_types=expected_explicit_binary_types, stage_name="Prod"),
            Api(path="/path2", method="GET", function_name="explicitfunction",
                binary_media_types=expected_explicit_binary_types, stage_name="Prod"),
            Api(path="/path3", method="GET", function_name="explicitfunction",
                binary_media_types=expected_explicit_binary_types, stage_name="Prod"),

            # Because of the RestApiId, Implicit APIs will also get the binary media types inherited from
            # the corresponding Explicit API
            Api(path="/connected-to-explicit-path", method="POST", function_name="ImplicitFunc",
                binary_media_types=expected_explicit_binary_types,
                stage_name="Prod"),

            # This is still just a true implicit API because it does not have RestApiId property
            Api(path="/true-implicit-path", method="POST", function_name="ImplicitFunc",
                binary_media_types=expected_implicit_binary_types,
                stage_name="Prod")
        ]

        provider = SamApiProvider(self.template)
        assertCountEqual(self, expected_apis, provider.apis)
    def test_must_prefer_implicit_with_any_method(self):
        implicit_apis = {
            "Event1": {
                "Type": "Api",
                "Properties": {
                    # This API is duplicated between implicit & explicit
                    "Path": "/path",
                    "Method": "ANY"
                }
            }
        }

        explicit_apis = [
            # Explicit should be over masked completely by implicit, because of "ANY"
            Api(path="/path", method="GET", function_name="explicitfunction", cors=None),
            Api(path="/path", method="DELETE", function_name="explicitfunction", cors=None),
        ]

        self.template["Resources"]["Api1"]["Properties"]["DefinitionBody"] = make_swagger(explicit_apis)
        self.template["Resources"]["ImplicitFunc"]["Properties"]["Events"] = implicit_apis

        expected_apis = [
            Api(path="/path", method="GET", function_name="ImplicitFunc", cors=None, stage_name="Prod"),
            Api(path="/path", method="POST", function_name="ImplicitFunc", cors=None, stage_name="Prod"),
            Api(path="/path", method="PUT", function_name="ImplicitFunc", cors=None, stage_name="Prod"),
            Api(path="/path", method="DELETE", function_name="ImplicitFunc", cors=None, stage_name="Prod"),
            Api(path="/path", method="HEAD", function_name="ImplicitFunc", cors=None, stage_name="Prod"),
            Api(path="/path", method="OPTIONS", function_name="ImplicitFunc", cors=None, stage_name="Prod"),
            Api(path="/path", method="PATCH", function_name="ImplicitFunc", cors=None, stage_name="Prod")
        ]

        provider = SamApiProvider(self.template)
        assertCountEqual(self, expected_apis, provider.apis)
    def test_both_apis_must_get_binary_media_types(self):
        events = {
            "Event1": {
                "Type": "Api",
                "Properties": {
                    "Path": "/newpath1",
                    "Method": "POST"
                }
            },

            "Event2": {
                "Type": "Api",
                "Properties": {
                    "Path": "/newpath2",
                    "Method": "POST"
                }
            }
        }

        # Binary type for implicit
        self.template["Globals"] = {
            "Api": {
                "BinaryMediaTypes": ["image~1gif", "image~1png"]
            }
        }
        self.template["Resources"]["ImplicitFunc"]["Properties"]["Events"] = events

        self.template["Resources"]["Api1"]["Properties"]["DefinitionBody"] = self.swagger
        # Binary type for explicit
        self.template["Resources"]["Api1"]["Properties"]["BinaryMediaTypes"] = ["explicit/type1", "explicit/type2"]

        # Because of Globals, binary types will be concatenated on the explicit API
        expected_explicit_binary_types = ["explicit/type1", "explicit/type2", "image/gif", "image/png"]
        expected_implicit_binary_types = ["image/gif", "image/png"]

        expected_apis = [
            # From Explicit APIs
            Api(path="/path1", method="GET", function_name="explicitfunction",
                binary_media_types=expected_explicit_binary_types, stage_name="Prod"),
            Api(path="/path2", method="GET", function_name="explicitfunction",
                binary_media_types=expected_explicit_binary_types, stage_name="Prod"),
            Api(path="/path3", method="GET", function_name="explicitfunction",
                binary_media_types=expected_explicit_binary_types, stage_name="Prod"),
            # From Implicit APIs
            Api(path="/newpath1", method="POST", function_name="ImplicitFunc",
                binary_media_types=expected_implicit_binary_types,
                stage_name="Prod"),
            Api(path="/newpath2", method="POST", function_name="ImplicitFunc",
                binary_media_types=expected_implicit_binary_types,
                stage_name="Prod")
        ]

        provider = SamApiProvider(self.template)
        assertCountEqual(self, expected_apis, provider.apis)
    def setUp(self):
        self.binary_types = ["image/png", "image/jpg"]
        self.input_apis = [
            Api(path="/path1", method="GET", function_name="SamFunc1", cors=None, stage_name="Prod"),
            Api(path="/path1", method="POST", function_name="SamFunc1", cors=None, stage_name="Prod"),

            Api(path="/path2", method="PUT", function_name="SamFunc1", cors=None, stage_name="Prod"),
            Api(path="/path2", method="GET", function_name="SamFunc1", cors=None, stage_name="Prod"),

            Api(path="/path3", method="DELETE", function_name="SamFunc1", cors=None, stage_name="Prod")
        ]
    def test_swagger_with_any_method(self):
        apis = [
            Api(path="/path", method="any", function_name="SamFunc1", cors=None)
        ]

        expected_apis = [
            Api(path="/path", method="GET", function_name="SamFunc1", cors=None, stage_name="Prod"),
            Api(path="/path", method="POST", function_name="SamFunc1", cors=None, stage_name="Prod"),
            Api(path="/path", method="PUT", function_name="SamFunc1", cors=None, stage_name="Prod"),
            Api(path="/path", method="DELETE", function_name="SamFunc1", cors=None, stage_name="Prod"),
            Api(path="/path", method="HEAD", function_name="SamFunc1", cors=None, stage_name="Prod"),
            Api(path="/path", method="OPTIONS", function_name="SamFunc1", cors=None, stage_name="Prod"),
            Api(path="/path", method="PATCH", function_name="SamFunc1", cors=None, stage_name="Prod")
        ]

        template = {
            "Resources": {
                "Api1": {
                    "Type": "AWS::Serverless::Api",
                    "Properties": {
                        "StageName": "Prod",
                        "DefinitionBody": make_swagger(apis)
                    }
                }
            }
        }

        provider = SamApiProvider(template)
        assertCountEqual(self, expected_apis, provider.apis)
    def test_provider_get_all(self):
        template = {
            "Resources": {

                "SamFunc1": {
                    "Type": "AWS::Serverless::Function",
                    "Properties": {
                        "CodeUri": "/usr/foo/bar",
                        "Runtime": "nodejs4.3",
                        "Handler": "index.handler",
                        "Events": {
                            "Event1": {
                                "Type": "Api",
                                "Properties": {
                                    "Path": "/path",
                                    "Method": "GET"
                                }
                            }
                        }
                    }
                },
                "SamFunc2": {
                    "Type": "AWS::Serverless::Function",
                    "Properties": {
                        "CodeUri": "/usr/foo/bar",
                        "Runtime": "nodejs4.3",
                        "Handler": "index.handler",
                        "Events": {
                            "Event1": {
                                "Type": "Api",
                                "Properties": {
                                    "Path": "/path",
                                    "Method": "POST"
                                }
                            }
                        }
                    }
                }
            }
        }

        provider = SamApiProvider(template)

        result = [f for f in provider.get_all()]

        api1 = Api(path="/path", method="GET", function_name="SamFunc1", stage_name="Prod")
        api2 = Api(path="/path", method="POST", function_name="SamFunc2", stage_name="Prod")

        self.assertIn(api1, result)
        self.assertIn(api2, result)
    def test_provider_has_correct_template(self):
        template = {
            "Resources": {

                "SamFunc1": {
                    "Type": "AWS::Serverless::Function",
                    "Properties": {
                        "CodeUri": "/usr/foo/bar",
                        "Runtime": "nodejs4.3",
                        "Handler": "index.handler",
                        "Events": {
                            "Event1": {
                                "Type": "Api",
                                "Properties": {
                                    "Path": "/path",
                                    "Method": "GET"
                                }
                            }
                        }
                    }
                },
                "SamFunc2": {
                    "Type": "AWS::Serverless::Function",
                    "Properties": {
                        "CodeUri": "/usr/foo/bar",
                        "Runtime": "nodejs4.3",
                        "Handler": "index.handler",
                        "Events": {
                            "Event1": {
                                "Type": "Api",
                                "Properties": {
                                    "Path": "/path",
                                    "Method": "POST"
                                }
                            }
                        }
                    }
                }
            }
        }

        provider = SamApiProvider(template)

        api1 = Api(path="/path", method="GET", function_name="SamFunc1", cors=None, stage_name="Prod")
        api2 = Api(path="/path", method="POST", function_name="SamFunc2", cors=None, stage_name="Prod")

        self.assertIn(api1, provider.apis)
        self.assertIn(api2, provider.apis)
示例#10
0
    def test_provider_has_correct_api(self, method):
        template = {
            "Resources": {

                "SamFunc1": {
                    "Type": "AWS::Serverless::Function",
                    "Properties": {
                        "CodeUri": "/usr/foo/bar",
                        "Runtime": "nodejs4.3",
                        "Handler": "index.handler",
                        "Events": {
                            "Event1": {
                                "Type": "Api",
                                "Properties": {
                                    "Path": "/path",
                                    "Method": method
                                }
                            }
                        }
                    }
                }
            }
        }

        provider = SamApiProvider(template)

        self.assertEquals(len(provider.apis), 1)
        self.assertEquals(list(provider.apis)[0], Api(path="/path", method="GET", function_name="SamFunc1", cors=None,
                                                      stage_name="Prod"))
示例#11
0
    def test_with_one_path_method(self):
        function_name = "myfunction"
        swagger = {
            "paths": {
                "/path1": {
                    "get": {
                        "x-amazon-apigateway-integration": {
                            "type": "aws_proxy",
                            "uri": "someuri"
                        }
                    }
                }
            }
        }

        parser = SwaggerParser(swagger)
        parser._get_integration_function_name = Mock()
        parser._get_integration_function_name.return_value = function_name

        expected = [Api(path="/path1", method="get", function_name=function_name, cors=None)]
        result = parser.get_apis()

        self.assertEquals(expected, result)
        parser._get_integration_function_name.assert_called_with({
            "x-amazon-apigateway-integration": {
                "type": "aws_proxy",
                "uri": "someuri"
            }
        })
示例#12
0
    def get_apis(self):
        """
        Parses a swagger document and returns a list of APIs configured in the document.

        Swagger documents have the following structure
        {
            "/path1": {    # path
                "get": {   # method
                    "x-amazon-apigateway-integration": {   # integration
                        "type": "aws_proxy",

                        # URI contains the Lambda function ARN that needs to be parsed to get Function Name
                        "uri": {
                            "Fn::Sub":
                                "arn:aws:apigateway:aws:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/..."
                        }
                    }
                },
                "post": {
                },
            },
            "/path2": {
                ...
            }
        }

        Returns
        -------
        list of samcli.commands.local.lib.provider.Api
            List of APIs that are configured in the Swagger document
        """

        result = []
        paths_dict = self.swagger.get("paths", {})

        binary_media_types = self.get_binary_media_types()

        for full_path, path_config in paths_dict.items():
            for method, method_config in path_config.items():

                function_name = self._get_integration_function_name(
                    method_config)
                if not function_name:
                    LOG.debug(
                        "Lambda function integration not found in Swagger document at path='%s' method='%s'",
                        full_path, method)
                    continue

                if method.lower() == self._ANY_METHOD_EXTENSION_KEY:
                    # Convert to a more commonly used method notation
                    method = self._ANY_METHOD

                api = Api(path=full_path,
                          method=method,
                          function_name=function_name,
                          cors=None,
                          binary_media_types=binary_media_types)
                result.append(api)

        return result
示例#13
0
    def _convert_event_api(lambda_logical_id, event_properties):
        """
        Converts a AWS::Serverless::Function's Event Property to an Api configuration usable by the provider.

        :param str lambda_logical_id: Logical Id of the AWS::Serverless::Function
        :param dict event_properties: Dictionary of the Event's Property
        :return tuple: tuple of API resource name and Api namedTuple
        """
        path = event_properties.get(SamApiProvider._EVENT_PATH)
        method = event_properties.get(SamApiProvider._EVENT_METHOD)

        # An API Event, can have RestApiId property which designates the resource that owns this API. If omitted,
        # the API is owned by Implicit API resource. This could either be a direct resource logical ID or a
        # "Ref" of the logicalID
        api_resource_id = event_properties.get(
            "RestApiId", SamApiProvider._IMPLICIT_API_RESOURCE_ID)
        if isinstance(api_resource_id, dict) and "Ref" in api_resource_id:
            api_resource_id = api_resource_id["Ref"]

        # This is still a dictionary. Something wrong with the template
        if isinstance(api_resource_id, dict):
            LOG.debug("Invalid RestApiId property of event %s",
                      event_properties)
            raise InvalidSamDocumentException(
                "RestApiId property of resource with logicalId '{}' is invalid. "
                "It should either be a LogicalId string or a Ref of a Logical Id string"
                .format(lambda_logical_id))

        return api_resource_id, Api(path=path,
                                    method=method,
                                    function_name=lambda_logical_id)
示例#14
0
 def test_initalize_with_values(self):
     lambda_runner = Mock()
     local_service = LocalApigwService(Api(), lambda_runner, static_dir="dir/static", port=5000, host="129.0.0.0")
     self.assertEqual(local_service.port, 5000)
     self.assertEqual(local_service.host, "129.0.0.0")
     self.assertEqual(local_service.api.routes, [])
     self.assertEqual(local_service.static_dir, "dir/static")
     self.assertEqual(local_service.lambda_runner, lambda_runner)
示例#15
0
    def setUp(self):
        self.host = "127.0.0.1"
        self.port = random.randint(30000, 40000)  # get a random port
        self.url = "http://{}:{}".format(self.host, self.port)

        self.code_abs_path = nodejs_lambda(API_GATEWAY_ECHO_EVENT)

        # Let's convert this absolute path to relative path. Let the parent be the CWD, and codeuri be the folder
        self.cwd = os.path.dirname(self.code_abs_path)
        self.code_uri = os.path.relpath(self.code_abs_path, self.cwd)  # Get relative path with respect to CWD

        # Setup a static file in the directory
        self.static_dir = "mystaticdir"
        self.static_file_name = "myfile.txt"
        self.static_file_content = "This is a static file"
        self._setup_static_file(
            os.path.join(self.cwd, self.static_dir),  # Create static directory with in cwd
            self.static_file_name,
            self.static_file_content,
        )

        # Create one Lambda function
        self.function_name = "name"
        self.function = provider.Function(
            name=self.function_name,
            runtime="nodejs4.3",
            memory=256,
            timeout=5,
            handler="index.handler",
            codeuri=self.code_uri,
            environment={},
            rolearn=None,
            layers=[],
        )
        self.mock_function_provider = Mock()
        self.mock_function_provider.get.return_value = self.function

        # Setup two APIs pointing to the same function
        routes = [
            Route(path="/get", methods=["GET"], function_name=self.function_name),
            Route(path="/post", methods=["POST"], function_name=self.function_name),
        ]
        api = Api(routes=routes)

        self.api_provider_mock = Mock()
        self.api_provider_mock.get_all.return_value = api

        # Now wire up the Lambda invoker and pass it through the context
        self.lambda_invoke_context_mock = Mock()
        manager = ContainerManager()
        layer_downloader = LayerDownloader("./", "./")
        lambda_image = LambdaImage(layer_downloader, False, False)
        local_runtime = LambdaRuntime(manager, lambda_image)
        lambda_runner = LocalLambdaRunner(local_runtime, self.mock_function_provider, self.cwd, debug_context=None)
        self.lambda_invoke_context_mock.local_lambda_runner = lambda_runner
        self.lambda_invoke_context_mock.get_cwd.return_value = self.cwd
示例#16
0
    def test_must_return_routing_list_from_apis(self):
        api_provider = Mock()
        apis = [
            Api(path="/1", method="GET1", function_name="name1", cors="CORS1"),
            Api(path="/2", method="GET2", function_name="name2", cors="CORS2"),
            Api(path="/3", method="GET3", function_name="name3", cors="CORS3"),
        ]
        expected = [
            Route(path="/1", methods=["GET1"], function_name="name1"),
            Route(path="/2", methods=["GET2"], function_name="name2"),
            Route(path="/3", methods=["GET3"], function_name="name3")
        ]

        api_provider.get_all.return_value = apis

        result = LocalApiService._make_routing_list(api_provider)
        self.assertEquals(len(result), len(expected))
        for index, r in enumerate(result):
            self.assertEquals(r.__dict__, expected[index].__dict__)
示例#17
0
    def test_with_combination_of_paths_methods(self):
        function_name = "myfunction"
        swagger = {
            "paths": {
                "/path1": {
                    "get": {
                        "x-amazon-apigateway-integration": {
                            "type": "aws_proxy",
                            "uri": "someuri"
                        }
                    },
                    "delete": {
                        "x-amazon-apigateway-integration": {
                            "type": "aws_proxy",
                            "uri": "someuri"
                        }
                    }
                },

                "/path2": {
                    "post": {
                        "x-amazon-apigateway-integration": {
                            "type": "aws_proxy",
                            "uri": "someuri"
                        }
                    }
                }
            }
        }

        parser = SwaggerParser(swagger)
        parser._get_integration_function_name = Mock()
        parser._get_integration_function_name.return_value = function_name

        expected = {
            Api(path="/path1", method="get", function_name=function_name, cors=None),
            Api(path="/path1", method="delete", function_name=function_name, cors=None),
            Api(path="/path2", method="post", function_name=function_name, cors=None),
        }
        result = parser.get_apis()

        self.assertEquals(expected, set(result))
    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"})
示例#19
0
    def setUp(self):
        self.function_name = Mock()
        self.api_gateway_route = Route(methods=["GET"], function_name=self.function_name, path="/")
        self.list_of_routes = [self.api_gateway_route]

        self.lambda_runner = Mock()
        self.lambda_runner.is_debugging.return_value = False

        self.stderr = Mock()
        self.api = Api(routes=self.list_of_routes)
        self.service = LocalApigwService(self.api, self.lambda_runner, port=3000, host="127.0.0.1", stderr=self.stderr)
示例#20
0
    def test_must_prefer_implicit_api_over_explicit(self):
        implicit_apis = {
            "Event1": {
                "Type": "Api",
                "Properties": {
                    # This API is duplicated between implicit & explicit
                    "Path": "/path1",
                    "Method": "get"
                }
            },

            "Event2": {
                "Type": "Api",
                "Properties": {
                    "Path": "/path2",
                    "Method": "POST"
                }
            }
        }

        self.template["Resources"]["Api1"]["Properties"]["DefinitionBody"] = self.swagger
        self.template["Resources"]["ImplicitFunc"]["Properties"]["Events"] = implicit_apis

        expected_apis = [
            Api(path="/path1", method="GET", function_name="ImplicitFunc", stage_name="Prod"),
            # Comes from Implicit

            Api(path="/path2", method="GET", function_name="explicitfunction", cors=None, stage_name="Prod"),
            Api(path="/path2", method="POST", function_name="ImplicitFunc", stage_name="Prod"),
            # Comes from implicit

            Api(path="/path3", method="GET", function_name="explicitfunction", cors=None, stage_name="Prod"),
        ]

        provider = SamApiProvider(self.template)
        assertCountEqual(self, expected_apis, provider.apis)
示例#21
0
    def test_must_add_explicit_api_when_ref_with_rest_api_id(self):
        events = {
            "Event1": {
                "Type": "Api",
                "Properties": {
                    "Path": "/newpath1",
                    "Method": "POST",
                    "RestApiId": "Api1"  # This path must get added to this API
                }
            },

            "Event2": {
                "Type": "Api",
                "Properties": {
                    "Path": "/newpath2",
                    "Method": "POST",
                    "RestApiId": {"Ref": "Api1"}  # This path must get added to this API
                }
            }
        }

        self.template["Resources"]["Api1"]["Properties"]["DefinitionBody"] = self.swagger
        self.template["Resources"]["ImplicitFunc"]["Properties"]["Events"] = events

        expected_apis = [
            # From Explicit APIs
            Api(path="/path1", method="GET", function_name="explicitfunction", cors=None, stage_name="Prod"),
            Api(path="/path2", method="GET", function_name="explicitfunction", cors=None, stage_name="Prod"),
            Api(path="/path3", method="GET", function_name="explicitfunction", cors=None, stage_name="Prod"),
            # From Implicit APIs
            Api(path="/newpath1", method="POST", function_name="ImplicitFunc", cors=None, stage_name="Prod"),
            Api(path="/newpath2", method="POST", function_name="ImplicitFunc", cors=None, stage_name="Prod")
        ]

        provider = SamApiProvider(self.template)
        assertCountEqual(self, expected_apis, provider.apis)
示例#22
0
    def test_create_creates_dict_of_routes(self):
        function_name_1 = Mock()
        function_name_2 = Mock()
        api_gateway_route_1 = Route(methods=["GET"], function_name=function_name_1, path="/")
        api_gateway_route_2 = Route(methods=["POST"], function_name=function_name_2, path="/")

        list_of_routes = [api_gateway_route_1, api_gateway_route_2]

        lambda_runner = Mock()

        api = Api(routes=list_of_routes)
        service = LocalApigwService(api, lambda_runner)

        service.create()

        self.assertEqual(service._dict_of_routes, {"/:GET": api_gateway_route_1, "/:POST": api_gateway_route_2})
示例#23
0
    def test_provider_must_support_binary_media_types_with_any_method(self):
        template = {
            "Globals": {
                "Api": {
                    "BinaryMediaTypes": [
                        "image~1gif",
                        "image~1png",
                        "text/html"
                    ]
                }
            },
            "Resources": {

                "SamFunc1": {
                    "Type": "AWS::Serverless::Function",
                    "Properties": {
                        "CodeUri": "/usr/foo/bar",
                        "Runtime": "nodejs4.3",
                        "Handler": "index.handler",
                        "Events": {
                            "Event1": {
                                "Type": "Api",
                                "Properties": {
                                    "Path": "/path",
                                    "Method": "any"
                                }
                            }
                        }
                    }
                }
            }
        }

        binary = ["image/gif", "image/png", "text/html"]

        expected_apis = [
            Api(path="/path", method="GET", function_name="SamFunc1", binary_media_types=binary, stage_name="Prod"),
            Api(path="/path", method="POST", function_name="SamFunc1", binary_media_types=binary, stage_name="Prod"),
            Api(path="/path", method="PUT", function_name="SamFunc1", binary_media_types=binary, stage_name="Prod"),
            Api(path="/path", method="DELETE", function_name="SamFunc1", binary_media_types=binary, stage_name="Prod"),
            Api(path="/path", method="HEAD", function_name="SamFunc1", binary_media_types=binary, stage_name="Prod"),
            Api(path="/path", method="OPTIONS", function_name="SamFunc1", binary_media_types=binary, stage_name="Prod"),
            Api(path="/path", method="PATCH", function_name="SamFunc1", binary_media_types=binary, stage_name="Prod")
        ]

        provider = SamApiProvider(template)

        assertCountEqual(self, provider.apis, expected_apis)
示例#24
0
    def test_provider_stage_variables(self):
        template = {
            "Resources": {

                "TestApi": {
                    "Type": "AWS::Serverless::Api",
                    "Properties": {
                        "StageName": "dev",
                        "Variables": {
                            "vis": "data",
                            "random": "test",
                            "foo": "bar"
                        },
                        "DefinitionBody": {
                            "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 = SamApiProvider(template)
        api1 = Api(path='/path', method='GET', function_name='NoApiEventFunction', cors=None, binary_media_types=[],
                   stage_name='dev',
                   stage_variables={
                       "vis": "data",
                       "random": "test",
                       "foo": "bar"
                   })

        self.assertIn(api1, provider.apis)
    def test_must_raise_if_route_not_available(self,
                                               extract_api,
                                               log_routes_mock,
                                               make_static_dir_mock,
                                               SamApiProviderMock,
                                               ApiGwServiceMock):
        routing_list = []  # Empty
        api = Api()
        extract_api.return_value = api
        SamApiProviderMock.extract_api.return_value = api
        SamApiProviderMock.return_value = self.api_provider_mock
        ApiGwServiceMock.return_value = self.apigw_service

        # Now start the service
        local_service = LocalApiService(self.lambda_invoke_context_mock, self.port, self.host, self.static_dir)
        local_service.api_provider.api.routes = routing_list
        with self.assertRaises(NoApisDefined):
            local_service.start()
示例#26
0
    def test_provider_must_support_binary_media_types(self):
        template = {
            "Globals": {
                "Api": {
                    "BinaryMediaTypes": [
                        "image~1gif",
                        "image~1png",
                        "image~1png",  # Duplicates must be ignored
                        {"Ref": "SomeParameter"}  # Refs are ignored as well
                    ]
                }
            },
            "Resources": {

                "SamFunc1": {
                    "Type": "AWS::Serverless::Function",
                    "Properties": {
                        "CodeUri": "/usr/foo/bar",
                        "Runtime": "nodejs4.3",
                        "Handler": "index.handler",
                        "Events": {
                            "Event1": {
                                "Type": "Api",
                                "Properties": {
                                    "Path": "/path",
                                    "Method": "get"
                                }
                            }
                        }
                    }
                }
            }
        }

        provider = SamApiProvider(template)

        self.assertEquals(len(provider.apis), 1)
        self.assertEquals(list(provider.apis)[0], Api(path="/path", method="GET", function_name="SamFunc1",
                                                      binary_media_types=["image/gif", "image/png"], cors=None,
                                                      stage_name="Prod"))
示例#27
0
    def test_provider_with_any_method(self, method):
        template = {
            "Resources": {

                "SamFunc1": {
                    "Type": "AWS::Serverless::Function",
                    "Properties": {
                        "CodeUri": "/usr/foo/bar",
                        "Runtime": "nodejs4.3",
                        "Handler": "index.handler",
                        "Events": {
                            "Event1": {
                                "Type": "Api",
                                "Properties": {
                                    "Path": "/path",
                                    "Method": method
                                }
                            }
                        }
                    }
                }
            }
        }

        provider = SamApiProvider(template)

        api_get = Api(path="/path", method="GET", function_name="SamFunc1", cors=None, stage_name="Prod")
        api_post = Api(path="/path", method="POST", function_name="SamFunc1", cors=None, stage_name="Prod")
        api_put = Api(path="/path", method="PUT", function_name="SamFunc1", cors=None, stage_name="Prod")
        api_delete = Api(path="/path", method="DELETE", function_name="SamFunc1", cors=None, stage_name="Prod")
        api_patch = Api(path="/path", method="PATCH", function_name="SamFunc1", cors=None, stage_name="Prod")
        api_head = Api(path="/path", method="HEAD", function_name="SamFunc1", cors=None, stage_name="Prod")
        api_options = Api(path="/path", method="OPTIONS", function_name="SamFunc1", cors=None, stage_name="Prod")

        self.assertEquals(len(provider.apis), 7)
        self.assertIn(api_get, provider.apis)
        self.assertIn(api_post, provider.apis)
        self.assertIn(api_put, provider.apis)
        self.assertIn(api_delete, provider.apis)
        self.assertIn(api_patch, provider.apis)
        self.assertIn(api_head, provider.apis)
        self.assertIn(api_options, provider.apis)
    def get_api(self):
        """
        Creates the api using the parts from the ApiCollector. The routes are also deduped so that there is no
        duplicate routes with the same function name, path, but different method.

        The normalised_routes are the routes that have been processed. By default, this will get all the routes.
        However, it can be changed to override the default value of normalised routes such as in SamApiProvider

        Return
        -------
        An Api object with all the properties
        """
        api = Api()
        routes = self.dedupe_function_routes(self.routes)
        routes = self.normalize_cors_methods(routes, self.cors)
        api.routes = routes
        api.binary_media_types_set = self.binary_media_types_set
        api.stage_name = self.stage_name
        api.stage_variables = self.stage_variables
        api.cors = self.cors
        return api
示例#29
0
    def test_must_union_implicit_and_explicit(self):
        events = {
            "Event1": {
                "Type": "Api",
                "Properties": {
                    "Path": "/path1",
                    "Method": "POST"
                }
            },

            "Event2": {
                "Type": "Api",
                "Properties": {
                    "Path": "/path2",
                    "Method": "POST"
                }
            },

            "Event3": {
                "Type": "Api",
                "Properties": {
                    "Path": "/path3",
                    "Method": "POST"
                }
            }
        }

        self.template["Resources"]["Api1"]["Properties"]["DefinitionBody"] = self.swagger
        self.template["Resources"]["ImplicitFunc"]["Properties"]["Events"] = events

        expected_apis = [
            # From Explicit APIs
            Api(path="/path1", method="GET", function_name="explicitfunction", cors=None, stage_name="Prod"),
            Api(path="/path2", method="GET", function_name="explicitfunction", cors=None, stage_name="Prod"),
            Api(path="/path3", method="GET", function_name="explicitfunction", cors=None, stage_name="Prod"),
            # From Implicit APIs
            Api(path="/path1", method="POST", function_name="ImplicitFunc", cors=None, stage_name="Prod"),
            Api(path="/path2", method="POST", function_name="ImplicitFunc", cors=None, stage_name="Prod"),
            Api(path="/path3", method="POST", function_name="ImplicitFunc", cors=None, stage_name="Prod")
        ]

        provider = SamApiProvider(self.template)
        assertCountEqual(self, expected_apis, provider.apis)
示例#30
0
    def test_multi_stage_get_all(self):
        template = {
            "Resources": {
                "TestApi": {
                    "Type": "AWS::Serverless::Api",
                    "Properties": {
                        "StageName": "dev",
                        "Variables": {
                            "vis": "data",
                            "random": "test",
                            "foo": "bar"
                        },
                        "DefinitionBody": {
                            "paths": {
                                "/path2": {
                                    "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": {},
                                        },
                                    }
                                }
                            }
                        }
                    }
                },
                "ProductionApi": {
                    "Type": "AWS::Serverless::Api",
                    "Properties": {
                        "StageName": "Production",
                        "Variables": {
                            "vis": "prod data",
                            "random": "test",
                            "foo": "bar"
                        },
                        "DefinitionBody": {
                            "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": {},
                                        },
                                    }
                                }

                            }
                        }
                    }
                }
            }
        }

        provider = SamApiProvider(template)

        result = [f for f in provider.get_all()]

        api1 = Api(path='/path2', method='GET', function_name='NoApiEventFunction', cors=None, binary_media_types=[],
                   stage_name='dev',
                   stage_variables={
                       "vis": "data",
                       "random": "test",
                       "foo": "bar"
                   })
        api2 = Api(path='/path', method='GET', function_name='NoApiEventFunction', cors=None, binary_media_types=[],
                   stage_name='Production', stage_variables={'vis': 'prod data', 'random': 'test', 'foo': 'bar'})
        api3 = Api(path='/anotherpath', method='POST', function_name='NoApiEventFunction', cors=None,
                   binary_media_types=[],
                   stage_name='Production',
                   stage_variables={
                       "vis": "prod data",
                       "random": "test",
                       "foo": "bar"
                   })
        self.assertEquals(len(result), 3)
        self.assertIn(api1, result)
        self.assertIn(api2, result)
        self.assertIn(api3, result)