def test_must_run_container_and_wait_for_logs(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        timer = Mock()
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir(
            self.code_path).__enter__.return_value = code_dir

        # Configure interrupt handler
        self.runtime._configure_interrupt = Mock()
        self.runtime._configure_interrupt.return_value = timer

        LambdaContainerMock.return_value = container

        self.runtime.invoke(self.func_config,
                            event,
                            debug_context=debug_options,
                            stdout=stdout,
                            stderr=stderr)

        # Verify if Lambda Event data is set
        self.env_vars.add_lambda_event_body.assert_called_with(event)

        # Make sure env-vars get resolved
        self.env_vars.resolve.assert_called_with()

        # Make sure the context manager is called to return the code directory
        self.runtime._get_code_dir.assert_called_with(self.code_path)

        # Make sure the container is created with proper values
        LambdaContainerMock.assert_called_with(
            self.lang,
            self.handler,
            code_dir,
            self.layers,
            lambda_image_mock,
            memory_mb=self.DEFAULT_MEMORY,
            env_vars=self.env_var_value,
            debug_options=debug_options,
        )

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)
        self.runtime._configure_interrupt.assert_called_with(
            self.name, self.DEFAULT_TIMEOUT, container, True)
        container.wait_for_logs.assert_called_with(stdout=stdout,
                                                   stderr=stderr)

        # Finally block
        timer.cancel.assert_called_with()
        self.manager_mock.stop.assert_called_with(container)
Esempio n. 2
0
    def test_keyboard_interrupt_must_not_raise(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        layer_downloader = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, layer_downloader)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir
        self.runtime._configure_interrupt = Mock()

        LambdaContainerMock.return_value = container

        self.manager_mock.run.side_effect = KeyboardInterrupt("some exception")

        self.runtime.invoke(self.func_config,
                            event,
                            stdout=stdout,
                            stderr=stderr)

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)

        self.runtime._configure_interrupt.assert_not_called()

        # Finally block must be called
        self.manager_mock.stop.assert_called_with(container)
Esempio n. 3
0
    def test_exception_from_run_must_trigger_cleanup(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        timer = Mock()
        layer_downloader = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, layer_downloader)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir.return_value = code_dir
        self.runtime._configure_interrupt = Mock()
        self.runtime._configure_interrupt.return_value = timer

        LambdaContainerMock.return_value = container
        container.is_running.return_value = False

        self.manager_mock.run.side_effect = ValueError("some exception")

        with self.assertRaises(ValueError):
            self.runtime.invoke(self.func_config, event, debug_context=None, stdout=stdout, stderr=stderr)

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)

        self.runtime._configure_interrupt.assert_not_called()

        # Finally block must be called
        # But timer was not yet created. It should not be called
        timer.cancel.assert_not_called()
        # In any case, stop the container
        self.manager_mock.stop.assert_called_with(container)
Esempio n. 4
0
    def setUp(self):
        self.name = "name"
        self.timeout = 123
        self.container = Mock()

        self.manager_mock = Mock()
        self.runtime = LambdaRuntime(self.manager_mock)
Esempio n. 5
0
    def setUp(self):
        self.code_dir = {
            "echo": nodejs_lambda(ECHO_CODE),
            "sleep": nodejs_lambda(SLEEP_CODE),
            "envvar": nodejs_lambda(GET_ENV_VAR)
        }

        self.container_manager = ContainerManager()
        self.runtime = LambdaRuntime(self.container_manager)
Esempio n. 6
0
    def test_must_run_container_and_wait_for_result(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        timer = Mock()
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir.return_value = code_dir

        self.runtime._clean_decompressed_paths = MagicMock()

        # Configure interrupt handler
        self.runtime._configure_interrupt = Mock()
        self.runtime._configure_interrupt.return_value = timer

        LambdaContainerMock.return_value = container
        container.is_running.return_value = False

        self.runtime.invoke(self.func_config, event, debug_context=debug_options, stdout=stdout, stderr=stderr)

        # Make sure env-vars get resolved
        self.env_vars.resolve.assert_called_with()

        # Make sure the context manager is called to return the code directory
        self.runtime._get_code_dir.assert_called_with(self.code_path)

        # Make sure the container is created with proper values
        LambdaContainerMock.assert_called_with(
            self.lang,
            self.imageuri,
            self.handler,
            self.packagetype,
            self.imageconfig,
            code_dir,
            self.layers,
            lambda_image_mock,
            debug_options=debug_options,
            env_vars=self.env_var_value,
            memory_mb=self.DEFAULT_MEMORY,
        )

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)
        self.runtime._configure_interrupt.assert_called_with(self.name, self.DEFAULT_TIMEOUT, container, True)
        container.wait_for_result.assert_called_with(event=event, name=self.name, stdout=stdout, stderr=stderr)

        # Finally block
        timer.cancel.assert_called_with()
        self.manager_mock.stop.assert_called_with(container)
        self.runtime._clean_decompressed_paths.assert_called_with()
Esempio n. 7
0
    def test_must_skip_run_running_container(self):
        container = Mock()
        container.is_running.return_value = True
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        self.runtime.run(container, self.func_config, debug_context=debug_options)
        self.manager_mock.run.assert_not_called()
Esempio n. 8
0
    def setUp(self):
        self.code_dir = {
            "echo": nodejs_lambda(ECHO_CODE),
            "sleep": nodejs_lambda(SLEEP_CODE),
            "envvar": nodejs_lambda(GET_ENV_VAR)
        }

        self.container_manager = ContainerManager()
        layer_downloader = LayerDownloader("./", "./")
        self.lambda_image = LambdaImage(layer_downloader, False, False)
        self.runtime = LambdaRuntime(self.container_manager, self.lambda_image)
Esempio n. 9
0
    def test_keyboard_interrupt_must_raise(self):
        container = Mock()
        container.is_running.return_value = False
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        self.manager_mock.run.side_effect = KeyboardInterrupt("some exception")

        with self.assertRaises(KeyboardInterrupt):
            self.runtime.run(container, self.func_config, debug_context=debug_options)
Esempio n. 10
0
class TestLambdaRuntime_get_code_dir(TestCase):

    def setUp(self):
        self.manager_mock = Mock()
        self.layer_downloader = Mock()
        self.runtime = LambdaRuntime(self.manager_mock, self.layer_downloader)

    @parameterized.expand([
        (".zip"),
        (".ZIP"),
        (".JAR"),
        (".jar")
    ])
    @patch("samcli.local.lambdafn.runtime.os")
    @patch("samcli.local.lambdafn.runtime.shutil")
    @patch("samcli.local.lambdafn.runtime._unzip_file")
    def test_must_uncompress_zip_files(self, extension, unzip_file_mock, shutil_mock, os_mock):
        code_path = "foo" + extension
        decompressed_dir = "decompressed-dir"

        unzip_file_mock.return_value = decompressed_dir
        os_mock.path.isfile.return_value = True

        with self.runtime._get_code_dir(code_path) as result:
            self.assertEquals(result, decompressed_dir)

        unzip_file_mock.assert_called_with(code_path)
        os_mock.path.isfile.assert_called_with(code_path)

        # Finally block must call this after the context manager exists
        shutil_mock.rmtree.assert_called_with(decompressed_dir)

    @patch("samcli.local.lambdafn.runtime.os")
    @patch("samcli.local.lambdafn.runtime.shutil")
    @patch("samcli.local.lambdafn.runtime._unzip_file")
    def test_must_return_a_valid_file(self, unzip_file_mock, shutil_mock, os_mock):
        """
        Input is a file that exists, but is not a zip/jar file
        """
        code_path = "foo.exe"

        os_mock.path.isfile.return_value = True

        with self.runtime._get_code_dir(code_path) as result:
            # code path must be returned. No decompression
            self.assertEquals(result, code_path)

        unzip_file_mock.assert_not_called()  # Unzip must not be called
        os_mock.path.isfile.assert_called_with(code_path)

        # Because we never unzipped anything, we should never delete
        shutil_mock.rmtree.assert_not_called()
Esempio n. 11
0
    def test_must_create_container_first_if_passed_container_is_none(self):
        container = Mock()
        container.is_running.return_value = False
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)
        create_mock = Mock()
        self.runtime.create = create_mock
        create_mock.return_value = container

        self.runtime.run(None, self.func_config, debug_context=debug_options)
        create_mock.assert_called_with(self.func_config, debug_options)
        self.manager_mock.run.assert_called_with(container)
Esempio n. 12
0
    def test_must_run_passed_container(self):
        event = "event"
        container = Mock()
        container.is_running.return_value = False
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        self.runtime.run(container,
                         self.func_config,
                         debug_context=debug_options,
                         event=event)
        self.manager_mock.run.assert_called_with(container)
Esempio n. 13
0
    def test_must_invoke(self):
        input_event = '"some data"'
        expected_env_vars = {
            "var1": "override_value1",
            "var2": "shell_env_value2"
        }

        manager = ContainerManager()
        local_runtime = LambdaRuntime(manager)
        runner = LocalLambdaRunner(local_runtime, self.mock_function_provider, self.cwd, self.env_var_overrides,
                                   debug_args=None, debug_port=None, aws_profile=None)

        # Append the real AWS credentials to the expected values.
        creds = runner.get_aws_creds()
        # default value for creds is not configured by the test. But coming from a downstream class
        expected_env_vars["AWS_SECRET_ACCESS_KEY"] = creds.get("secret", "defaultsecret")
        expected_env_vars["AWS_ACCESS_KEY_ID"] = creds.get("key", "defaultkey")
        expected_env_vars["AWS_REGION"] = creds.get("region", "us-east-1")

        stdout_stream = io.BytesIO()
        stderr_stream = io.BytesIO()
        runner.invoke(self.function_name, input_event, stdout=stdout_stream, stderr=stderr_stream)

        # stderr is where the Lambda container runtime logs are available. It usually contains requestId, start time
        # etc. So it is non-zero in size
        self.assertGreater(len(stderr_stream.getvalue().strip()), 0, "stderr stream must contain data")

        # This should contain all the environment variables passed to the function
        actual_output = json.loads(stdout_stream.getvalue().strip().decode('utf-8'))

        for key, value in expected_env_vars.items():
            self.assertTrue(key in actual_output, "Key '{}' must be in function output".format(key))
            self.assertEquals(actual_output.get(key), value)
Esempio n. 14
0
    def setUp(self):
        self.code_dir = nodejs_lambda(SLEEP_CODE)

        Input = namedtuple('Input', ["timeout", "sleep", "check_stdout"])
        self.inputs = [
            Input(sleep=1, timeout=10, check_stdout=True),
            Input(sleep=2, timeout=10, check_stdout=True),
            Input(sleep=3, timeout=10, check_stdout=True),
            Input(sleep=5, timeout=10, check_stdout=True),
            Input(sleep=8, timeout=10, check_stdout=True),
            Input(sleep=13, timeout=12, check_stdout=False),  # Must timeout
            Input(sleep=21, timeout=20, check_stdout=False),  # Must timeout. So stdout will be empty
        ]
        random.shuffle(self.inputs)

        container_manager = ContainerManager()
        self.runtime = LambdaRuntime(container_manager)
Esempio n. 15
0
    def setUp(self):
        self.name = "name"
        self.timeout = 123
        self.container = Mock()

        self.manager_mock = Mock()
        self.layer_downloader = Mock()
        self.runtime = LambdaRuntime(self.manager_mock, self.layer_downloader)
Esempio n. 16
0
    def test_must_create_lambda_container(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"

        container = Mock()
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir.return_value = code_dir

        LambdaContainerMock.return_value = container

        self.runtime.create(self.func_config,
                            debug_context=debug_options,
                            event=event)

        # Verify if Lambda Event data is set
        self.env_vars.add_lambda_event_body.assert_called_with(event)

        # Make sure env-vars get resolved
        self.env_vars.resolve.assert_called_with()

        # Make sure the context manager is called to return the code directory
        self.runtime._get_code_dir.assert_called_with(self.code_path)

        # Make sure the container is created with proper values
        LambdaContainerMock.assert_called_with(
            self.lang,
            self.imageuri,
            self.handler,
            self.packagetype,
            self.imageconfig,
            code_dir,
            self.layers,
            lambda_image_mock,
            debug_options=debug_options,
            env_vars=self.env_var_value,
            memory_mb=self.DEFAULT_MEMORY,
        )
        # Run the container and get results
        self.manager_mock.create.assert_called_with(container)
Esempio n. 17
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
Esempio n. 18
0
    def setUp(self):
        self.code_dir = nodejs_lambda(SLEEP_CODE)

        Input = namedtuple("Input", ["timeout", "sleep", "check_stdout"])
        self.inputs = [
            Input(sleep=1, timeout=10, check_stdout=True),
            Input(sleep=2, timeout=10, check_stdout=True),
            Input(sleep=3, timeout=10, check_stdout=True),
            Input(sleep=5, timeout=10, check_stdout=True),
            Input(sleep=8, timeout=10, check_stdout=True),
            Input(sleep=13, timeout=12, check_stdout=False),  # Must timeout
            Input(sleep=21, timeout=20, check_stdout=False),  # Must timeout. So stdout will be empty
        ]
        random.shuffle(self.inputs)

        container_manager = ContainerManager()
        layer_downloader = LayerDownloader("./", "./")
        self.lambda_image = LambdaImage(layer_downloader, False, False)
        self.runtime = LambdaRuntime(container_manager, self.lambda_image)
Esempio n. 19
0
    def test_keyboard_interrupt_must_raise(self, LambdaContainerMock):
        code_dir = "some code dir"

        container = Mock()
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir.return_value = code_dir

        LambdaContainerMock.return_value = container

        self.manager_mock.create.side_effect = KeyboardInterrupt("some exception")

        with self.assertRaises(KeyboardInterrupt):
            self.runtime.create(self.func_config, debug_context=debug_options)
Esempio n. 20
0
    def test_exception_from_wait_for_logs_must_trigger_cleanup(
            self, LambdaContainerMock):
        event = "event"
        debug_port = 123
        debug_arg = "abc"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        timer = Mock()

        self.runtime = LambdaRuntime(self.manager_mock)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir(
            self.code_path).__enter__.return_value = code_dir
        self.runtime._configure_interrupt = Mock()
        self.runtime._configure_interrupt.return_value = timer

        LambdaContainerMock.return_value = container

        container.wait_for_logs.side_effect = ValueError("some exception")

        with self.assertRaises(ValueError):
            self.runtime.invoke(self.func_config,
                                event,
                                debug_port=debug_port,
                                debug_args=debug_arg,
                                stdout=stdout,
                                stderr=stderr)

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)

        self.runtime._configure_interrupt.assert_called_with(
            self.name, self.DEFAULT_TIMEOUT, container, True)

        # Finally block must be called
        # Timer was created. So it must be cancelled
        timer.cancel.assert_called_with()
        # In any case, stop the container
        self.manager_mock.stop.assert_called_with(container)
Esempio n. 21
0
    def lambda_runtime(self) -> LambdaRuntime:
        if not self._lambda_runtimes:
            layer_downloader = LayerDownloader(self._layer_cache_basedir, self.get_cwd(), self._stacks)
            image_builder = LambdaImage(layer_downloader, self._skip_pull_image, self._force_image_build)
            self._lambda_runtimes = {
                ContainersMode.WARM: WarmLambdaRuntime(self._container_manager, image_builder),
                ContainersMode.COLD: LambdaRuntime(self._container_manager, image_builder),
            }

        return self._lambda_runtimes[self._containers_mode]
Esempio n. 22
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
Esempio n. 23
0
    def test_must_run_container_and_wait_for_logs(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        timer = Mock()
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir

        # Configure interrupt handler
        self.runtime._configure_interrupt = Mock()
        self.runtime._configure_interrupt.return_value = timer

        LambdaContainerMock.return_value = container

        self.runtime.invoke(self.func_config,
                            event,
                            debug_context=debug_options,
                            stdout=stdout,
                            stderr=stderr)

        # Verify if Lambda Event data is set
        self.env_vars.add_lambda_event_body.assert_called_with(event)

        # Make sure env-vars get resolved
        self.env_vars.resolve.assert_called_with()

        # Make sure the context manager is called to return the code directory
        self.runtime._get_code_dir.assert_called_with(self.code_path)

        # Make sure the container is created with proper values
        LambdaContainerMock.assert_called_with(self.lang, self.handler, code_dir, self.layers, lambda_image_mock,
                                               memory_mb=self.DEFAULT_MEMORY, env_vars=self.env_var_value,
                                               debug_options=debug_options)

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)
        self.runtime._configure_interrupt.assert_called_with(self.name, self.DEFAULT_TIMEOUT, container, True)
        container.wait_for_logs.assert_called_with(stdout=stdout, stderr=stderr)

        # Finally block
        timer.cancel.assert_called_with()
        self.manager_mock.stop.assert_called_with(container)
Esempio n. 24
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
Esempio n. 25
0
    def local_lambda_runner(self):
        """
        Returns an instance of the runner capable of running Lambda functions locally

        :return samcli.commands.local.lib.local_lambda.LocalLambdaRunner: Runner configured to run Lambda functions
            locally
        """

        container_manager = ContainerManager(docker_network_id=self._docker_network,
                                             skip_pull_image=self._skip_pull_image)

        lambda_runtime = LambdaRuntime(container_manager)
        return LocalLambdaRunner(local_runtime=lambda_runtime,
                                 function_provider=self._function_provider,
                                 cwd=self.get_cwd(),
                                 env_vars_values=self._env_vars_value,
                                 debug_context=self._debug_context,
                                 aws_profile=self._aws_profile,
                                 aws_region=self._aws_region)
Esempio n. 26
0
    def local_lambda_runner(self):
        """
        Returns an instance of the runner capable of running Lambda functions locally

        :return samcli.commands.local.lib.local_lambda.LocalLambdaRunner: Runner configured to run Lambda functions
            locally
        """

        layer_downloader = LayerDownloader(self._layer_cache_basedir,
                                           self.get_cwd())
        image_builder = LambdaImage(layer_downloader, self._skip_pull_image,
                                    self._force_image_build)

        lambda_runtime = LambdaRuntime(self._container_manager, image_builder)
        return LocalLambdaRunner(local_runtime=lambda_runtime,
                                 function_provider=self._function_provider,
                                 cwd=self.get_cwd(),
                                 env_vars_values=self._env_vars_value,
                                 debug_context=self._debug_context)
Esempio n. 27
0
    def test_exception_from_wait_for_logs_must_trigger_cleanup(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        timer = Mock()
        debug_options = Mock()
        layer_downloader = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, layer_downloader)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir
        self.runtime._configure_interrupt = Mock()
        self.runtime._configure_interrupt.return_value = timer

        LambdaContainerMock.return_value = container

        container.wait_for_logs.side_effect = ValueError("some exception")

        with self.assertRaises(ValueError):
            self.runtime.invoke(self.func_config,
                                event,
                                debug_context=debug_options,
                                stdout=stdout,
                                stderr=stderr)

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)

        self.runtime._configure_interrupt.assert_called_with(self.name, self.DEFAULT_TIMEOUT, container, True)

        # Finally block must be called
        # Timer was created. So it must be cancelled
        timer.cancel.assert_called_with()
        # In any case, stop the container
        self.manager_mock.stop.assert_called_with(container)
Esempio n. 28
0
    def test_exception_from_run_must_trigger_cleanup(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        timer = Mock()
        layer_downloader = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, layer_downloader)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir
        self.runtime._configure_interrupt = Mock()
        self.runtime._configure_interrupt.return_value = timer

        LambdaContainerMock.return_value = container

        self.manager_mock.run.side_effect = ValueError("some exception")

        with self.assertRaises(ValueError):
            self.runtime.invoke(self.func_config,
                                event,
                                debug_context=None,
                                stdout=stdout,
                                stderr=stderr)

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)

        self.runtime._configure_interrupt.assert_not_called()

        # Finally block must be called
        # But timer was not yet created. It should not be called
        timer.cancel.assert_not_called()
        # In any case, stop the container
        self.manager_mock.stop.assert_called_with(container)
Esempio n. 29
0
class LambdaRuntime_create(TestCase):

    DEFAULT_MEMORY = 128
    DEFAULT_TIMEOUT = 3

    def setUp(self):
        self.manager_mock = Mock()
        self.name = "name"
        self.lang = "runtime"
        self.handler = "handler"
        self.code_path = "code-path"
        self.layers = []
        self.manager_mock = Mock()
        self.imageuri = None
        self.packagetype = ZIP
        self.imageconfig = None
        self.func_config = FunctionConfig(
            self.name,
            self.lang,
            self.handler,
            self.imageuri,
            self.imageconfig,
            self.packagetype,
            self.code_path,
            self.layers,
        )

        self.env_vars = Mock()
        self.func_config.env_vars = self.env_vars
        self.env_var_value = {"a": "b"}
        self.env_vars.resolve.return_value = self.env_var_value

    @patch("samcli.local.lambdafn.runtime.LambdaContainer")
    def test_must_create_lambda_container(self, LambdaContainerMock):
        code_dir = "some code dir"

        container = Mock()
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir.return_value = code_dir

        LambdaContainerMock.return_value = container

        self.runtime.create(self.func_config, debug_context=debug_options)

        # Make sure env-vars get resolved
        self.env_vars.resolve.assert_called_with()

        # Make sure the context manager is called to return the code directory
        self.runtime._get_code_dir.assert_called_with(self.code_path)

        # Make sure the container is created with proper values
        LambdaContainerMock.assert_called_with(
            self.lang,
            self.imageuri,
            self.handler,
            self.packagetype,
            self.imageconfig,
            code_dir,
            self.layers,
            lambda_image_mock,
            debug_options=debug_options,
            env_vars=self.env_var_value,
            memory_mb=self.DEFAULT_MEMORY,
        )
        # Run the container and get results
        self.manager_mock.create.assert_called_with(container)

    @patch("samcli.local.lambdafn.runtime.LambdaContainer")
    def test_keyboard_interrupt_must_raise(self, LambdaContainerMock):
        code_dir = "some code dir"

        container = Mock()
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir.return_value = code_dir

        LambdaContainerMock.return_value = container

        self.manager_mock.create.side_effect = KeyboardInterrupt("some exception")

        with self.assertRaises(KeyboardInterrupt):
            self.runtime.create(self.func_config, debug_context=debug_options)
Esempio n. 30
0
 def setUp(self):
     self.manager_mock = Mock()
     self.runtime = LambdaRuntime(self.manager_mock)
Esempio n. 31
0
 def setUp(self):
     self.manager_mock = Mock()
     self.layer_downloader = Mock()
     self.runtime = LambdaRuntime(self.manager_mock, self.layer_downloader)
Esempio n. 32
0
class LambdaRuntime_run(TestCase):

    DEFAULT_MEMORY = 128
    DEFAULT_TIMEOUT = 3

    def setUp(self):
        self.manager_mock = Mock()
        self.name = "name"
        self.lang = "runtime"
        self.handler = "handler"
        self.code_path = "code-path"
        self.layers = []
        self.imageuri = None
        self.packagetype = ZIP
        self.imageconfig = None
        self.func_config = FunctionConfig(
            self.name,
            self.lang,
            self.handler,
            self.imageuri,
            self.imageconfig,
            self.packagetype,
            self.code_path,
            self.layers,
        )

        self.env_vars = Mock()
        self.func_config.env_vars = self.env_vars
        self.env_var_value = {"a": "b"}
        self.env_vars.resolve.return_value = self.env_var_value

    def test_must_run_passed_container(self):
        container = Mock()
        container.is_running.return_value = False
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        self.runtime.run(container, self.func_config, debug_context=debug_options)
        self.manager_mock.run.assert_called_with(container)

    def test_must_create_container_first_if_passed_container_is_none(self):
        container = Mock()
        container.is_running.return_value = False
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)
        create_mock = Mock()
        self.runtime.create = create_mock
        create_mock.return_value = container

        self.runtime.run(None, self.func_config, debug_context=debug_options)
        create_mock.assert_called_with(self.func_config, debug_options)
        self.manager_mock.run.assert_called_with(container)

    def test_must_skip_run_running_container(self):
        container = Mock()
        container.is_running.return_value = True
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        self.runtime.run(container, self.func_config, debug_context=debug_options)
        self.manager_mock.run.assert_not_called()

    def test_keyboard_interrupt_must_raise(self):
        container = Mock()
        container.is_running.return_value = False
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        self.manager_mock.run.side_effect = KeyboardInterrupt("some exception")

        with self.assertRaises(KeyboardInterrupt):
            self.runtime.run(container, self.func_config, debug_context=debug_options)
Esempio n. 33
0
class LambdaRuntime_invoke(TestCase):

    DEFAULT_MEMORY = 128
    DEFAULT_TIMEOUT = 3

    def setUp(self):

        self.manager_mock = Mock()

        self.name = "name"
        self.lang = "runtime"
        self.handler = "handler"
        self.code_path = "code-path"
        self.layers = []
        self.func_config = FunctionConfig(self.name, self.lang, self.handler, self.code_path, self.layers)

        self.env_vars = Mock()
        self.func_config.env_vars = self.env_vars
        self.env_var_value = {"a": "b"}
        self.env_vars.resolve.return_value = self.env_var_value

    @patch("samcli.local.lambdafn.runtime.LambdaContainer")
    def test_must_run_container_and_wait_for_logs(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        timer = Mock()
        debug_options = Mock()
        lambda_image_mock = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, lambda_image_mock)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir

        # Configure interrupt handler
        self.runtime._configure_interrupt = Mock()
        self.runtime._configure_interrupt.return_value = timer

        LambdaContainerMock.return_value = container

        self.runtime.invoke(self.func_config,
                            event,
                            debug_context=debug_options,
                            stdout=stdout,
                            stderr=stderr)

        # Verify if Lambda Event data is set
        self.env_vars.add_lambda_event_body.assert_called_with(event)

        # Make sure env-vars get resolved
        self.env_vars.resolve.assert_called_with()

        # Make sure the context manager is called to return the code directory
        self.runtime._get_code_dir.assert_called_with(self.code_path)

        # Make sure the container is created with proper values
        LambdaContainerMock.assert_called_with(self.lang, self.handler, code_dir, self.layers, lambda_image_mock,
                                               memory_mb=self.DEFAULT_MEMORY, env_vars=self.env_var_value,
                                               debug_options=debug_options)

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)
        self.runtime._configure_interrupt.assert_called_with(self.name, self.DEFAULT_TIMEOUT, container, True)
        container.wait_for_logs.assert_called_with(stdout=stdout, stderr=stderr)

        # Finally block
        timer.cancel.assert_called_with()
        self.manager_mock.stop.assert_called_with(container)

    @patch("samcli.local.lambdafn.runtime.LambdaContainer")
    def test_exception_from_run_must_trigger_cleanup(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        timer = Mock()
        layer_downloader = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, layer_downloader)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir
        self.runtime._configure_interrupt = Mock()
        self.runtime._configure_interrupt.return_value = timer

        LambdaContainerMock.return_value = container

        self.manager_mock.run.side_effect = ValueError("some exception")

        with self.assertRaises(ValueError):
            self.runtime.invoke(self.func_config,
                                event,
                                debug_context=None,
                                stdout=stdout,
                                stderr=stderr)

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)

        self.runtime._configure_interrupt.assert_not_called()

        # Finally block must be called
        # But timer was not yet created. It should not be called
        timer.cancel.assert_not_called()
        # In any case, stop the container
        self.manager_mock.stop.assert_called_with(container)

    @patch("samcli.local.lambdafn.runtime.LambdaContainer")
    def test_exception_from_wait_for_logs_must_trigger_cleanup(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        timer = Mock()
        debug_options = Mock()
        layer_downloader = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, layer_downloader)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir
        self.runtime._configure_interrupt = Mock()
        self.runtime._configure_interrupt.return_value = timer

        LambdaContainerMock.return_value = container

        container.wait_for_logs.side_effect = ValueError("some exception")

        with self.assertRaises(ValueError):
            self.runtime.invoke(self.func_config,
                                event,
                                debug_context=debug_options,
                                stdout=stdout,
                                stderr=stderr)

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)

        self.runtime._configure_interrupt.assert_called_with(self.name, self.DEFAULT_TIMEOUT, container, True)

        # Finally block must be called
        # Timer was created. So it must be cancelled
        timer.cancel.assert_called_with()
        # In any case, stop the container
        self.manager_mock.stop.assert_called_with(container)

    @patch("samcli.local.lambdafn.runtime.LambdaContainer")
    def test_keyboard_interrupt_must_not_raise(self, LambdaContainerMock):
        event = "event"
        code_dir = "some code dir"
        stdout = "stdout"
        stderr = "stderr"
        container = Mock()
        layer_downloader = Mock()

        self.runtime = LambdaRuntime(self.manager_mock, layer_downloader)

        # Using MagicMock to mock the context manager
        self.runtime._get_code_dir = MagicMock()
        self.runtime._get_code_dir(self.code_path).__enter__.return_value = code_dir
        self.runtime._configure_interrupt = Mock()

        LambdaContainerMock.return_value = container

        self.manager_mock.run.side_effect = KeyboardInterrupt("some exception")

        self.runtime.invoke(self.func_config,
                            event,
                            stdout=stdout,
                            stderr=stderr)

        # Run the container and get results
        self.manager_mock.run.assert_called_with(container)

        self.runtime._configure_interrupt.assert_not_called()

        # Finally block must be called
        self.manager_mock.stop.assert_called_with(container)
Esempio n. 34
0
class TestLambdaRuntime_configure_interrupt(TestCase):

    def setUp(self):
        self.name = "name"
        self.timeout = 123
        self.container = Mock()

        self.manager_mock = Mock()
        self.layer_downloader = Mock()
        self.runtime = LambdaRuntime(self.manager_mock, self.layer_downloader)

    @patch("samcli.local.lambdafn.runtime.threading")
    @patch("samcli.local.lambdafn.runtime.signal")
    def test_must_setup_timer(self, SignalMock, ThreadingMock):
        is_debugging = False  # We are not debugging. So setup timer
        timer_obj = Mock()
        ThreadingMock.Timer.return_value = timer_obj

        result = self.runtime._configure_interrupt(self.name, self.timeout, self.container, is_debugging)

        self.assertEquals(result, timer_obj)

        ThreadingMock.Timer.assert_called_with(self.timeout, ANY, ())
        timer_obj.start.assert_called_with()

        SignalMock.signal.assert_not_called()  # must not setup signal handler

    @patch("samcli.local.lambdafn.runtime.threading")
    @patch("samcli.local.lambdafn.runtime.signal")
    def test_must_setup_signal_handler(self, SignalMock, ThreadingMock):
        is_debugging = True  # We are debugging. So setup signal
        SignalMock.SIGTERM = sigterm = "sigterm"

        result = self.runtime._configure_interrupt(self.name, self.timeout, self.container, is_debugging)

        self.assertIsNone(result, "There are no return values when setting up signal handler")

        SignalMock.signal.assert_called_with(sigterm, ANY)
        ThreadingMock.Timer.signal.assert_not_called()  # must not setup timer

    @patch("samcli.local.lambdafn.runtime.threading")
    @patch("samcli.local.lambdafn.runtime.signal")
    def test_verify_signal_handler(self, SignalMock, ThreadingMock):
        """
        Verify the internal implementation of the Signal Handler
        """
        is_debugging = True  # We are debugging. So setup signal
        SignalMock.SIGTERM = "sigterm"

        # Fake the real method with a Lambda. Also run the handler immediately.
        SignalMock.signal = lambda term, handler: handler("a", "b")

        self.runtime._configure_interrupt(self.name, self.timeout, self.container, is_debugging)

        # This method should be called from within the Signal Handler
        self.manager_mock.stop.assert_called_with(self.container)

    @patch("samcli.local.lambdafn.runtime.threading")
    @patch("samcli.local.lambdafn.runtime.signal")
    def test_verify_timer_handler(self, SignalMock, ThreadingMock):
        """
        Verify the internal implementation of the Signal Handler
        """
        is_debugging = False

        def fake_timer(timeout, handler, args):
            handler()
            return Mock()

        # Fake the real method with a Lambda. Also run the handler immediately.
        ThreadingMock.Timer = fake_timer

        self.runtime._configure_interrupt(self.name, self.timeout, self.container, is_debugging)

        # This method should be called from within the Timer Handler
        self.manager_mock.stop.assert_called_with(self.container)