def test_request_handler_returns_process_stdout_when_making_response(self, request_mock, lambda_output_parser_mock,
                                                                         service_response_mock):
        request_mock.get_data.return_value = b'{}'

        lambda_logs = "logs"
        lambda_response = "response"
        is_customer_error = False
        lambda_output_parser_mock.get_lambda_output.return_value = lambda_response, lambda_logs, is_customer_error

        service_response_mock.return_value = 'request response'

        lambda_runner_mock = Mock()
        stderr_mock = Mock()
        service = LocalLambdaInvokeService(lambda_runner=lambda_runner_mock,
                                           port=3000,
                                           host='localhost',
                                           stderr=stderr_mock)

        result = service._invoke_request_handler(function_name='HelloWorld')

        self.assertEquals(result, 'request response')
        lambda_output_parser_mock.get_lambda_output.assert_called_with(ANY)

        # Make sure the logs are written to stderr
        stderr_mock.write.assert_called_with(lambda_logs)
Exemple #2
0
    def test_invoke_request_handler_with_lambda_that_errors(
            self, request_mock, lambda_output_parser_mock,
            service_response_mock):
        lambda_output_parser_mock.get_lambda_output.return_value = 'hello world', None, True
        service_response_mock.return_value = 'request response'
        request_mock.get_data.return_value = b'{}'

        lambda_runner_mock = Mock()
        service = LocalLambdaInvokeService(lambda_runner=lambda_runner_mock,
                                           port=3000,
                                           host='localhost')

        response = service._invoke_request_handler(function_name='HelloWorld')

        self.assertEquals(response, 'request response')

        lambda_runner_mock.invoke.assert_called_once_with('HelloWorld',
                                                          '{}',
                                                          stdout=ANY,
                                                          stderr=None)
        service_response_mock.assert_called_once_with(
            'hello world', {
                'Content-Type': 'application/json',
                'x-amz-function-error': 'Unhandled'
            }, 200)
Exemple #3
0
    def test_request_handler_returns_process_stdout_when_making_response(
            self, lambda_output_parser_mock, service_response_mock):
        request_mock = Mock()
        request_mock.get_data.return_value = b"{}"
        local_lambda_invoke_service.request = request_mock

        lambda_logs = "logs"
        lambda_response = "response"
        is_customer_error = False
        lambda_output_parser_mock.get_lambda_output.return_value = lambda_response, lambda_logs, is_customer_error

        service_response_mock.return_value = "request response"

        lambda_runner_mock = Mock()
        stderr_mock = Mock()
        service = LocalLambdaInvokeService(lambda_runner=lambda_runner_mock,
                                           port=3000,
                                           host="localhost",
                                           stderr=stderr_mock)

        result = service._invoke_request_handler(function_name="HelloWorld")

        self.assertEqual(result, "request response")
        lambda_output_parser_mock.get_lambda_output.assert_called_with(ANY)

        # Make sure the logs are written to stderr
        stderr_mock.write.assert_called_with(lambda_logs)
Exemple #4
0
    def test_invoke_request_handler(self, lambda_output_parser_mock,
                                    service_response_mock):
        lambda_output_parser_mock.get_lambda_output.return_value = "hello world", None, False
        service_response_mock.return_value = "request response"

        request_mock = Mock()
        request_mock.get_data.return_value = b"{}"

        local_lambda_invoke_service.request = request_mock

        lambda_runner_mock = Mock()
        service = LocalLambdaInvokeService(lambda_runner=lambda_runner_mock,
                                           port=3000,
                                           host="localhost")

        response = service._invoke_request_handler(function_name="HelloWorld")

        self.assertEqual(response, "request response")

        lambda_runner_mock.invoke.assert_called_once_with("HelloWorld",
                                                          "{}",
                                                          stdout=ANY,
                                                          stderr=None)
        service_response_mock.assert_called_once_with(
            "hello world", {"Content-Type": "application/json"}, 200)
Exemple #5
0
    def test_invoke_request_handler_on_incorrect_path(
            self, lambda_error_responses_mock):
        request_mock = Mock()
        request_mock.get_data.return_value = b"{}"
        local_lambda_invoke_service.request = request_mock

        lambda_runner_mock = Mock()
        lambda_runner_mock.invoke.side_effect = FunctionNotFound

        lambda_error_responses_mock.resource_not_found.return_value = "Couldn't find Lambda"

        service = LocalLambdaInvokeService(lambda_runner=lambda_runner_mock,
                                           port=3000,
                                           host="localhost")

        response = service._invoke_request_handler(function_name="NotFound")

        self.assertEqual(response, "Couldn't find Lambda")

        lambda_runner_mock.invoke.assert_called_once_with("NotFound",
                                                          "{}",
                                                          stdout=ANY,
                                                          stderr=None)

        lambda_error_responses_mock.resource_not_found.assert_called_once_with(
            "NotFound")
    def test_invoke_request_handler(self, request_mock, lambda_output_parser_mock, service_response_mock):
        lambda_output_parser_mock.get_lambda_output.return_value = 'hello world', None, False
        service_response_mock.return_value = 'request response'
        request_mock.get_data.return_value = b'{}'

        lambda_runner_mock = Mock()
        service = LocalLambdaInvokeService(lambda_runner=lambda_runner_mock, port=3000, host='localhost')

        response = service._invoke_request_handler(function_name='HelloWorld')

        self.assertEquals(response, 'request response')

        lambda_runner_mock.invoke.assert_called_once_with('HelloWorld', '{}', stdout=ANY, stderr=None)
        service_response_mock.assert_called_once_with('hello world', {'Content-Type': 'application/json'}, 200)
    def test_construct_error_handling(self, lambda_error_response_mock):
        service = LocalLambdaInvokeService(lambda_runner=Mock(),
                                           port=3000,
                                           host='localhost',
                                           stderr=Mock())

        flask_app_mock = Mock()
        service._app = flask_app_mock
        service._construct_error_handling()

        flask_app_mock.register_error_handler.assert_has_calls([
            call(500, lambda_error_response_mock.generic_service_exception),
            call(404, lambda_error_response_mock.generic_path_not_found),
            call(405, lambda_error_response_mock.generic_method_not_allowed)])
    def test_construct_error_handling(self, lambda_error_response_mock):
        service = LocalLambdaInvokeService(lambda_runner=Mock(),
                                           port=3000,
                                           host='localhost',
                                           stderr=Mock())

        flask_app_mock = Mock()
        service._app = flask_app_mock
        service._construct_error_handling()

        flask_app_mock.register_error_handler.assert_has_calls([
            call(500, lambda_error_response_mock.generic_service_exception),
            call(404, lambda_error_response_mock.generic_path_not_found),
            call(405, lambda_error_response_mock.generic_method_not_allowed)])
    def test_create_service_endpoints(self, flask_mock, error_handling_mock):
        app_mock = Mock()
        flask_mock.return_value = app_mock

        error_handling_mock.return_value = Mock()

        lambda_runner_mock = Mock()
        service = LocalLambdaInvokeService(lambda_runner=lambda_runner_mock, port=3000, host='localhost')

        service.create()

        app_mock.add_url_rule.assert_called_once_with('/2015-03-31/functions/<function_name>/invocations',
                                                      endpoint='/2015-03-31/functions/<function_name>/invocations',
                                                      view_func=service._invoke_request_handler,
                                                      methods=['POST'],
                                                      provide_automatic_options=False)
    def test_create_service_endpoints(self, flask_mock, error_handling_mock):
        app_mock = Mock()
        flask_mock.return_value = app_mock

        error_handling_mock.return_value = Mock()

        lambda_runner_mock = Mock()
        service = LocalLambdaInvokeService(lambda_runner=lambda_runner_mock, port=3000, host='localhost')

        service.create()

        app_mock.add_url_rule.assert_called_once_with('/2015-03-31/functions/<function_name>/invocations',
                                                      endpoint='/2015-03-31/functions/<function_name>/invocations',
                                                      view_func=service._invoke_request_handler,
                                                      methods=['POST'],
                                                      provide_automatic_options=False)
 def test_initalize_creates_default_values(self):
     lambda_runner_mock = Mock()
     service = LocalLambdaInvokeService(lambda_runner=lambda_runner_mock, port=3001, host='127.0.0.1')
     self.assertEquals(service.port, 3001)
     self.assertEquals(service.host, '127.0.0.1')
     self.assertEquals(service.lambda_runner, lambda_runner_mock)
     self.assertIsNone(service.stderr)
    def test_invoke_request_handler_on_incorrect_path(self, request_mock, lambda_error_responses_mock):
        request_mock.get_data.return_value = b'{}'
        lambda_runner_mock = Mock()
        lambda_runner_mock.invoke.side_effect = FunctionNotFound

        lambda_error_responses_mock.resource_not_found.return_value = "Couldn't find Lambda"

        service = LocalLambdaInvokeService(lambda_runner=lambda_runner_mock, port=3000, host='localhost')

        response = service._invoke_request_handler(function_name='NotFound')

        self.assertEquals(response, "Couldn't find Lambda")

        lambda_runner_mock.invoke.assert_called_once_with('NotFound', '{}', stdout=ANY, stderr=None)

        lambda_error_responses_mock.resource_not_found.assert_called_once_with('NotFound')
 def test_initalize_with_values(self):
     lambda_runner_mock = Mock()
     stderr_mock = Mock()
     local_service = LocalLambdaInvokeService(lambda_runner_mock, port=5000, host='129.0.0.0', stderr=stderr_mock)
     self.assertEquals(local_service.port, 5000)
     self.assertEquals(local_service.host, '129.0.0.0')
     self.assertEquals(local_service.stderr, stderr_mock)
     self.assertEquals(local_service.lambda_runner, lambda_runner_mock)
    def test_request_with_no_data(self, flask_request):
        flask_request.get_data.return_value = None
        flask_request.headers = {}
        flask_request.content_type = 'application/json'
        flask_request.args = {}

        response = LocalLambdaInvokeService.validate_request()

        self.assertIsNone(response)
    def test_request_with_no_data(self, flask_request):
        flask_request.get_data.return_value = None
        flask_request.headers = {}
        flask_request.content_type = 'application/json'
        flask_request.args = {}

        response = LocalLambdaInvokeService.validate_request()

        self.assertIsNone(response)
Exemple #16
0
    def start(self):
        """
        Creates and starts the Local Lambda Invoke service. This method will block until the service is stopped
        manually using an interrupt. After the service is started, callers can make HTTP requests to the endpoint
        to invoke the Lambda function and receive a response.

        NOTE: This is a blocking call that will not return until the thread is interrupted with SIGINT/SIGTERM
        """

        # We care about passing only stderr to the Service and not stdout because stdout from Docker container
        # contains the response to the API which is sent out as HTTP response. Only stderr needs to be printed
        # to the console or a log file. stderr from Docker container contains runtime logs and output of print
        # statements from the Lambda function
        service = LocalLambdaInvokeService(lambda_runner=self.lambda_runner,
                                           port=self.port,
                                           host=self.host,
                                           stderr=self.stderr_stream)

        service.create()

        LOG.info(
            "Starting the Local Lambda Service. You can now invoke your Lambda Functions defined in your template"
            " through the endpoint.")

        service.run()
Exemple #17
0
def make_service(function_provider, cwd):
    port = random_port()
    manager = ContainerManager()
    layer_downloader = LayerDownloader("./", "./")
    image_builder = LambdaImage(layer_downloader, False, False)
    local_runtime = LambdaRuntime(manager, image_builder)
    lambda_runner = LocalLambdaRunner(local_runtime=local_runtime, function_provider=function_provider, cwd=cwd)

    service = LocalLambdaInvokeService(lambda_runner, port=port, host="127.0.0.1")

    scheme = "http"
    url = "{}://127.0.0.1:{}".format(scheme, port)
    return service, port, url, scheme
    def test_request_invocation_type_not_ResponseRequest(self, flask_request, lambda_error_responses_mock):
        flask_request.get_data.return_value = None
        flask_request.headers = {'X-Amz-Invocation-Type': 'DryRun'}
        flask_request.content_type = 'application/json'
        flask_request.args = {}

        lambda_error_responses_mock.not_implemented_locally.return_value = "NotImplementedLocally"

        response = LocalLambdaInvokeService.validate_request()

        self.assertEquals(response, "NotImplementedLocally")

        lambda_error_responses_mock.not_implemented_locally.assert_called_once_with(
            "invocation-type: DryRun is not supported. RequestResponse is only supported.")
    def test_request_with_query_strings(self, flask_request, lambda_error_responses_mock):
        flask_request.get_data.return_value = None
        flask_request.headers = {}
        flask_request.content_type = 'application/json'
        flask_request.args = {"key": "value"}

        lambda_error_responses_mock.invalid_request_content.return_value = "InvalidRequestContent"

        response = LocalLambdaInvokeService.validate_request()

        self.assertEquals(response, "InvalidRequestContent")

        lambda_error_responses_mock.invalid_request_content.assert_called_once_with(
            "Query Parameters are not supported")
    def test_request_invocation_type_not_ResponseRequest(self, flask_request, lambda_error_responses_mock):
        flask_request.get_data.return_value = None
        flask_request.headers = {'X-Amz-Invocation-Type': 'DryRun'}
        flask_request.content_type = 'application/json'
        flask_request.args = {}

        lambda_error_responses_mock.not_implemented_locally.return_value = "NotImplementedLocally"

        response = LocalLambdaInvokeService.validate_request()

        self.assertEquals(response, "NotImplementedLocally")

        lambda_error_responses_mock.not_implemented_locally.assert_called_once_with(
            "invocation-type: DryRun is not supported. RequestResponse is only supported.")
    def test_request_with_content_type_not_application_json(self, flask_request, lambda_error_responses_mock):
        flask_request.get_data.return_value = None
        flask_request.headers = {}
        flask_request.content_type = 'image/gif'
        flask_request.args = {}

        lambda_error_responses_mock.unsupported_media_type.return_value = "UnsupportedMediaType"

        response = LocalLambdaInvokeService.validate_request()

        self.assertEquals(response, "UnsupportedMediaType")

        lambda_error_responses_mock.unsupported_media_type.assert_called_once_with(
            "image/gif")
    def test_request_with_query_strings(self, flask_request, lambda_error_responses_mock):
        flask_request.get_data.return_value = None
        flask_request.headers = {}
        flask_request.content_type = 'application/json'
        flask_request.args = {"key": "value"}

        lambda_error_responses_mock.invalid_request_content.return_value = "InvalidRequestContent"

        response = LocalLambdaInvokeService.validate_request()

        self.assertEquals(response, "InvalidRequestContent")

        lambda_error_responses_mock.invalid_request_content.assert_called_once_with(
            "Query Parameters are not supported")
    def test_request_with_non_json_data(self, flask_request, lambda_error_responses_mock):
        flask_request.get_data.return_value = b'notat:asdfasdf'
        flask_request.headers = {}
        flask_request.content_type = 'application/json'
        flask_request.args = {}

        lambda_error_responses_mock.invalid_request_content.return_value = "InvalidRequestContent"

        response = LocalLambdaInvokeService.validate_request()

        self.assertEquals(response, "InvalidRequestContent")

        expected_called_with = "Could not parse request body into json: No JSON object could be decoded"

        lambda_error_responses_mock.invalid_request_content.assert_called_once_with(expected_called_with)
Exemple #24
0
    def test_request_log_type_not_None(self, flask_request,
                                       lambda_error_responses_mock):
        flask_request.get_data.return_value = None
        flask_request.headers = {"X-Amz-Log-Type": "Tail"}
        flask_request.content_type = "application/json"
        flask_request.args = {}

        lambda_error_responses_mock.not_implemented_locally.return_value = "NotImplementedLocally"

        response = LocalLambdaInvokeService.validate_request()

        self.assertEqual(response, "NotImplementedLocally")

        lambda_error_responses_mock.not_implemented_locally.assert_called_once_with(
            "log-type: Tail is not supported. None is only supported.")
Exemple #25
0
def make_service(function_provider, cwd):
    port = random_port()
    manager = ContainerManager()
    local_runtime = LambdaRuntime(manager)
    lambda_runner = LocalLambdaRunner(local_runtime=local_runtime,
                                      function_provider=function_provider,
                                      cwd=cwd)

    service = LocalLambdaInvokeService(lambda_runner,
                                       port=port,
                                       host='127.0.0.1')

    scheme = "http"
    url = '{}://127.0.0.1:{}'.format(scheme, port)
    return service, port, url, scheme
    def test_request_with_non_json_data(self, flask_request, lambda_error_responses_mock):
        flask_request.get_data.return_value = b'notat:asdfasdf'
        flask_request.headers = {}
        flask_request.content_type = 'application/json'
        flask_request.args = {}

        lambda_error_responses_mock.invalid_request_content.return_value = "InvalidRequestContent"

        response = LocalLambdaInvokeService.validate_request()

        self.assertEquals(response, "InvalidRequestContent")

        expected_called_with = "Could not parse request body into json: No JSON object could be decoded"

        lambda_error_responses_mock.invalid_request_content.assert_called_once_with(expected_called_with)
    def start(self):
        """
        Creates and starts the Local Lambda Invoke service. This method will block until the service is stopped
        manually using an interrupt. After the service is started, callers can make HTTP requests to the endpoint
        to invoke the Lambda function and receive a response.

        NOTE: This is a blocking call that will not return until the thread is interrupted with SIGINT/SIGTERM
        """

        # We care about passing only stderr to the Service and not stdout because stdout from Docker container
        # contains the response to the API which is sent out as HTTP response. Only stderr needs to be printed
        # to the console or a log file. stderr from Docker container contains runtime logs and output of print
        # statements from the Lambda function
        service = LocalLambdaInvokeService(lambda_runner=self.lambda_runner,
                                           port=self.port,
                                           host=self.host,
                                           stderr=self.stderr_stream)

        service.create()

        LOG.info("Starting the Local Lambda Service. You can now invoke your Lambda Functions defined in your template"
                 " through the endpoint.")

        service.run()