Esempio n. 1
0
    def _get_cors_prop(cors_dict, prop_name):
        """
        Extract cors properties from dictionary and remove extra quotes.

        Parameters
        ----------
        cors_dict : dict
            Resource properties for Cors

        Return
        ------
        A string with the extra quotes removed
        """
        prop = cors_dict.get(prop_name)
        if prop:
            if (not isinstance(prop, string_types)) or (not (prop.startswith("'") and prop.endswith("'"))):
                raise InvalidSamDocumentException(
                    "{} must be a quoted string " '(i.e. "\'value\'" is correct, but "value" is not).'.format(prop_name)
                )
            prop = prop.strip("'")
        return prop
Esempio n. 2
0
    def extract_cors(self, cors_prop):
        """
        Extract Cors property from AWS::Serverless::Api resource by reading and parsing Swagger documents. The result
        is added to the Api.

        Parameters
        ----------
        cors_prop : dict
            Resource properties for Cors
        """
        cors = None
        if cors_prop and isinstance(cors_prop, dict):
            allow_methods = self._get_cors_prop(cors_prop, "AllowMethods")
            if allow_methods:
                allow_methods = self.normalize_cors_allow_methods(allow_methods)
            else:
                allow_methods = ",".join(sorted(Route.ANY_HTTP_METHODS))

            allow_origin = self._get_cors_prop(cors_prop, "AllowOrigin")
            allow_headers = self._get_cors_prop(cors_prop, "AllowHeaders")
            max_age = self._get_cors_prop(cors_prop, "MaxAge")

            cors = Cors(
                allow_origin=allow_origin, allow_methods=allow_methods, allow_headers=allow_headers, max_age=max_age
            )
        elif cors_prop and isinstance(cors_prop, string_types):
            allow_origin = cors_prop
            if not (allow_origin.startswith("'") and allow_origin.endswith("'")):
                raise InvalidSamDocumentException(
                    "Cors Properties must be a quoted string " '(i.e. "\'*\'" is correct, but "*" is not).'
                )
            allow_origin = allow_origin.strip("'")

            cors = Cors(
                allow_origin=allow_origin,
                allow_methods=",".join(sorted(Route.ANY_HTTP_METHODS)),
                allow_headers=None,
                max_age=None,
            )
        return cors
Esempio n. 3
0
    def run_plugins(self, convert_local_uris=True):
        template_copy = self.template

        additional_plugins = []
        if convert_local_uris:
            # Add all the plugins to convert local path if asked to.
            additional_plugins.append(self.local_uri_plugin)

        parser = _SamParserReimplemented()
        all_plugins = prepare_plugins(additional_plugins)

        try:
            parser.parse(
                template_copy,
                all_plugins)  # parse() will run all configured plugins
        except InvalidDocumentException as e:
            raise InvalidSamDocumentException(
                functools.reduce(
                    lambda message, error: message + ' ' + str(error),
                    e.causes, str(e)))

        return template_copy
Esempio n. 4
0
    def _get_cors_prop(cors_dict: Dict,
                       prop_name: str,
                       allow_bool: bool = False) -> Optional[str]:
        """
        Extract cors properties from dictionary and remove extra quotes.

        Parameters
        ----------
        cors_dict : dict
            Resource properties for Cors

        prop_name : str
            Cors property to get the value for

        allow_bool : bool
            If a boolean value is allowed for this property or not (defaults to false)

        Return
        ------
        A string with the extra quotes removed
        """
        prop = cors_dict.get(prop_name)
        if prop:
            if allow_bool and isinstance(prop, bool):
                prop = "'true'"  # We alredy know this is true due to L141 passing
            if not isinstance(prop, str) or prop.startswith("!"):
                LOG.warning(
                    "CORS Property %s was not fully resolved. Will proceed as if the Property was not defined.",
                    prop_name,
                )
                return None

            if not (prop.startswith("'") and prop.endswith("'")):
                raise InvalidSamDocumentException(
                    "{} must be a quoted string "
                    '(i.e. "\'value\'" is correct, but "value" is not).'.
                    format(prop_name))
            prop = prop.strip("'")
        return prop
Esempio n. 5
0
    def test_must_raise_user_exception_on_invalid_sam_template(self, get_event_mock, InvokeContextMock):
        event_data = "data"
        get_event_mock.return_value = event_data

        InvokeContextMock.side_effect = InvalidSamDocumentException("bad template")

        with self.assertRaises(UserException) as ex_ctx:

            invoke_cli(ctx=None,
                       function_identifier=self.function_id,
                       template=self.template,
                       event=self.eventfile,
                       env_vars=self.env_vars,
                       debug_port=self.debug_port,
                       debug_args=self.debug_args,
                       docker_volume_basedir=self.docker_volume_basedir,
                       docker_network=self.docker_network,
                       log_file=self.log_file,
                       skip_pull_image=self.skip_pull_image,
                       profile=self.profile)

        msg = str(ex_ctx.exception)
        self.assertEquals(msg, "bad template")
Esempio n. 6
0
class TestCli(TestCase):
    def setUp(self):
        self.template = "template"
        self.env_vars = "env-vars"
        self.debug_ports = [123]
        self.debug_args = "args"
        self.debugger_path = "/test/path"
        self.container_env_vars = "container-env-vars"
        self.docker_volume_basedir = "basedir"
        self.docker_network = "network"
        self.log_file = "logfile"
        self.skip_pull_image = True
        self.parameter_overrides = {}
        self.layer_cache_basedir = "/some/layers/path"
        self.force_image_build = True
        self.shutdown = True
        self.region_name = "region"
        self.profile = "profile"

        self.warm_containers = None
        self.debug_function = None

        self.ctx_mock = Mock()
        self.ctx_mock.region = self.region_name
        self.ctx_mock.profile = self.profile

        self.host = "host"
        self.port = 123
        self.static_dir = "staticdir"

    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    @patch("samcli.commands.local.lib.local_api_service.LocalApiService")
    def test_cli_must_setup_context_and_start_service(self, local_api_service_mock, invoke_context_mock):
        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        invoke_context_mock.return_value.__enter__.return_value = context_mock

        service_mock = Mock()
        local_api_service_mock.return_value = service_mock

        self.warm_containers = None
        self.debug_function = None

        self.call_cli()

        invoke_context_mock.assert_called_with(
            template_file=self.template,
            function_identifier=None,
            env_vars_file=self.env_vars,
            docker_volume_basedir=self.docker_volume_basedir,
            docker_network=self.docker_network,
            log_file=self.log_file,
            skip_pull_image=self.skip_pull_image,
            debug_ports=self.debug_ports,
            debug_args=self.debug_args,
            debugger_path=self.debugger_path,
            container_env_vars_file=self.container_env_vars,
            parameter_overrides=self.parameter_overrides,
            layer_cache_basedir=self.layer_cache_basedir,
            force_image_build=self.force_image_build,
            aws_region=self.region_name,
            aws_profile=self.profile,
            warm_container_initialization_mode=self.warm_containers,
            debug_function=self.debug_function,
            shutdown=self.shutdown,
        )

        local_api_service_mock.assert_called_with(
            lambda_invoke_context=context_mock, port=self.port, host=self.host, static_dir=self.static_dir
        )

        service_mock.start.assert_called_with()

    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    @patch("samcli.commands.local.lib.local_api_service.LocalApiService")
    def test_must_raise_if_no_api_defined(self, local_api_service_mock, invoke_context_mock):

        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        invoke_context_mock.return_value.__enter__.return_value = context_mock

        service_mock = Mock()
        local_api_service_mock.return_value = service_mock
        service_mock.start.side_effect = NoApisDefined("no apis")

        with self.assertRaises(UserException) as context:
            self.call_cli()

        msg = str(context.exception)
        expected = "Template does not have any APIs connected to Lambda functions"
        self.assertEqual(msg, expected)

    @parameterized.expand(
        [
            (InvalidSamDocumentException("bad template"), "bad template"),
            (
                InvalidLayerReference(),
                "Layer References need to be of type " "'AWS::Serverless::LayerVersion' or 'AWS::Lambda::LayerVersion'",
            ),
            (DebuggingNotSupported("Debugging not supported"), "Debugging not supported"),
        ]
    )
    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    def test_must_raise_user_exception_on_invalid_sam_template(
        self, exeception_to_raise, execption_message, invoke_context_mock
    ):

        invoke_context_mock.side_effect = exeception_to_raise

        with self.assertRaises(UserException) as context:
            self.call_cli()

        msg = str(context.exception)
        expected = execption_message
        self.assertEqual(msg, expected)

    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    def test_must_raise_user_exception_on_invalid_env_vars(self, invoke_context_mock):
        invoke_context_mock.side_effect = OverridesNotWellDefinedError("bad env vars")

        with self.assertRaises(UserException) as context:
            self.call_cli()

        msg = str(context.exception)
        expected = "bad env vars"
        self.assertEqual(msg, expected)

    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    def test_must_raise_user_exception_on_no_free_ports(self, invoke_context_mock):
        invoke_context_mock.side_effect = ContainerNotStartableException("no free ports on host to bind with container")

        with self.assertRaises(UserException) as context:
            self.call_cli()

        msg = str(context.exception)
        expected = "no free ports on host to bind with container"
        self.assertEqual(msg, expected)

    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    def test_must_raise_user_exception_on_invalid_imageuri(self, invoke_context_mock):
        invoke_context_mock.side_effect = InvalidIntermediateImageError("invalid imageuri")

        with self.assertRaises(UserException) as context:
            self.call_cli()

        msg = str(context.exception)
        expected = "invalid imageuri"
        self.assertEqual(msg, expected)

    def call_cli(self):
        start_api_cli(
            ctx=self.ctx_mock,
            host=self.host,
            port=self.port,
            static_dir=self.static_dir,
            template=self.template,
            env_vars=self.env_vars,
            debug_port=self.debug_ports,
            debug_args=self.debug_args,
            debugger_path=self.debugger_path,
            container_env_vars=self.container_env_vars,
            docker_volume_basedir=self.docker_volume_basedir,
            docker_network=self.docker_network,
            log_file=self.log_file,
            skip_pull_image=self.skip_pull_image,
            parameter_overrides=self.parameter_overrides,
            layer_cache_basedir=self.layer_cache_basedir,
            force_image_build=self.force_image_build,
            warm_containers=self.warm_containers,
            debug_function=self.debug_function,
            shutdown=self.shutdown,
        )
Esempio n. 7
0
class TestCli(TestCase):
    def setUp(self):
        self.template = "template"
        self.env_vars = "env-vars"
        self.debug_port = 123
        self.debug_args = "args"
        self.debugger_path = "/test/path"
        self.docker_volume_basedir = "basedir"
        self.docker_network = "network"
        self.log_file = "logfile"
        self.skip_pull_image = True
        self.parameter_overrides = {}
        self.layer_cache_basedir = "/some/layers/path"
        self.force_image_build = True
        self.region_name = "region"
        self.profile = "profile"

        self.ctx_mock = Mock()
        self.ctx_mock.region = self.region_name
        self.ctx_mock.profile = self.profile

        self.host = "host"
        self.port = 123

    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    @patch("samcli.commands.local.lib.local_lambda_service.LocalLambdaService")
    def test_cli_must_setup_context_and_start_service(self, local_lambda_service_mock, invoke_context_mock):
        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        invoke_context_mock.return_value.__enter__.return_value = context_mock

        service_mock = Mock()
        local_lambda_service_mock.return_value = service_mock

        self.call_cli()

        invoke_context_mock.assert_called_with(
            template_file=self.template,
            function_identifier=None,
            env_vars_file=self.env_vars,
            docker_volume_basedir=self.docker_volume_basedir,
            docker_network=self.docker_network,
            log_file=self.log_file,
            skip_pull_image=self.skip_pull_image,
            debug_port=self.debug_port,
            debug_args=self.debug_args,
            debugger_path=self.debugger_path,
            parameter_overrides=self.parameter_overrides,
            layer_cache_basedir=self.layer_cache_basedir,
            force_image_build=self.force_image_build,
            aws_region=self.region_name,
            aws_profile=self.profile,
        )

        local_lambda_service_mock.assert_called_with(lambda_invoke_context=context_mock, port=self.port, host=self.host)

        service_mock.start.assert_called_with()

    @parameterized.expand(
        [
            (InvalidSamDocumentException("bad template"), "bad template"),
            (
                InvalidLayerReference(),
                "Layer References need to be of type " "'AWS::Serverless::LayerVersion' or 'AWS::Lambda::LayerVersion'",
            ),
            (DebuggingNotSupported("Debugging not supported"), "Debugging not supported"),
        ]
    )
    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    def test_must_raise_user_exception_on_invalid_sam_template(
        self, exeception_to_raise, execption_message, invoke_context_mock
    ):
        invoke_context_mock.side_effect = exeception_to_raise

        with self.assertRaises(UserException) as context:
            self.call_cli()

        msg = str(context.exception)
        expected = execption_message
        self.assertEqual(msg, expected)

    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    def test_must_raise_user_exception_on_invalid_env_vars(self, invoke_context_mock):
        invoke_context_mock.side_effect = OverridesNotWellDefinedError("bad env vars")

        with self.assertRaises(UserException) as context:
            self.call_cli()

        msg = str(context.exception)
        expected = "bad env vars"
        self.assertEqual(msg, expected)

    def call_cli(self):
        start_lambda_cli(
            ctx=self.ctx_mock,
            host=self.host,
            port=self.port,
            template=self.template,
            env_vars=self.env_vars,
            debug_port=self.debug_port,
            debug_args=self.debug_args,
            debugger_path=self.debugger_path,
            docker_volume_basedir=self.docker_volume_basedir,
            docker_network=self.docker_network,
            log_file=self.log_file,
            skip_pull_image=self.skip_pull_image,
            parameter_overrides=self.parameter_overrides,
            layer_cache_basedir=self.layer_cache_basedir,
            force_image_build=self.force_image_build,
        )
Esempio n. 8
0
class TestCli(TestCase):
    def setUp(self):
        self.function_id = "id"
        self.template = "template"
        self.eventfile = "eventfile"
        self.env_vars = "env-vars"
        self.debug_port = 123
        self.debug_args = "args"
        self.debugger_path = "/test/path"
        self.docker_volume_basedir = "basedir"
        self.docker_network = "network"
        self.log_file = "logfile"
        self.skip_pull_image = True
        self.no_event = False
        self.parameter_overrides = {}
        self.layer_cache_basedir = "/some/layers/path"
        self.force_image_build = True
        self.region_name = "region"

    @patch("samcli.commands.local.invoke.cli.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_cli_must_setup_context_and_invoke(self, get_event_mock,
                                               InvokeContextMock):
        event_data = "data"
        get_event_mock.return_value = event_data

        ctx_mock = Mock()
        ctx_mock.region = self.region_name

        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        InvokeContextMock.return_value.__enter__.return_value = context_mock

        invoke_cli(ctx=ctx_mock,
                   function_identifier=self.function_id,
                   template=self.template,
                   event=self.eventfile,
                   no_event=self.no_event,
                   env_vars=self.env_vars,
                   debug_port=self.debug_port,
                   debug_args=self.debug_args,
                   debugger_path=self.debugger_path,
                   docker_volume_basedir=self.docker_volume_basedir,
                   docker_network=self.docker_network,
                   log_file=self.log_file,
                   skip_pull_image=self.skip_pull_image,
                   parameter_overrides=self.parameter_overrides,
                   layer_cache_basedir=self.layer_cache_basedir,
                   force_image_build=self.force_image_build)

        InvokeContextMock.assert_called_with(
            template_file=self.template,
            function_identifier=self.function_id,
            env_vars_file=self.env_vars,
            docker_volume_basedir=self.docker_volume_basedir,
            docker_network=self.docker_network,
            log_file=self.log_file,
            skip_pull_image=self.skip_pull_image,
            debug_port=self.debug_port,
            debug_args=self.debug_args,
            debugger_path=self.debugger_path,
            parameter_overrides=self.parameter_overrides,
            layer_cache_basedir=self.layer_cache_basedir,
            force_image_build=self.force_image_build,
            aws_region=self.region_name)

        context_mock.local_lambda_runner.invoke.assert_called_with(
            context_mock.function_name,
            event=event_data,
            stdout=context_mock.stdout,
            stderr=context_mock.stderr)
        get_event_mock.assert_called_with(self.eventfile)

    @patch("samcli.commands.local.invoke.cli.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_cli_must_invoke_with_no_event(self, get_event_mock,
                                           InvokeContextMock):
        self.no_event = True

        ctx_mock = Mock()
        ctx_mock.region = self.region_name

        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        InvokeContextMock.return_value.__enter__.return_value = context_mock
        invoke_cli(ctx=ctx_mock,
                   function_identifier=self.function_id,
                   template=self.template,
                   event=STDIN_FILE_NAME,
                   no_event=self.no_event,
                   env_vars=self.env_vars,
                   debug_port=self.debug_port,
                   debug_args=self.debug_args,
                   debugger_path=self.debugger_path,
                   docker_volume_basedir=self.docker_volume_basedir,
                   docker_network=self.docker_network,
                   log_file=self.log_file,
                   skip_pull_image=self.skip_pull_image,
                   parameter_overrides=self.parameter_overrides,
                   layer_cache_basedir=self.layer_cache_basedir,
                   force_image_build=self.force_image_build)

        InvokeContextMock.assert_called_with(
            template_file=self.template,
            function_identifier=self.function_id,
            env_vars_file=self.env_vars,
            docker_volume_basedir=self.docker_volume_basedir,
            docker_network=self.docker_network,
            log_file=self.log_file,
            skip_pull_image=self.skip_pull_image,
            debug_port=self.debug_port,
            debug_args=self.debug_args,
            debugger_path=self.debugger_path,
            parameter_overrides=self.parameter_overrides,
            layer_cache_basedir=self.layer_cache_basedir,
            force_image_build=self.force_image_build,
            aws_region=self.region_name)

        context_mock.local_lambda_runner.invoke.assert_called_with(
            context_mock.function_name,
            event="{}",
            stdout=context_mock.stdout,
            stderr=context_mock.stderr)
        get_event_mock.assert_not_called()

    @patch("samcli.commands.local.invoke.cli.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_must_raise_user_exception_on_no_event_and_event(
            self, get_event_mock, InvokeContextMock):
        self.no_event = True

        ctx_mock = Mock()
        ctx_mock.region = self.region_name

        with self.assertRaises(UserException) as ex_ctx:

            invoke_cli(ctx=ctx_mock,
                       function_identifier=self.function_id,
                       template=self.template,
                       event=self.eventfile,
                       no_event=self.no_event,
                       env_vars=self.env_vars,
                       debug_port=self.debug_port,
                       debug_args=self.debug_args,
                       debugger_path=self.debugger_path,
                       docker_volume_basedir=self.docker_volume_basedir,
                       docker_network=self.docker_network,
                       log_file=self.log_file,
                       skip_pull_image=self.skip_pull_image,
                       parameter_overrides=self.parameter_overrides,
                       layer_cache_basedir=self.layer_cache_basedir,
                       force_image_build=self.force_image_build)

        msg = str(ex_ctx.exception)
        self.assertEquals(
            msg,
            "no_event and event cannot be used together. Please provide only one."
        )

    @parameterized.expand([
        param(FunctionNotFound("not found"),
              "Function id not found in template"),
        param(DockerImagePullFailedException("Failed to pull image"),
              "Failed to pull image")
    ])
    @patch("samcli.commands.local.invoke.cli.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_must_raise_user_exception_on_function_not_found(
            self, side_effect_exception, expected_exectpion_message,
            get_event_mock, InvokeContextMock):
        event_data = "data"
        get_event_mock.return_value = event_data

        ctx_mock = Mock()
        ctx_mock.region = self.region_name

        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        InvokeContextMock.return_value.__enter__.return_value = context_mock

        context_mock.local_lambda_runner.invoke.side_effect = side_effect_exception

        with self.assertRaises(UserException) as ex_ctx:

            invoke_cli(ctx=ctx_mock,
                       function_identifier=self.function_id,
                       template=self.template,
                       event=self.eventfile,
                       no_event=self.no_event,
                       env_vars=self.env_vars,
                       debug_port=self.debug_port,
                       debug_args=self.debug_args,
                       debugger_path=self.debugger_path,
                       docker_volume_basedir=self.docker_volume_basedir,
                       docker_network=self.docker_network,
                       log_file=self.log_file,
                       skip_pull_image=self.skip_pull_image,
                       parameter_overrides=self.parameter_overrides,
                       layer_cache_basedir=self.layer_cache_basedir,
                       force_image_build=self.force_image_build)

        msg = str(ex_ctx.exception)
        self.assertEquals(msg, expected_exectpion_message)

    @parameterized.expand([
        (InvalidSamDocumentException("bad template"), "bad template"),
        (InvalidLayerReference(), "Layer References need to be of type "
         "'AWS::Serverless::LayerVersion' or 'AWS::Lambda::LayerVersion'"),
        (DebuggingNotSupported("Debugging not supported"),
         "Debugging not supported")
    ])
    @patch("samcli.commands.local.invoke.cli.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_must_raise_user_exception_on_invalid_sam_template(
            self, exeception_to_raise, execption_message, get_event_mock,
            InvokeContextMock):
        event_data = "data"
        get_event_mock.return_value = event_data

        ctx_mock = Mock()
        ctx_mock.region = self.region_name

        InvokeContextMock.side_effect = exeception_to_raise

        with self.assertRaises(UserException) as ex_ctx:

            invoke_cli(ctx=ctx_mock,
                       function_identifier=self.function_id,
                       template=self.template,
                       event=self.eventfile,
                       no_event=self.no_event,
                       env_vars=self.env_vars,
                       debug_port=self.debug_port,
                       debug_args=self.debug_args,
                       debugger_path=self.debugger_path,
                       docker_volume_basedir=self.docker_volume_basedir,
                       docker_network=self.docker_network,
                       log_file=self.log_file,
                       skip_pull_image=self.skip_pull_image,
                       parameter_overrides=self.parameter_overrides,
                       layer_cache_basedir=self.layer_cache_basedir,
                       force_image_build=self.force_image_build)

        msg = str(ex_ctx.exception)
        self.assertEquals(msg, execption_message)

    @patch("samcli.commands.local.invoke.cli.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_must_raise_user_exception_on_invalid_env_vars(
            self, get_event_mock, InvokeContextMock):
        event_data = "data"
        get_event_mock.return_value = event_data

        ctx_mock = Mock()
        ctx_mock.region = self.region_name

        InvokeContextMock.side_effect = OverridesNotWellDefinedError(
            "bad env vars")

        with self.assertRaises(UserException) as ex_ctx:

            invoke_cli(ctx=ctx_mock,
                       function_identifier=self.function_id,
                       template=self.template,
                       event=self.eventfile,
                       no_event=self.no_event,
                       env_vars=self.env_vars,
                       debug_port=self.debug_port,
                       debug_args=self.debug_args,
                       debugger_path=self.debugger_path,
                       docker_volume_basedir=self.docker_volume_basedir,
                       docker_network=self.docker_network,
                       log_file=self.log_file,
                       skip_pull_image=self.skip_pull_image,
                       parameter_overrides=self.parameter_overrides,
                       layer_cache_basedir=self.layer_cache_basedir,
                       force_image_build=self.force_image_build)

        msg = str(ex_ctx.exception)
        self.assertEquals(msg, "bad env vars")
Esempio n. 9
0
class TestCli(TestCase):
    def setUp(self):
        self.function_id = "id"
        self.template = "template"
        self.eventfile = "eventfile"
        self.env_vars = "env-vars"
        self.container_env_vars = "debug-env-vars"
        self.debug_ports = [123]
        self.debug_args = "args"
        self.debugger_path = "/test/path"
        self.docker_volume_basedir = "basedir"
        self.docker_network = "network"
        self.log_file = "logfile"
        self.skip_pull_image = True
        self.no_event = True
        self.parameter_overrides = {}
        self.layer_cache_basedir = "/some/layers/path"
        self.force_image_build = True
        self.shutdown = False
        self.region_name = "region"
        self.profile = "profile"

    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_cli_must_setup_context_and_invoke(self, get_event_mock,
                                               InvokeContextMock):
        event_data = "data"
        get_event_mock.return_value = event_data

        ctx_mock = Mock()
        ctx_mock.region = self.region_name
        ctx_mock.profile = self.profile

        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        InvokeContextMock.return_value.__enter__.return_value = context_mock

        invoke_cli(
            ctx=ctx_mock,
            function_identifier=self.function_id,
            template=self.template,
            event=self.eventfile,
            no_event=self.no_event,
            env_vars=self.env_vars,
            debug_port=self.debug_ports,
            debug_args=self.debug_args,
            debugger_path=self.debugger_path,
            container_env_vars=self.container_env_vars,
            docker_volume_basedir=self.docker_volume_basedir,
            docker_network=self.docker_network,
            log_file=self.log_file,
            skip_pull_image=self.skip_pull_image,
            parameter_overrides=self.parameter_overrides,
            layer_cache_basedir=self.layer_cache_basedir,
            force_image_build=self.force_image_build,
            shutdown=self.shutdown,
        )

        InvokeContextMock.assert_called_with(
            template_file=self.template,
            function_identifier=self.function_id,
            env_vars_file=self.env_vars,
            docker_volume_basedir=self.docker_volume_basedir,
            docker_network=self.docker_network,
            log_file=self.log_file,
            skip_pull_image=self.skip_pull_image,
            debug_ports=self.debug_ports,
            debug_args=self.debug_args,
            debugger_path=self.debugger_path,
            container_env_vars_file=self.container_env_vars,
            parameter_overrides=self.parameter_overrides,
            layer_cache_basedir=self.layer_cache_basedir,
            force_image_build=self.force_image_build,
            shutdown=self.shutdown,
            aws_region=self.region_name,
            aws_profile=self.profile,
        )

        context_mock.local_lambda_runner.invoke.assert_called_with(
            context_mock.function_identifier,
            event=event_data,
            stdout=context_mock.stdout,
            stderr=context_mock.stderr)
        get_event_mock.assert_called_with(self.eventfile)

    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_cli_must_invoke_with_no_event(self, get_event_mock,
                                           InvokeContextMock):
        self.event = None

        ctx_mock = Mock()
        ctx_mock.region = self.region_name
        ctx_mock.profile = self.profile

        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        InvokeContextMock.return_value.__enter__.return_value = context_mock
        invoke_cli(
            ctx=ctx_mock,
            function_identifier=self.function_id,
            template=self.template,
            event=self.event,
            no_event=self.no_event,
            env_vars=self.env_vars,
            debug_port=self.debug_ports,
            debug_args=self.debug_args,
            debugger_path=self.debugger_path,
            container_env_vars=self.container_env_vars,
            docker_volume_basedir=self.docker_volume_basedir,
            docker_network=self.docker_network,
            log_file=self.log_file,
            skip_pull_image=self.skip_pull_image,
            parameter_overrides=self.parameter_overrides,
            layer_cache_basedir=self.layer_cache_basedir,
            force_image_build=self.force_image_build,
            shutdown=self.shutdown,
        )

        InvokeContextMock.assert_called_with(
            template_file=self.template,
            function_identifier=self.function_id,
            env_vars_file=self.env_vars,
            docker_volume_basedir=self.docker_volume_basedir,
            docker_network=self.docker_network,
            log_file=self.log_file,
            skip_pull_image=self.skip_pull_image,
            debug_ports=self.debug_ports,
            debug_args=self.debug_args,
            debugger_path=self.debugger_path,
            container_env_vars_file=self.container_env_vars,
            parameter_overrides=self.parameter_overrides,
            layer_cache_basedir=self.layer_cache_basedir,
            force_image_build=self.force_image_build,
            shutdown=self.shutdown,
            aws_region=self.region_name,
            aws_profile=self.profile,
        )

        get_event_mock.assert_not_called()
        context_mock.local_lambda_runner.invoke.assert_called_with(
            context_mock.function_identifier,
            event="{}",
            stdout=context_mock.stdout,
            stderr=context_mock.stderr)

    @parameterized.expand([
        param(FunctionNotFound("not found"),
              "Function id not found in template"),
        param(DockerImagePullFailedException("Failed to pull image"),
              "Failed to pull image"),
    ])
    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_must_raise_user_exception_on_function_not_found(
            self, side_effect_exception, expected_exectpion_message,
            get_event_mock, InvokeContextMock):
        event_data = "data"
        get_event_mock.return_value = event_data

        ctx_mock = Mock()
        ctx_mock.region = self.region_name
        ctx_mock.profile = self.profile

        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        InvokeContextMock.return_value.__enter__.return_value = context_mock

        context_mock.local_lambda_runner.invoke.side_effect = side_effect_exception

        with self.assertRaises(UserException) as ex_ctx:

            invoke_cli(
                ctx=ctx_mock,
                function_identifier=self.function_id,
                template=self.template,
                event=self.eventfile,
                no_event=self.no_event,
                env_vars=self.env_vars,
                debug_port=self.debug_ports,
                debug_args=self.debug_args,
                debugger_path=self.debugger_path,
                container_env_vars=self.container_env_vars,
                docker_volume_basedir=self.docker_volume_basedir,
                docker_network=self.docker_network,
                log_file=self.log_file,
                skip_pull_image=self.skip_pull_image,
                parameter_overrides=self.parameter_overrides,
                layer_cache_basedir=self.layer_cache_basedir,
                force_image_build=self.force_image_build,
                shutdown=self.shutdown,
            )

        msg = str(ex_ctx.exception)
        self.assertEqual(msg, expected_exectpion_message)

    @parameterized.expand([
        param(
            InvalidIntermediateImageError(
                "ImageUri not set to a reference-able image for Function: MyFunction"
            ),
            "ImageUri not set to a reference-able image for Function: MyFunction",
        ),
    ])
    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_must_raise_user_exception_on_function_local_invoke_image_not_found_for_IMAGE_packagetype(
            self, side_effect_exception, expected_exectpion_message,
            get_event_mock, InvokeContextMock):
        event_data = "data"
        get_event_mock.return_value = event_data

        ctx_mock = Mock()
        ctx_mock.region = self.region_name
        ctx_mock.profile = self.profile

        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        InvokeContextMock.return_value.__enter__.return_value = context_mock

        context_mock.local_lambda_runner.invoke.side_effect = side_effect_exception

        with self.assertRaises(UserException) as ex_ctx:

            invoke_cli(
                ctx=ctx_mock,
                function_identifier=self.function_id,
                template=self.template,
                event=self.eventfile,
                no_event=self.no_event,
                env_vars=self.env_vars,
                debug_port=self.debug_ports,
                debug_args=self.debug_args,
                debugger_path=self.debugger_path,
                container_env_vars=self.container_env_vars,
                docker_volume_basedir=self.docker_volume_basedir,
                docker_network=self.docker_network,
                log_file=self.log_file,
                skip_pull_image=self.skip_pull_image,
                parameter_overrides=self.parameter_overrides,
                layer_cache_basedir=self.layer_cache_basedir,
                force_image_build=self.force_image_build,
                shutdown=self.shutdown,
            )

        msg = str(ex_ctx.exception)
        self.assertEqual(msg, expected_exectpion_message)

    @parameterized.expand([
        (InvalidSamDocumentException("bad template"), "bad template"),
        (
            InvalidLayerReference(),
            "Layer References need to be of type "
            "'AWS::Serverless::LayerVersion' or 'AWS::Lambda::LayerVersion'",
        ),
        (DebuggingNotSupported("Debugging not supported"),
         "Debugging not supported"),
    ])
    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_must_raise_user_exception_on_invalid_sam_template(
            self, exeception_to_raise, execption_message, get_event_mock,
            InvokeContextMock):
        event_data = "data"
        get_event_mock.return_value = event_data

        ctx_mock = Mock()
        ctx_mock.region = self.region_name
        ctx_mock.profile = self.profile

        InvokeContextMock.side_effect = exeception_to_raise

        with self.assertRaises(UserException) as ex_ctx:

            invoke_cli(
                ctx=ctx_mock,
                function_identifier=self.function_id,
                template=self.template,
                event=self.eventfile,
                no_event=self.no_event,
                env_vars=self.env_vars,
                debug_port=self.debug_ports,
                debug_args=self.debug_args,
                debugger_path=self.debugger_path,
                container_env_vars=self.container_env_vars,
                docker_volume_basedir=self.docker_volume_basedir,
                docker_network=self.docker_network,
                log_file=self.log_file,
                skip_pull_image=self.skip_pull_image,
                parameter_overrides=self.parameter_overrides,
                layer_cache_basedir=self.layer_cache_basedir,
                force_image_build=self.force_image_build,
                shutdown=self.shutdown,
            )

        msg = str(ex_ctx.exception)
        self.assertEqual(msg, execption_message)

    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_must_raise_user_exception_on_invalid_env_vars(
            self, get_event_mock, InvokeContextMock):
        event_data = "data"
        get_event_mock.return_value = event_data

        ctx_mock = Mock()
        ctx_mock.region = self.region_name
        ctx_mock.profile = self.profile

        InvokeContextMock.side_effect = OverridesNotWellDefinedError(
            "bad env vars")

        with self.assertRaises(UserException) as ex_ctx:

            invoke_cli(
                ctx=ctx_mock,
                function_identifier=self.function_id,
                template=self.template,
                event=self.eventfile,
                no_event=self.no_event,
                env_vars=self.env_vars,
                debug_port=self.debug_ports,
                debug_args=self.debug_args,
                debugger_path=self.debugger_path,
                container_env_vars=self.container_env_vars,
                docker_volume_basedir=self.docker_volume_basedir,
                docker_network=self.docker_network,
                log_file=self.log_file,
                skip_pull_image=self.skip_pull_image,
                parameter_overrides=self.parameter_overrides,
                layer_cache_basedir=self.layer_cache_basedir,
                force_image_build=self.force_image_build,
                shutdown=self.shutdown,
            )

        msg = str(ex_ctx.exception)
        self.assertEqual(msg, "bad env vars")

    @parameterized.expand([
        param(
            ContainerNotStartableException(
                "Container cannot be started, no free ports on host"),
            "Container cannot be started, no free ports on host",
        ),
    ])
    @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext")
    @patch("samcli.commands.local.invoke.cli._get_event")
    def test_must_raise_user_exception_on_function_no_free_ports(
            self, side_effect_exception, expected_exectpion_message,
            get_event_mock, InvokeContextMock):
        event_data = "data"
        get_event_mock.return_value = event_data

        ctx_mock = Mock()
        ctx_mock.region = self.region_name
        ctx_mock.profile = self.profile

        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        InvokeContextMock.return_value.__enter__.return_value = context_mock

        context_mock.local_lambda_runner.invoke.side_effect = side_effect_exception

        with self.assertRaises(UserException) as ex_ctx:

            invoke_cli(
                ctx=ctx_mock,
                function_identifier=self.function_id,
                template=self.template,
                event=self.eventfile,
                no_event=self.no_event,
                env_vars=self.env_vars,
                debug_port=self.debug_ports,
                debug_args=self.debug_args,
                debugger_path=self.debugger_path,
                container_env_vars=self.container_env_vars,
                docker_volume_basedir=self.docker_volume_basedir,
                docker_network=self.docker_network,
                log_file=self.log_file,
                skip_pull_image=self.skip_pull_image,
                parameter_overrides=self.parameter_overrides,
                layer_cache_basedir=self.layer_cache_basedir,
                force_image_build=self.force_image_build,
                shutdown=self.shutdown,
            )

        msg = str(ex_ctx.exception)
        self.assertEqual(msg, expected_exectpion_message)