Example #1
0
def do_cli(  # pylint: disable=R0914
    ctx,
    host,
    port,
    static_dir,
    template,
    env_vars,
    debug_port,
    debug_args,
    debugger_path,
    docker_volume_basedir,
    docker_network,
    log_file,
    layer_cache_basedir,
    skip_pull_image,
    force_image_build,
    parameter_overrides,
):
    """
    Implementation of the ``cli`` method, just separated out for unit testing purposes
    """

    from samcli.commands.local.cli_common.invoke_context import InvokeContext
    from samcli.commands.local.lib.exceptions import NoApisDefined, InvalidLayerReference
    from samcli.commands.exceptions import UserException
    from samcli.commands.local.lib.local_api_service import LocalApiService
    from samcli.commands.validate.lib.exceptions import InvalidSamDocumentException
    from samcli.commands.local.lib.exceptions import OverridesNotWellDefinedError
    from samcli.local.docker.lambda_debug_entrypoint import DebuggingNotSupported

    LOG.debug("local start-api command is called")

    # Pass all inputs to setup necessary context to invoke function locally.
    # Handler exception raised by the processor for invalid args and print errors

    try:
        with InvokeContext(
            template_file=template,
            function_identifier=None,  # Don't scope to one particular function
            env_vars_file=env_vars,
            docker_volume_basedir=docker_volume_basedir,
            docker_network=docker_network,
            log_file=log_file,
            skip_pull_image=skip_pull_image,
            debug_port=debug_port,
            debug_args=debug_args,
            debugger_path=debugger_path,
            parameter_overrides=parameter_overrides,
            layer_cache_basedir=layer_cache_basedir,
            force_image_build=force_image_build,
            aws_region=ctx.region,
            aws_profile=ctx.profile,
        ) as invoke_context:

            service = LocalApiService(lambda_invoke_context=invoke_context, port=port, host=host, static_dir=static_dir)
            service.start()

    except NoApisDefined:
        raise UserException("Template does not have any APIs connected to Lambda functions")
    except (
        InvalidSamDocumentException,
        OverridesNotWellDefinedError,
        InvalidLayerReference,
        DebuggingNotSupported,
    ) as ex:
        raise UserException(str(ex))
    def test_must_return_function_name_if_present(self):
        id = "id"
        context = InvokeContext(template_file="template_file",
                                function_identifier=id)

        self.assertEqual(id, context.function_name)
    def test_must_return_tempalte_dict(self):
        context = InvokeContext(template_file="file")
        context._template_dict = "My template"

        self.assertEqual("My template", context.template)
    def test_must_ignore_if_handle_is_absent(self):
        context = InvokeContext(template_file="template")
        context._log_file_handle = None

        context.__exit__()
        self.assertIsNone(context._log_file_handle)
    def test_must_read_from_necessary_files(self, SamFunctionProviderMock):
        function_provider = Mock()

        SamFunctionProviderMock.return_value = function_provider

        template_file = "template_file"
        env_vars_file = "env_vars_file"
        log_file = "log_file"

        invoke_context = InvokeContext(
            template_file=template_file,
            function_identifier="id",
            env_vars_file=env_vars_file,
            docker_volume_basedir="volumedir",
            docker_network="network",
            log_file=log_file,
            skip_pull_image=True,
            debug_port=1111,
            debugger_path="path-to-debugger",
            debug_args="args",
            parameter_overrides={},
            aws_region="region",
            aws_profile="profile",
        )

        template_dict = "template_dict"
        invoke_context._get_template_data = Mock()
        invoke_context._get_template_data.return_value = template_dict

        env_vars_value = "env_vars_value"
        invoke_context._get_env_vars_value = Mock()
        invoke_context._get_env_vars_value.return_value = env_vars_value

        log_file_handle = "handle"
        invoke_context._setup_log_file = Mock()
        invoke_context._setup_log_file.return_value = log_file_handle

        debug_context_mock = Mock()
        invoke_context._get_debug_context = Mock()
        invoke_context._get_debug_context.return_value = debug_context_mock

        container_manager_mock = Mock()
        container_manager_mock.is_docker_reachable = True
        invoke_context._get_container_manager = Mock(
            return_value=container_manager_mock)

        # Call Enter method manually for testing purposes
        result = invoke_context.__enter__()
        self.assertTrue(result is invoke_context,
                        "__enter__() must return self")

        self.assertEqual(invoke_context._template_dict, template_dict)
        self.assertEqual(invoke_context._function_provider, function_provider)
        self.assertEqual(invoke_context._env_vars_value, env_vars_value)
        self.assertEqual(invoke_context._log_file_handle, log_file_handle)
        self.assertEqual(invoke_context._debug_context, debug_context_mock)
        self.assertEqual(invoke_context._container_manager,
                         container_manager_mock)

        invoke_context._get_template_data.assert_called_with(template_file)
        SamFunctionProviderMock.assert_called_with(template_dict,
                                                   {"AWS::Region": "region"})
        invoke_context._get_env_vars_value.assert_called_with(env_vars_file)
        invoke_context._setup_log_file.assert_called_with(log_file)
        invoke_context._get_debug_context.assert_called_once_with(
            1111, "args", "path-to-debugger")
        invoke_context._get_container_manager.assert_called_once_with(
            "network", True)
Example #6
0
def do_cli(  # pylint: disable=R0914
    ctx,
    host,
    port,
    template,
    env_vars,
    debug_port,
    debug_args,
    debugger_path,
    container_env_vars,
    docker_volume_basedir,
    docker_network,
    log_file,
    layer_cache_basedir,
    skip_pull_image,
    force_image_build,
    parameter_overrides,
    warm_containers,
    debug_function,
):
    """
    Implementation of the ``cli`` method, just separated out for unit testing purposes
    """

    from samcli.commands.local.cli_common.invoke_context import InvokeContext
    from samcli.commands.local.cli_common.user_exceptions import UserException
    from samcli.lib.providers.exceptions import InvalidLayerReference
    from samcli.commands.local.lib.local_lambda_service import LocalLambdaService
    from samcli.commands.validate.lib.exceptions import InvalidSamDocumentException
    from samcli.commands.local.lib.exceptions import OverridesNotWellDefinedError
    from samcli.local.docker.lambda_debug_settings import DebuggingNotSupported

    LOG.debug("local start_lambda command is called")

    # Pass all inputs to setup necessary context to invoke function locally.
    # Handler exception raised by the processor for invalid args and print errors

    try:
        with InvokeContext(
            template_file=template,
            function_identifier=None,  # Don't scope to one particular function
            env_vars_file=env_vars,
            docker_volume_basedir=docker_volume_basedir,
            docker_network=docker_network,
            log_file=log_file,
            skip_pull_image=skip_pull_image,
            debug_ports=debug_port,
            debug_args=debug_args,
            debugger_path=debugger_path,
            container_env_vars_file=container_env_vars,
            parameter_overrides=parameter_overrides,
            layer_cache_basedir=layer_cache_basedir,
            force_image_build=force_image_build,
            aws_region=ctx.region,
            aws_profile=ctx.profile,
            warm_container_initialization_mode=warm_containers,
            debug_function=debug_function,
        ) as invoke_context:

            service = LocalLambdaService(lambda_invoke_context=invoke_context, port=port, host=host)
            service.start()

    except (
        InvalidSamDocumentException,
        OverridesNotWellDefinedError,
        InvalidLayerReference,
        InvalidIntermediateImageError,
        DebuggingNotSupported,
    ) as ex:
        raise UserException(str(ex), wrapped_from=ex.__class__.__name__) from ex
    except ContainerNotStartableException as ex:
        raise UserException(str(ex), wrapped_from=ex.__class__.__name__) from ex
Example #7
0
def do_cli(  # pylint: disable=R0914
    ctx,
    function_identifier,
    template,
    event,
    no_event,
    env_vars,
    debug_port,
    debug_args,
    debugger_path,
    docker_volume_basedir,
    docker_network,
    log_file,
    layer_cache_basedir,
    skip_pull_image,
    force_image_build,
    parameter_overrides,
):
    """
    Implementation of the ``cli`` method, just separated out for unit testing purposes
    """

    from samcli.commands.exceptions import UserException
    from samcli.commands.local.lib.exceptions import InvalidLayerReference
    from samcli.commands.local.cli_common.invoke_context import InvokeContext
    from samcli.local.lambdafn.exceptions import FunctionNotFound
    from samcli.commands.validate.lib.exceptions import InvalidSamDocumentException
    from samcli.commands.local.lib.exceptions import OverridesNotWellDefinedError
    from samcli.local.docker.manager import DockerImagePullFailedException
    from samcli.local.docker.lambda_debug_entrypoint import DebuggingNotSupported

    LOG.debug("local invoke command is called")

    if no_event and event != STDIN_FILE_NAME:
        # Do not know what the user wants. no_event and event both passed in.
        raise UserException(
            "no_event and event cannot be used together. Please provide only one."
        )

    if no_event:
        event_data = "{}"
    else:
        event_data = _get_event(event)

    # Pass all inputs to setup necessary context to invoke function locally.
    # Handler exception raised by the processor for invalid args and print errors
    try:
        with InvokeContext(
                template_file=template,
                function_identifier=function_identifier,
                env_vars_file=env_vars,
                docker_volume_basedir=docker_volume_basedir,
                docker_network=docker_network,
                log_file=log_file,
                skip_pull_image=skip_pull_image,
                debug_port=debug_port,
                debug_args=debug_args,
                debugger_path=debugger_path,
                parameter_overrides=parameter_overrides,
                layer_cache_basedir=layer_cache_basedir,
                force_image_build=force_image_build,
                aws_region=ctx.region,
                aws_profile=ctx.profile,
        ) as context:

            # Invoke the function
            context.local_lambda_runner.invoke(context.function_name,
                                               event=event_data,
                                               stdout=context.stdout,
                                               stderr=context.stderr)

    except FunctionNotFound:
        raise UserException(
            "Function {} not found in template".format(function_identifier))
    except (
            InvalidSamDocumentException,
            OverridesNotWellDefinedError,
            InvalidLayerReference,
            DebuggingNotSupported,
    ) as ex:
        raise UserException(str(ex))
    except DockerImagePullFailedException as ex:
        raise UserException(str(ex))
Example #8
0
def do_cli(  # pylint: disable=R0914
    ctx,
    function_identifier,
    template,
    event,
    no_event,
    env_vars,
    debug_port,
    debug_args,
    debugger_path,
    container_env_vars,
    docker_volume_basedir,
    docker_network,
    log_file,
    layer_cache_basedir,
    skip_pull_image,
    force_image_build,
    parameter_overrides,
):
    """
    Implementation of the ``cli`` method, just separated out for unit testing purposes
    """

    from samcli.commands.exceptions import UserException
    from samcli.lib.providers.exceptions import InvalidLayerReference
    from samcli.commands.local.cli_common.invoke_context import InvokeContext
    from samcli.local.lambdafn.exceptions import FunctionNotFound
    from samcli.commands.validate.lib.exceptions import InvalidSamDocumentException
    from samcli.commands.local.lib.exceptions import OverridesNotWellDefinedError, NoPrivilegeException
    from samcli.local.docker.manager import DockerImagePullFailedException
    from samcli.local.docker.lambda_debug_settings import DebuggingNotSupported

    LOG.debug("local invoke command is called")

    if event:
        event_data = _get_event(event)
    else:
        event_data = "{}"

    # Pass all inputs to setup necessary context to invoke function locally.
    # Handler exception raised by the processor for invalid args and print errors
    try:
        with InvokeContext(
                template_file=template,
                function_identifier=function_identifier,
                env_vars_file=env_vars,
                docker_volume_basedir=docker_volume_basedir,
                docker_network=docker_network,
                log_file=log_file,
                skip_pull_image=skip_pull_image,
                debug_ports=debug_port,
                debug_args=debug_args,
                debugger_path=debugger_path,
                container_env_vars_file=container_env_vars,
                parameter_overrides=parameter_overrides,
                layer_cache_basedir=layer_cache_basedir,
                force_image_build=force_image_build,
                aws_region=ctx.region,
                aws_profile=ctx.profile,
        ) as context:

            # Invoke the function
            context.local_lambda_runner.invoke(context.function_name,
                                               event=event_data,
                                               stdout=context.stdout,
                                               stderr=context.stderr)

    except FunctionNotFound as ex:
        raise UserException(
            "Function {} not found in template".format(function_identifier),
            wrapped_from=ex.__class__.__name__) from ex
    except (
            InvalidSamDocumentException,
            OverridesNotWellDefinedError,
            InvalidLayerReference,
            InvalidIntermediateImageError,
            DebuggingNotSupported,
            NoPrivilegeException,
    ) as ex:
        raise UserException(str(ex),
                            wrapped_from=ex.__class__.__name__) from ex
    except DockerImagePullFailedException as ex:
        raise UserException(str(ex),
                            wrapped_from=ex.__class__.__name__) from ex
    except ContainerNotStartableException as ex:
        raise UserException(str(ex),
                            wrapped_from=ex.__class__.__name__) from ex
Example #9
0
    def test_must_create_runner_using_warm_containers(
            self, SamFunctionProviderMock, LocalLambdaMock,
            WarmLambdaRuntimeMock, download_layers_mock, lambda_image_patch):
        runtime_mock = Mock()
        WarmLambdaRuntimeMock.return_value = runtime_mock

        runner_mock = Mock()
        LocalLambdaMock.return_value = runner_mock

        download_mock = Mock()
        download_layers_mock.return_value = download_mock

        image_mock = Mock()
        lambda_image_patch.return_value = image_mock

        cwd = "cwd"
        self.context = InvokeContext(
            template_file="template_file",
            function_identifier="id",
            env_vars_file="env_vars_file",
            docker_volume_basedir="volumedir",
            docker_network="network",
            log_file="log_file",
            skip_pull_image=True,
            force_image_build=True,
            debug_ports=[1111],
            debugger_path="path-to-debugger",
            debug_args="args",
            aws_profile="profile",
            aws_region="region",
            warm_container_initialization_mode=ContainersInitializationMode.
            EAGER,
        )
        self.context.get_cwd = Mock()
        self.context.get_cwd.return_value = cwd

        self.context._get_stacks = Mock()
        self.context._get_stacks.return_value = [Mock()]
        self.context._get_env_vars_value = Mock()
        self.context._setup_log_file = Mock()
        self.context._get_debug_context = Mock(return_value=None)

        container_manager_mock = Mock()
        container_manager_mock.is_docker_reachable = PropertyMock(
            return_value=True)
        self.context._get_container_manager = Mock(
            return_value=container_manager_mock)

        with self.context:
            result = self.context.local_lambda_runner
            self.assertEqual(result, runner_mock)

            WarmLambdaRuntimeMock.assert_called_with(container_manager_mock,
                                                     image_mock)
            lambda_image_patch.assert_called_once_with(download_mock, True,
                                                       True)
            LocalLambdaMock.assert_called_with(
                local_runtime=runtime_mock,
                function_provider=ANY,
                cwd=cwd,
                debug_context=None,
                env_vars_values=ANY,
                aws_profile="profile",
                aws_region="region",
            )

            result = self.context.local_lambda_runner
            self.assertEqual(result, runner_mock)
            # assert that lambda runner is created only one time, and the cached version used in the second call
            self.assertEqual(LocalLambdaMock.call_count, 1)
Example #10
0
    def test_no_container_will_be_initialized_if_lazy_containers_is_enabled(
            self, SamFunctionProviderMock, ContainerManagerMock):
        function_provider = Mock()

        SamFunctionProviderMock.return_value = function_provider

        template_file = "template_file"
        env_vars_file = "env_vars_file"
        log_file = "log_file"

        invoke_context = InvokeContext(
            template_file=template_file,
            function_identifier="id",
            env_vars_file=env_vars_file,
            docker_volume_basedir="volumedir",
            docker_network="network",
            log_file=log_file,
            skip_pull_image=True,
            debug_ports=[1111],
            debugger_path="path-to-debugger",
            debug_args="args",
            parameter_overrides={},
            aws_region="region",
            aws_profile="profile",
            warm_container_initialization_mode=ContainersInitializationMode.
            LAZY.value,
            debug_function="debug_function",
            shutdown=True,
        )

        template_dict = "template_dict"
        stacks = [
            Stack("", "", template_file, invoke_context.parameter_overrides,
                  template_dict)
        ]
        invoke_context._get_stacks = Mock()
        invoke_context._get_stacks.return_value = stacks

        env_vars_value = "env_vars_value"
        invoke_context._get_env_vars_value = Mock()
        invoke_context._get_env_vars_value.return_value = env_vars_value

        log_file_handle = "handle"
        invoke_context._setup_log_file = Mock()
        invoke_context._setup_log_file.return_value = log_file_handle

        debug_context_mock = Mock()
        invoke_context._get_debug_context = Mock()
        invoke_context._get_debug_context.return_value = debug_context_mock

        container_manager_mock = Mock()
        container_manager_mock.is_docker_reachable = True
        ContainerManagerMock.return_value = container_manager_mock

        # Call Enter method manually for testing purposes
        result = invoke_context.__enter__()
        self.assertTrue(result is invoke_context,
                        "__enter__() must return self")

        self.assertEqual(invoke_context._template_dict, template_dict)
        self.assertEqual(invoke_context._function_provider, function_provider)
        self.assertEqual(invoke_context._env_vars_value, env_vars_value)
        self.assertEqual(invoke_context._log_file_handle, log_file_handle)
        self.assertEqual(invoke_context._debug_context, debug_context_mock)
        self.assertEqual(invoke_context._container_manager,
                         container_manager_mock)
        self.assertEqual(invoke_context._containers_mode, ContainersMode.WARM)
        self.assertEqual(invoke_context._containers_initializing_mode,
                         ContainersInitializationMode.LAZY)

        invoke_context._get_stacks.assert_called_once()
        SamFunctionProviderMock.assert_called_with(stacks)
        self.assertEqual(invoke_context.parameter_overrides,
                         {"AWS::Region": "region"})
        self.assertEqual(invoke_context._get_env_vars_value.call_count, 2)
        self.assertEqual(invoke_context._get_env_vars_value.call_args_list,
                         [call(env_vars_file), call(None)])
        invoke_context._setup_log_file.assert_called_with(log_file)
        invoke_context._get_debug_context.assert_called_once_with(
            [1111], "args", "path-to-debugger", "env_vars_value",
            "debug_function")
        ContainerManagerMock.assert_called_once_with(
            docker_network_id="network",
            skip_pull_image=True,
            do_shutdown_event=True)
Example #11
0
    def test_must_return_log_file_handle(self):
        context = InvokeContext(template_file="template")
        context._log_file_handle = "handle"

        self.assertEquals("handle", context.stderr)
Example #12
0
    def test_must_set_debug_function_if_warm_containers_enabled_no_debug_function_provided_and_template_contains_one_function(
            self, SamFunctionProviderMock, ContainerManagerMock):
        function_provider = Mock()
        function_provider.functions = {"function_name": ANY}
        SamFunctionProviderMock.return_value = function_provider

        template_file = "template_file"
        env_vars_file = "env_vars_file"
        container_env_vars_file = "container_env_vars_file"
        log_file = "log_file"

        invoke_context = InvokeContext(
            template_file=template_file,
            function_identifier="id",
            env_vars_file=env_vars_file,
            docker_volume_basedir="volumedir",
            docker_network="network",
            log_file=log_file,
            skip_pull_image=True,
            debug_ports=[1111],
            debugger_path="path-to-debugger",
            container_env_vars_file=container_env_vars_file,
            debug_args="args",
            parameter_overrides={},
            aws_region="region",
            aws_profile="profile",
            warm_container_initialization_mode=ContainersInitializationMode.
            EAGER.value,
            debug_function="",
            shutdown=True,
        )

        _initialize_all_functions_containers_mock = Mock()
        invoke_context._initialize_all_functions_containers = _initialize_all_functions_containers_mock

        template_dict = "template_dict"
        invoke_context._get_template_data = Mock()
        invoke_context._get_template_data.return_value = template_dict

        invoke_context._get_env_vars_value = Mock(
            side_effect=["Env var value", "Debug env var value"])

        log_file_handle = "handle"
        invoke_context._setup_log_file = Mock()
        invoke_context._setup_log_file.return_value = log_file_handle

        debug_context_mock = Mock()
        invoke_context._get_debug_context = Mock()
        invoke_context._get_debug_context.return_value = debug_context_mock

        container_manager_mock = Mock()
        container_manager_mock.is_docker_reachable = True
        ContainerManagerMock.return_value = container_manager_mock

        # Call Enter method manually for testing purposes
        result = invoke_context.__enter__()
        self.assertTrue(result is invoke_context,
                        "__enter__() must return self")

        self.assertEqual(invoke_context._template_dict, template_dict)
        self.assertEqual(invoke_context._function_provider, function_provider)
        self.assertEqual(invoke_context._env_vars_value, "Env var value")
        self.assertEqual(invoke_context._container_env_vars_value,
                         "Debug env var value")
        self.assertEqual(invoke_context._log_file_handle, log_file_handle)
        self.assertEqual(invoke_context._debug_context, debug_context_mock)
        self.assertEqual(invoke_context._container_manager,
                         container_manager_mock)
        self.assertEqual(invoke_context._containers_mode, ContainersMode.WARM)
        self.assertEqual(invoke_context._containers_initializing_mode,
                         ContainersInitializationMode.EAGER)

        invoke_context._get_template_data.assert_called_with(template_file)
        SamFunctionProviderMock.assert_called_with(template_dict,
                                                   {"AWS::Region": "region"})
        self.assertEqual(invoke_context._get_env_vars_value.call_count, 2)
        self.assertEqual(
            invoke_context._get_env_vars_value.call_args_list,
            [call("env_vars_file"),
             call("container_env_vars_file")])
        invoke_context._setup_log_file.assert_called_with(log_file)
        invoke_context._get_debug_context.assert_called_once_with(
            [1111], "args", "path-to-debugger", "Debug env var value",
            "function_name")
        ContainerManagerMock.assert_called_once_with(
            docker_network_id="network",
            skip_pull_image=True,
            do_shutdown_event=True)
        _initialize_all_functions_containers_mock.assert_called_once_with()