def do_cli(ctx, host, port, static_dir, template, env_vars, debug_port, debug_args, # pylint: disable=R0914 debugger_path, docker_volume_basedir, docker_network, log_file, skip_pull_image, profile, region): """ Implementation of the ``cli`` method, just separated out for unit testing purposes """ 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, aws_profile=profile, debug_port=debug_port, debug_args=debug_args, debugger_path=debugger_path, aws_region=region) 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 as ex: raise UserException(str(ex))
def test_must_start_service(self, make_routing_list_mock, log_routes_mock, make_static_dir_mock, SamApiProviderMock, ApiGwServiceMock): routing_list = [1, 2, 3] # something static_dir_path = "/foo/bar" make_routing_list_mock.return_value = routing_list make_static_dir_mock.return_value = static_dir_path SamApiProviderMock.return_value = self.api_provider_mock ApiGwServiceMock.return_value = self.apigw_service # Now start the service local_service = LocalApiService(self.lambda_invoke_context_mock, self.port, self.host, self.static_dir) local_service.start() # Make sure the right methods are called SamApiProviderMock.assert_called_with(self.template, cwd=self.cwd) make_routing_list_mock.assert_called_with(self.api_provider_mock) log_routes_mock.assert_called_with(self.api_provider_mock, self.host, self.port) make_static_dir_mock.assert_called_with(self.cwd, self.static_dir) ApiGwServiceMock.assert_called_with(routing_list=routing_list, lambda_runner=self.lambda_runner_mock, static_dir=static_dir_path, port=self.port, host=self.host, stderr=self.stderr_mock) self.apigw_service.create.assert_called_with() self.apigw_service.run.assert_called_with()
def test_must_raise_if_route_not_available( self, extract_api, log_routes_mock, make_static_dir_mock, SamApiProviderMock, ApiGwServiceMock ): routing_list = [] # Empty api = Api() extract_api.return_value = api SamApiProviderMock.extract_api.return_value = api SamApiProviderMock.return_value = self.api_provider_mock ApiGwServiceMock.return_value = self.apigw_service # Now start the service local_service = LocalApiService(self.lambda_invoke_context_mock, self.port, self.host, self.static_dir) local_service.api_provider.api.routes = routing_list with self.assertRaises(NoApisDefined): local_service.start()
def test_must_print_routes(self): host = "host" port = 123 api_provider = Mock() apis = [ Api(path="/1", method="GET", function_name="name1", cors="CORS1"), Api(path="/1", method="POST", function_name="name1", cors="CORS1"), Api(path="/1", method="DELETE", function_name="othername1", cors="CORS1"), Api(path="/2", method="GET2", function_name="name2", cors="CORS2"), Api(path="/3", method="GET3", function_name="name3", cors="CORS3"), ] api_provider.get_all.return_value = apis expected = { "Mounting name1 at http://host:123/1 [GET, POST]", "Mounting othername1 at http://host:123/1 [DELETE]", "Mounting name2 at http://host:123/2 [GET2]", "Mounting name3 at http://host:123/3 [GET3]" } actual = LocalApiService._print_routes(api_provider, host, port) self.assertEquals(expected, set(actual))
def test_make_routing_list(self): routing_list = LocalApiService._make_routing_list( self.api_provider_mock) expected_routes = [ Route(function_name=self.function_name, methods=['GET'], path='/get', stage_name=None, stage_variables=None), Route(function_name=self.function_name, methods=['GET'], path='/get', stage_name='Dev', stage_variables=None), Route(function_name=self.function_name, methods=['POST'], path='/post', stage_name='Prod', stage_variables=None), Route(function_name=self.function_name, methods=['GET'], path='/get', stage_name=None, stage_variables={'test': 'data'}), Route(function_name=self.function_name, methods=['POST'], path='/post', stage_name='Prod', stage_variables={'data': 'more data'}), ] self.assertEquals(len(routing_list), len(expected_routes)) for index, r in enumerate(routing_list): self.assertEquals(r.__dict__, expected_routes[index].__dict__)
def test_must_return_none_if_path_not_exists(self, os_mock): static_dir = "mydir" cwd = "cwd" resolved_path = "cwd/mydir" os_mock.path.join.return_value = resolved_path os_mock.path.exists.return_value = False # Resolved path does not exist result = LocalApiService._make_static_dir_path(cwd, static_dir) self.assertIsNone(result)
def test_must_resolve_with_respect_to_cwd(self, os_mock): static_dir = "mydir" cwd = "cwd" resolved_path = "cwd/mydir" os_mock.path.join.return_value = resolved_path os_mock.path.exists.return_value = True # Fake the path to exist result = LocalApiService._make_static_dir_path(cwd, static_dir) self.assertEquals(resolved_path, result) os_mock.path.join.assert_called_with(cwd, static_dir) os_mock.path.exists.assert_called_with(resolved_path)
def test_must_serve_static_files(self, sam_api_provider_mock): sam_api_provider_mock.return_value = self.api_provider_mock local_service = LocalApiService( self.lambda_invoke_context_mock, self.port, self.host, self.static_dir ) # Mount the static directory self._start_service_thread(local_service) # NOTE: The URL does not contain the static_dir because this directory is mounted directly at / response = requests.get("{}/{}".format(self.url, self.static_file_name)) self.assertEqual(response.status_code, 200) self.assertEqual(self.static_file_content, response.text)
def test_must_start_service_and_serve_endpoints(self, sam_api_provider_mock): sam_api_provider_mock.return_value = self.api_provider_mock local_service = LocalApiService( self.lambda_invoke_context_mock, self.port, self.host, None ) # No static directory self._start_service_thread(local_service) response = requests.get(self.url + "/get") self.assertEqual(response.status_code, 200) response = requests.post(self.url + "/post", {}) self.assertEqual(response.status_code, 200) response = requests.get(self.url + "/post") self.assertEqual(response.status_code, 403) # "HTTP GET /post" must not exist
def test_must_return_routing_list_from_apis(self): api_provider = Mock() apis = [ Api(path="/1", method="GET1", function_name="name1", cors="CORS1"), Api(path="/2", method="GET2", function_name="name2", cors="CORS2"), Api(path="/3", method="GET3", function_name="name3", cors="CORS3"), ] expected = [ Route(path="/1", methods=["GET1"], function_name="name1"), Route(path="/2", methods=["GET2"], function_name="name2"), Route(path="/3", methods=["GET3"], function_name="name3") ] api_provider.get_all.return_value = apis result = LocalApiService._make_routing_list(api_provider) self.assertEquals(len(result), len(expected)) for index, r in enumerate(result): self.assertEquals(r.__dict__, expected[index].__dict__)
def test_must_print_routes(self): host = "host" port = 123 apis = [ Route(path="/1", methods=["GET"], function_name="name1"), Route(path="/1", methods=["POST"], function_name="name1"), Route(path="/1", methods=["DELETE"], function_name="othername1"), Route(path="/2", methods=["GET2"], function_name="name2"), Route(path="/3", methods=["GET3"], function_name="name3"), ] apis = ApiCollector.dedupe_function_routes(apis) expected = {"Mounting name1 at http://host:123/1 [GET, POST]", "Mounting othername1 at http://host:123/1 [DELETE]", "Mounting name2 at http://host:123/2 [GET2]", "Mounting name3 at http://host:123/3 [GET3]"} actual = LocalApiService._print_routes(apis, host, port) self.assertEquals(expected, set(actual))
def test_must_skip_if_none(self): result = LocalApiService._make_static_dir_path("something", None) self.assertIsNone(result)
def do_cli( # pylint: disable=R0914 ctx, host, port, static_dir, 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.lib.exceptions import NoApisDefined from samcli.lib.providers.exceptions import 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_settings 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_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 = LocalApiService(lambda_invoke_context=invoke_context, port=port, host=host, static_dir=static_dir) service.start() except NoApisDefined as ex: raise UserException( "Template does not have any APIs connected to Lambda functions", wrapped_from=ex.__class__.__name__) from ex 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