From e653fe214255357aa6eb025dc060b2672d9e8e51 Mon Sep 17 00:00:00 2001 From: Xia Zhao <78883180+xazhao@users.noreply.github.com> Date: Tue, 23 Mar 2021 13:59:40 -0700 Subject: [PATCH] feat: add option --container-host to commands local start-api, local start-lambda and local invoke (#2700) --- .../local/cli_common/invoke_context.py | 6 ++ samcli/commands/local/cli_common/options.py | 11 ++- samcli/commands/local/invoke/cli.py | 4 + samcli/commands/local/lib/local_lambda.py | 12 ++- samcli/commands/local/start_api/cli.py | 4 + samcli/commands/local/start_lambda/cli.py | 4 + samcli/local/docker/container.py | 10 ++- samcli/local/docker/lambda_container.py | 4 + samcli/local/lambdafn/runtime.py | 14 +++- .../local/cli_common/test_invoke_context.py | 74 +++++++++++++++++++ tests/unit/commands/local/invoke/test_cli.py | 10 +++ .../commands/local/lib/test_local_lambda.py | 46 +++++++++++- .../unit/commands/local/start_api/test_cli.py | 4 + .../commands/local/start_lambda/test_cli.py | 4 + .../unit/commands/samconfig/test_samconfig.py | 7 ++ tests/unit/local/docker/test_container.py | 8 +- tests/unit/local/lambdafn/test_runtime.py | 5 ++ 17 files changed, 214 insertions(+), 13 deletions(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index 111ee2c908..db4f723c15 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -75,6 +75,7 @@ def __init__( warm_container_initialization_mode: Optional[str] = None, debug_function: Optional[str] = None, shutdown: bool = False, + container_host: Optional[str] = None, ) -> None: """ Initialize the context @@ -121,6 +122,8 @@ def __init__( option is enabled shutdown bool Optional. If True, perform a SHUTDOWN event when tearing down containers. Default False. + container_host string + Optional. Host of locally emulated Lambda container """ self._template_file = template_file self._function_identifier = function_identifier @@ -146,6 +149,8 @@ def __init__( self._aws_profile = aws_profile self._shutdown = shutdown + self._container_host = container_host + self._containers_mode = ContainersMode.COLD self._containers_initializing_mode = ContainersInitializationMode.LAZY @@ -327,6 +332,7 @@ def local_lambda_runner(self) -> LocalLambdaRunner: aws_region=self._aws_region, env_vars_values=self._env_vars_value, debug_context=self._debug_context, + container_host=self._container_host, ) return self._local_lambda_runner diff --git a/samcli/commands/local/cli_common/options.py b/samcli/commands/local/cli_common/options.py index e5d19413c1..287b476c57 100644 --- a/samcli/commands/local/cli_common/options.py +++ b/samcli/commands/local/cli_common/options.py @@ -48,7 +48,16 @@ def local_common_options(f): default=False, help="If set, will emulate a shutdown event after the invoke completes, " "in order to test extension handling of shutdown behavior.", - ) + ), + click.option( + "--container-host", + default="localhost", + show_default=True, + help="Host of locally emulated Lambda container. " + "This option is useful when the container runs on a different host than SAM CLI. " + "For example, if you want to run SAM CLI in a Docker container on macOS, " + "use this option with host.docker.internal", + ), ] # Reverse the list to maintain ordering of options in help text printed with --help diff --git a/samcli/commands/local/invoke/cli.py b/samcli/commands/local/invoke/cli.py index ef1bdf56c8..2ea1a4ba7f 100644 --- a/samcli/commands/local/invoke/cli.py +++ b/samcli/commands/local/invoke/cli.py @@ -72,6 +72,7 @@ def cli( parameter_overrides, config_file, config_env, + container_host, ): """ `sam local invoke` command entry point @@ -97,6 +98,7 @@ def cli( force_image_build, shutdown, parameter_overrides, + container_host, ) # pragma: no cover @@ -119,6 +121,7 @@ def do_cli( # pylint: disable=R0914 force_image_build, shutdown, parameter_overrides, + container_host, ): """ Implementation of the ``cli`` method, just separated out for unit testing purposes @@ -161,6 +164,7 @@ def do_cli( # pylint: disable=R0914 aws_region=ctx.region, aws_profile=ctx.profile, shutdown=shutdown, + container_host=container_host, ) as context: # Invoke the function diff --git a/samcli/commands/local/lib/local_lambda.py b/samcli/commands/local/lib/local_lambda.py index 13d78bd66b..61425aa171 100644 --- a/samcli/commands/local/lib/local_lambda.py +++ b/samcli/commands/local/lib/local_lambda.py @@ -43,6 +43,7 @@ def __init__( aws_region: Optional[str] = None, env_vars_values: Optional[Dict[Any, Any]] = None, debug_context: Optional[DebugContext] = None, + container_host: Optional[str] = None, ) -> None: """ Initializes the class @@ -55,6 +56,7 @@ def __init__( :param string aws_region: Optional. AWS Region to use. :param dict env_vars_values: Optional. Dictionary containing values of environment variables. :param DebugContext debug_context: Optional. Debug context for the function (includes port, args, and path). + :param string container_host: Optional. Host of locally emulated Lambda container """ self.local_runtime = local_runtime @@ -66,6 +68,7 @@ def __init__( self.debug_context = debug_context self._boto3_session_creds: Optional[Dict[str, str]] = None self._boto3_region: Optional[str] = None + self.container_host = container_host def invoke( self, @@ -121,7 +124,14 @@ def invoke( # Invoke the function try: - self.local_runtime.invoke(config, event, debug_context=self.debug_context, stdout=stdout, stderr=stderr) + self.local_runtime.invoke( + config, + event, + debug_context=self.debug_context, + stdout=stdout, + stderr=stderr, + container_host=self.container_host, + ) except ContainerResponseException: # NOTE(sriram-mv): This should still result in a exit code zero to avoid regressions. LOG.info("No response from invoke container for %s", function.name) diff --git a/samcli/commands/local/start_api/cli.py b/samcli/commands/local/start_api/cli.py index 1fafe62dfa..45b3f3dbd4 100644 --- a/samcli/commands/local/start_api/cli.py +++ b/samcli/commands/local/start_api/cli.py @@ -81,6 +81,7 @@ def cli( warm_containers, shutdown, debug_function, + container_host, ): """ `sam local start-api` command entry point @@ -108,6 +109,7 @@ def cli( warm_containers, shutdown, debug_function, + container_host, ) # pragma: no cover @@ -132,6 +134,7 @@ def do_cli( # pylint: disable=R0914 warm_containers, shutdown, debug_function, + container_host, ): """ Implementation of the ``cli`` method, just separated out for unit testing purposes @@ -172,6 +175,7 @@ def do_cli( # pylint: disable=R0914 warm_container_initialization_mode=warm_containers, debug_function=debug_function, shutdown=shutdown, + container_host=container_host, ) as invoke_context: service = LocalApiService(lambda_invoke_context=invoke_context, port=port, host=host, static_dir=static_dir) diff --git a/samcli/commands/local/start_lambda/cli.py b/samcli/commands/local/start_lambda/cli.py index 995e57ca04..197ee1a9ef 100644 --- a/samcli/commands/local/start_lambda/cli.py +++ b/samcli/commands/local/start_lambda/cli.py @@ -92,6 +92,7 @@ def cli( warm_containers, shutdown, debug_function, + container_host, ): """ `sam local start-lambda` command entry point @@ -118,6 +119,7 @@ def cli( warm_containers, shutdown, debug_function, + container_host, ) # pragma: no cover @@ -141,6 +143,7 @@ def do_cli( # pylint: disable=R0914 warm_containers, shutdown, debug_function, + container_host, ): """ Implementation of the ``cli`` method, just separated out for unit testing purposes @@ -180,6 +183,7 @@ def do_cli( # pylint: disable=R0914 warm_container_initialization_mode=warm_containers, debug_function=debug_function, shutdown=shutdown, + container_host=container_host, ) as invoke_context: service = LocalLambdaService(lambda_invoke_context=invoke_context, port=port, host=host) diff --git a/samcli/local/docker/container.py b/samcli/local/docker/container.py index fbaf237224..943b5b995e 100644 --- a/samcli/local/docker/container.py +++ b/samcli/local/docker/container.py @@ -38,7 +38,7 @@ class Container: _STDOUT_FRAME_TYPE = 1 _STDERR_FRAME_TYPE = 2 RAPID_PORT_CONTAINER = "8080" - URL = "http://localhost:{port}/2015-03-31/functions/{function_name}/invocations" + URL = "http://{host}:{port}/2015-03-31/functions/{function_name}/invocations" # Set connection timeout to 1 sec to support the large input. RAPID_CONNECTION_TIMEOUT = 1 @@ -55,6 +55,7 @@ def __init__( docker_client=None, container_opts=None, additional_volumes=None, + container_host="localhost", ): """ Initializes the class with given configuration. This does not automatically create or run the container. @@ -71,6 +72,7 @@ def __init__( :param docker_client: Optional, a docker client to replace the default one loaded from env :param container_opts: Optional, a dictionary containing the container options :param additional_volumes: Optional list of additional volumes + :param string container_host: Optional. Host of locally emulated Lambda container """ self._image = image @@ -96,6 +98,9 @@ def __init__( # selecting the first free port in a range that's not ephemeral. self._start_port_range = 5000 self._end_port_range = 9000 + + self._container_host = container_host + try: self.rapid_port_host = find_free_port(start=self._start_port_range, end=self._end_port_range) except NoFreePortsError as ex: @@ -266,8 +271,9 @@ def wait_for_http_response(self, name, event, stdout): # TODO(sriram-mv): `aws-lambda-rie` is in a mode where the function_name is always "function" # NOTE(sriram-mv): There is a connection timeout set on the http call to `aws-lambda-rie`, however there is not # a read time out for the response received from the server. + resp = requests.post( - self.URL.format(port=self.rapid_port_host, function_name="function"), + self.URL.format(host=self._container_host, port=self.rapid_port_host, function_name="function"), data=event.encode("utf-8"), timeout=(self.RAPID_CONNECTION_TIMEOUT, None), ) diff --git a/samcli/local/docker/lambda_container.py b/samcli/local/docker/lambda_container.py index 87d79f1b44..b36dd7b4b7 100644 --- a/samcli/local/docker/lambda_container.py +++ b/samcli/local/docker/lambda_container.py @@ -45,6 +45,7 @@ def __init__( memory_mb=128, env_vars=None, debug_options=None, + container_host=None, ): """ Initializes the class @@ -74,6 +75,8 @@ def __init__( Optional. Dictionary containing environment variables passed to container debug_options DebugContext Optional. Contains container debugging info (port, debugger path) + container_host string + Optional. Host of locally emulated Lambda container """ if not Runtime.has_value(runtime) and not packagetype == IMAGE: raise ValueError("Unsupported Lambda runtime {}".format(runtime)) @@ -119,6 +122,7 @@ def __init__( env_vars=env_vars, container_opts=additional_options, additional_volumes=additional_volumes, + container_host=container_host, ) @staticmethod diff --git a/samcli/local/lambdafn/runtime.py b/samcli/local/lambdafn/runtime.py index 62f88fc20d..bbbe824ac8 100644 --- a/samcli/local/lambdafn/runtime.py +++ b/samcli/local/lambdafn/runtime.py @@ -44,7 +44,7 @@ def __init__(self, container_manager, image_builder): self._image_builder = image_builder self._temp_uncompressed_paths_to_be_cleaned = [] - def create(self, function_config, debug_context=None): + def create(self, function_config, debug_context=None, container_host=None): """ Create a new Container for the passed function, then store it in a dictionary using the function name, so it can be retrieved later and used in the other functions. Make sure to use the debug_context only @@ -56,6 +56,8 @@ def create(self, function_config, debug_context=None): Configuration of the function to create a new Container for it. debug_context DebugContext Debugging context for the function (includes port, args, and path) + container_host string + Host of locally emulated Lambda container Returns ------- @@ -78,6 +80,7 @@ def create(self, function_config, debug_context=None): memory_mb=function_config.memory, env_vars=env_vars, debug_options=debug_context, + container_host=container_host, ) try: # create the container. @@ -132,6 +135,7 @@ def invoke( debug_context=None, stdout: Optional[StreamWriter] = None, stderr: Optional[StreamWriter] = None, + container_host=None, ): """ Invoke the given Lambda function locally. @@ -150,13 +154,15 @@ def invoke( StreamWriter that receives stdout text from container. :param samcli.lib.utils.stream_writer.StreamWriter stderr: Optional. StreamWriter that receives stderr text from container. + :param string container_host: Optional. + Host of locally emulated Lambda container :raises Keyboard """ timer = None container = None try: # Start the container. This call returns immediately after the container starts - container = self.create(function_config, debug_context) + container = self.create(function_config, debug_context, container_host) container = self.run(container, function_config, debug_context) # Setup appropriate interrupt - timeout or Ctrl+C - before function starts executing. # @@ -301,7 +307,7 @@ def __init__(self, container_manager, image_builder): super().__init__(container_manager, image_builder) - def create(self, function_config, debug_context=None): + def create(self, function_config, debug_context=None, container_host=None): """ Create a new Container for the passed function, then store it in a dictionary using the function name, so it can be retrieved later and used in the other functions. Make sure to use the debug_context only @@ -336,7 +342,7 @@ def create(self, function_config, debug_context=None): ) debug_context = None - container = super().create(function_config, debug_context) + container = super().create(function_config, debug_context, container_host) self._containers[function_config.name] = container self._observer.watch(function_config) diff --git a/tests/unit/commands/local/cli_common/test_invoke_context.py b/tests/unit/commands/local/cli_common/test_invoke_context.py index 1f744d9d57..f3732b05c1 100644 --- a/tests/unit/commands/local/cli_common/test_invoke_context.py +++ b/tests/unit/commands/local/cli_common/test_invoke_context.py @@ -543,6 +543,7 @@ def test_must_create_runner( env_vars_values=ANY, aws_profile="profile", aws_region="region", + container_host=None, ) result = self.context.local_lambda_runner @@ -614,6 +615,79 @@ def test_must_create_runner_using_warm_containers( env_vars_values=ANY, aws_profile="profile", aws_region="region", + container_host=None, + ) + + 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) + + @patch("samcli.commands.local.cli_common.invoke_context.LambdaImage") + @patch("samcli.commands.local.cli_common.invoke_context.LayerDownloader") + @patch("samcli.commands.local.cli_common.invoke_context.LambdaRuntime") + @patch("samcli.commands.local.cli_common.invoke_context.LocalLambdaRunner") + @patch("samcli.commands.local.cli_common.invoke_context.SamFunctionProvider") + def test_must_create_runner_with_container_host_option( + self, SamFunctionProviderMock, LocalLambdaMock, LambdaRuntimeMock, download_layers_mock, lambda_image_patch + ): + runtime_mock = Mock() + LambdaRuntimeMock.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", + container_host="localhost", + ) + 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) + + LambdaRuntimeMock.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", + container_host="localhost", ) result = self.context.local_lambda_runner diff --git a/tests/unit/commands/local/invoke/test_cli.py b/tests/unit/commands/local/invoke/test_cli.py index cf4f39881a..8f5dfad569 100644 --- a/tests/unit/commands/local/invoke/test_cli.py +++ b/tests/unit/commands/local/invoke/test_cli.py @@ -41,6 +41,7 @@ def setUp(self): self.shutdown = False self.region_name = "region" self.profile = "profile" + self.container_host = "localhost" @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext") @patch("samcli.commands.local.invoke.cli._get_event") @@ -75,6 +76,7 @@ def test_cli_must_setup_context_and_invoke(self, get_event_mock, InvokeContextMo layer_cache_basedir=self.layer_cache_basedir, force_image_build=self.force_image_build, shutdown=self.shutdown, + container_host=self.container_host, ) InvokeContextMock.assert_called_with( @@ -95,6 +97,7 @@ def test_cli_must_setup_context_and_invoke(self, get_event_mock, InvokeContextMo shutdown=self.shutdown, aws_region=self.region_name, aws_profile=self.profile, + container_host=self.container_host, ) context_mock.local_lambda_runner.invoke.assert_called_with( @@ -133,6 +136,7 @@ def test_cli_must_invoke_with_no_event(self, get_event_mock, InvokeContextMock): layer_cache_basedir=self.layer_cache_basedir, force_image_build=self.force_image_build, shutdown=self.shutdown, + container_host=self.container_host, ) InvokeContextMock.assert_called_with( @@ -153,6 +157,7 @@ def test_cli_must_invoke_with_no_event(self, get_event_mock, InvokeContextMock): shutdown=self.shutdown, aws_region=self.region_name, aws_profile=self.profile, + container_host=self.container_host, ) get_event_mock.assert_not_called() @@ -205,6 +210,7 @@ def test_must_raise_user_exception_on_function_not_found( layer_cache_basedir=self.layer_cache_basedir, force_image_build=self.force_image_build, shutdown=self.shutdown, + container_host=self.container_host, ) msg = str(ex_ctx.exception) @@ -257,6 +263,7 @@ def test_must_raise_user_exception_on_function_local_invoke_image_not_found_for_ layer_cache_basedir=self.layer_cache_basedir, force_image_build=self.force_image_build, shutdown=self.shutdown, + container_host=self.container_host, ) msg = str(ex_ctx.exception) @@ -307,6 +314,7 @@ def test_must_raise_user_exception_on_invalid_sam_template( layer_cache_basedir=self.layer_cache_basedir, force_image_build=self.force_image_build, shutdown=self.shutdown, + container_host=self.container_host, ) msg = str(ex_ctx.exception) @@ -345,6 +353,7 @@ def test_must_raise_user_exception_on_invalid_env_vars(self, get_event_mock, Inv layer_cache_basedir=self.layer_cache_basedir, force_image_build=self.force_image_build, shutdown=self.shutdown, + container_host=self.container_host, ) msg = str(ex_ctx.exception) @@ -397,6 +406,7 @@ def test_must_raise_user_exception_on_function_no_free_ports( layer_cache_basedir=self.layer_cache_basedir, force_image_build=self.force_image_build, shutdown=self.shutdown, + container_host=self.container_host, ) msg = str(ex_ctx.exception) diff --git a/tests/unit/commands/local/lib/test_local_lambda.py b/tests/unit/commands/local/lib/test_local_lambda.py index a1e377152b..af30fcddf9 100644 --- a/tests/unit/commands/local/lib/test_local_lambda.py +++ b/tests/unit/commands/local/lib/test_local_lambda.py @@ -518,7 +518,7 @@ def test_must_work(self): self.local_lambda.invoke(name, event, stdout, stderr) self.runtime_mock.invoke.assert_called_with( - invoke_config, event, debug_context=None, stdout=stdout, stderr=stderr + invoke_config, event, debug_context=None, stdout=stdout, stderr=stderr, container_host=None ) def test_must_work_packagetype_ZIP(self): @@ -536,7 +536,7 @@ def test_must_work_packagetype_ZIP(self): self.local_lambda.invoke(name, event, stdout, stderr) self.runtime_mock.invoke.assert_called_with( - invoke_config, event, debug_context=None, stdout=stdout, stderr=stderr + invoke_config, event, debug_context=None, stdout=stdout, stderr=stderr, container_host=None ) def test_must_raise_if_no_privilege(self): @@ -609,7 +609,7 @@ def test_works_if_imageuri_and_Image_packagetype(self): self.local_lambda.get_invoke_config.return_value = invoke_config self.local_lambda.invoke(name, event, stdout, stderr) self.runtime_mock.invoke.assert_called_with( - invoke_config, event, debug_context=None, stdout=stdout, stderr=stderr + invoke_config, event, debug_context=None, stdout=stdout, stderr=stderr, container_host=None ) def test_must_raise_if_imageuri_not_found(self): @@ -625,6 +625,45 @@ def test_must_raise_if_imageuri_not_found(self): self.local_lambda.invoke(name, event, stdout, stderr) +class TestLocalLambda_invoke_with_container_host_option(TestCase): + def setUp(self): + self.runtime_mock = Mock() + self.function_provider_mock = Mock() + self.cwd = "/my/current/working/directory" + self.debug_context = None + self.aws_profile = "myprofile" + self.aws_region = "region" + self.env_vars_values = {} + self.container_host = "localhost" + + self.local_lambda = LocalLambdaRunner( + self.runtime_mock, + self.function_provider_mock, + self.cwd, + env_vars_values=self.env_vars_values, + debug_context=self.debug_context, + container_host=self.container_host, + ) + + def test_must_work(self): + name = "name" + event = "event" + stdout = "stdout" + stderr = "stderr" + function = Mock(functionname="name") + invoke_config = "config" + + self.function_provider_mock.get_all.return_value = [function] + self.local_lambda.get_invoke_config = Mock() + self.local_lambda.get_invoke_config.return_value = invoke_config + + self.local_lambda.invoke(name, event, stdout, stderr) + + self.runtime_mock.invoke.assert_called_with( + invoke_config, event, debug_context=None, stdout=stdout, stderr=stderr, container_host="localhost" + ) + + class TestLocalLambda_is_debugging(TestCase): def setUp(self): self.runtime_mock = Mock() @@ -647,7 +686,6 @@ def test_must_be_on(self): self.assertTrue(self.local_lambda.is_debugging()) def test_must_be_off(self): - self.local_lambda = LocalLambdaRunner( self.runtime_mock, self.function_provider_mock, diff --git a/tests/unit/commands/local/start_api/test_cli.py b/tests/unit/commands/local/start_api/test_cli.py index b470f576df..62323824cb 100644 --- a/tests/unit/commands/local/start_api/test_cli.py +++ b/tests/unit/commands/local/start_api/test_cli.py @@ -47,6 +47,8 @@ def setUp(self): self.port = 123 self.static_dir = "staticdir" + self.container_host = "localhost" + @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): @@ -82,6 +84,7 @@ def test_cli_must_setup_context_and_start_service(self, local_api_service_mock, warm_container_initialization_mode=self.warm_containers, debug_function=self.debug_function, shutdown=self.shutdown, + container_host=self.container_host, ) local_api_service_mock.assert_called_with( @@ -188,4 +191,5 @@ def call_cli(self): warm_containers=self.warm_containers, debug_function=self.debug_function, shutdown=self.shutdown, + container_host=self.container_host, ) diff --git a/tests/unit/commands/local/start_lambda/test_cli.py b/tests/unit/commands/local/start_lambda/test_cli.py index 202a30d0b9..95505a1d41 100644 --- a/tests/unit/commands/local/start_lambda/test_cli.py +++ b/tests/unit/commands/local/start_lambda/test_cli.py @@ -40,6 +40,8 @@ def setUp(self): self.host = "host" self.port = 123 + self.container_host = "localhost" + @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): @@ -74,6 +76,7 @@ def test_cli_must_setup_context_and_start_service(self, local_lambda_service_moc warm_container_initialization_mode=self.warm_containers, debug_function=self.debug_function, shutdown=self.shutdown, + container_host=self.container_host, ) local_lambda_service_mock.assert_called_with(lambda_invoke_context=context_mock, port=self.port, host=self.host) @@ -157,4 +160,5 @@ def call_cli(self): warm_containers=self.warm_containers, debug_function=self.debug_function, shutdown=self.shutdown, + container_host=self.container_host, ) diff --git a/tests/unit/commands/samconfig/test_samconfig.py b/tests/unit/commands/samconfig/test_samconfig.py index d27469ec45..3e8da14f35 100644 --- a/tests/unit/commands/samconfig/test_samconfig.py +++ b/tests/unit/commands/samconfig/test_samconfig.py @@ -256,6 +256,7 @@ def test_local_invoke(self, do_cli_mock): True, True, {"Key": "Value", "Key2": "Value2"}, + "localhost", ) @patch("samcli.commands.local.start_api.cli.do_cli") @@ -317,6 +318,7 @@ def test_local_start_api(self, do_cli_mock): None, False, None, + "localhost", ) @patch("samcli.commands.local.start_lambda.cli.do_cli") @@ -376,6 +378,7 @@ def test_local_start_lambda(self, do_cli_mock): None, False, None, + "localhost", ) @patch("samcli.lib.cli_validation.image_repository_validation.get_template_function_resource_ids") @@ -793,6 +796,8 @@ def test_override_with_cli_params(self, do_cli_mock): "--shutdown", "--parameter-overrides", "A=123 C=D E=F12! G=H", + "--container-host", + "localhost", ], ) @@ -822,6 +827,7 @@ def test_override_with_cli_params(self, do_cli_mock): None, True, None, + "localhost", ) @patch("samcli.commands.local.start_lambda.cli.do_cli") @@ -913,6 +919,7 @@ def test_override_with_cli_params_and_envvars(self, do_cli_mock): None, False, None, + "localhost", ) @patch("samcli.commands.validate.validate.do_cli") diff --git a/tests/unit/local/docker/test_container.py b/tests/unit/local/docker/test_container.py index a853bfd5bb..ae348ebab8 100644 --- a/tests/unit/local/docker/test_container.py +++ b/tests/unit/local/docker/test_container.py @@ -513,12 +513,18 @@ def setUp(self): self.cmd = ["cmd"] self.working_dir = "working_dir" self.host_dir = "host_dir" + self.container_host = "localhost" self.mock_docker_client = Mock() self.mock_docker_client.containers = Mock() self.mock_docker_client.containers.get = Mock() self.container = Container( - self.image, self.cmd, self.working_dir, self.host_dir, docker_client=self.mock_docker_client + self.image, + self.cmd, + self.working_dir, + self.host_dir, + docker_client=self.mock_docker_client, + container_host=self.container_host, ) self.container.id = "someid" diff --git a/tests/unit/local/lambdafn/test_runtime.py b/tests/unit/local/lambdafn/test_runtime.py index f569a1aea3..99b6f83732 100644 --- a/tests/unit/local/lambdafn/test_runtime.py +++ b/tests/unit/local/lambdafn/test_runtime.py @@ -81,6 +81,7 @@ def test_must_create_lambda_container(self, LambdaContainerMock): debug_options=debug_options, env_vars=self.env_var_value, memory_mb=self.DEFAULT_MEMORY, + container_host=None, ) # Run the container and get results self.manager_mock.create.assert_called_with(container) @@ -269,6 +270,7 @@ def test_must_run_container_and_wait_for_result(self, LambdaContainerMock): debug_options=debug_options, env_vars=self.env_var_value, memory_mb=self.DEFAULT_MEMORY, + container_host=None, ) # Run the container and get results @@ -595,6 +597,7 @@ def test_must_run_container_then_wait_for_result_and_container_not_stopped( debug_options=debug_options, env_vars=self.env_var_value, memory_mb=self.DEFAULT_MEMORY, + container_host=None, ) # Run the container and get results @@ -672,6 +675,7 @@ def test_must_create_non_cached_container(self, LambdaContainerMock, LambdaFunct debug_options=debug_options, env_vars=self.env_var_value, memory_mb=self.DEFAULT_MEMORY, + container_host=None, ) self.manager_mock.create.assert_called_with(container) @@ -737,6 +741,7 @@ def test_must_ignore_debug_options_if_function_name_is_not_debug_function( debug_options=None, env_vars=self.env_var_value, memory_mb=self.DEFAULT_MEMORY, + container_host=None, ) self.manager_mock.create.assert_called_with(container) # validate that the created container got cached