forked from aws/aws-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(LocalLambdaInvokeService): Command interface for `sam local star…
…t-lambda` (aws#544)
- Loading branch information
Showing
11 changed files
with
321 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
""" | ||
Connects the CLI with Local Lambda Invoke Service. | ||
""" | ||
import logging | ||
|
||
from samcli.local.lambda_service.local_lambda_invoke_service import LocalLambdaInvokeService | ||
|
||
LOG = logging.getLogger(__name__) | ||
|
||
|
||
class LocalLambdaService(object): | ||
""" | ||
Implementation of Local Lambda Invoke Service that is capable of serving the invoke path to your Lambda Functions | ||
that are defined in a SAM file. | ||
""" | ||
|
||
def __init__(self, | ||
lambda_invoke_context, | ||
port, | ||
host): | ||
""" | ||
Initialize the Local Lambda Invoke service. | ||
:param samcli.commands.local.cli_common.invoke_context.InvokeContext lambda_invoke_context: Context object | ||
that can help with Lambda invocation | ||
:param int port: Port to listen on | ||
:param string host: Local hostname or IP address to bind to | ||
""" | ||
|
||
self.port = port | ||
self.host = host | ||
self.lambda_runner = lambda_invoke_context.local_lambda_runner | ||
self.stderr_stream = lambda_invoke_context.stderr | ||
|
||
def start(self): | ||
""" | ||
Creates and starts the Local Lambda Invoke service. This method will block until the service is stopped | ||
manually using an interrupt. After the service is started, callers can make HTTP requests to the endpoint | ||
to invoke the Lambda function and receive a response. | ||
NOTE: This is a blocking call that will not return until the thread is interrupted with SIGINT/SIGTERM | ||
""" | ||
|
||
# We care about passing only stderr to the Service and not stdout because stdout from Docker container | ||
# contains the response to the API which is sent out as HTTP response. Only stderr needs to be printed | ||
# to the console or a log file. stderr from Docker container contains runtime logs and output of print | ||
# statements from the Lambda function | ||
service = LocalLambdaInvokeService(lambda_runner=self.lambda_runner, | ||
port=self.port, | ||
host=self.host, | ||
stderr=self.stderr_stream) | ||
|
||
service.create() | ||
|
||
LOG.info("Starting the Local Lambda Service. You can now invoke your Lambda Functions defined in your template" | ||
"through the endpoint.") | ||
|
||
service.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
""" | ||
CLI command for "local start-lambda" command | ||
""" | ||
|
||
import logging | ||
import click | ||
|
||
from samcli.cli.main import pass_context, common_options as cli_framework_options | ||
from samcli.commands.local.cli_common.options import invoke_common_options, service_common_options | ||
from samcli.commands.local.cli_common.invoke_context import InvokeContext | ||
from samcli.commands.local.cli_common.user_exceptions import UserException | ||
from samcli.commands.local.lib.local_lambda_service import LocalLambdaService | ||
from samcli.commands.validate.lib.exceptions import InvalidSamDocumentException | ||
|
||
LOG = logging.getLogger(__name__) | ||
|
||
HELP_TEXT = """ | ||
Allows you to run a Local Lambda Service that will service the invoke path to your functions for quick development & | ||
testing through the AWS CLI or SDKs. When run in a directory that contains your Serverless functions and your AWS | ||
SAM template, it will create a local HTTP server that wil response to the invoke call to your functions. | ||
When accessed (via browser, cli etc), it will launch a Docker container locally to invoke the function. It will read | ||
the CodeUri property of AWS::Serverless::Function resource to find the path in your file system containing the Lambda | ||
Function code. This could be the project's root directory for interpreted languages like Node & Python, or a build | ||
directory that stores your compiled artifacts or a JAR file. If you are using a interpreted language, local changes | ||
will be available immediately in Docker container on every invoke. For more compiled languages or projects requiring | ||
complex packing support, we recommended you run your own building solution and point SAM to the directory or file | ||
containing build artifacts. | ||
""" | ||
|
||
|
||
@click.command("start-lambda", help=HELP_TEXT, short_help="Runs a Local Lambda Service (for the Invoke path only)") | ||
@service_common_options(3001) | ||
@invoke_common_options | ||
@cli_framework_options | ||
@pass_context | ||
def cli(ctx, | ||
# start-lambda Specific Options | ||
host, port, | ||
|
||
# Common Options for Lambda Invoke | ||
template, env_vars, debug_port, debug_args, docker_volume_basedir, | ||
docker_network, log_file, skip_pull_image, profile | ||
): | ||
# All logic must be implemented in the ``do_cli`` method. This helps with easy unit testing | ||
|
||
do_cli(ctx, host, port, template, env_vars, debug_port, debug_args, docker_volume_basedir, | ||
docker_network, log_file, skip_pull_image, profile) # pragma: no cover | ||
|
||
|
||
def do_cli(ctx, host, port, template, env_vars, debug_port, debug_args, # pylint: disable=R0914 | ||
docker_volume_basedir, docker_network, log_file, skip_pull_image, profile): | ||
""" | ||
Implementation of the ``cli`` method, just separated out for unit testing purposes | ||
""" | ||
|
||
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, | ||
debug_port=debug_port, | ||
debug_args=debug_args, | ||
docker_volume_basedir=docker_volume_basedir, | ||
docker_network=docker_network, | ||
log_file=log_file, | ||
skip_pull_image=skip_pull_image, | ||
aws_profile=profile) as invoke_context: | ||
|
||
service = LocalLambdaService(lambda_invoke_context=invoke_context, | ||
port=port, | ||
host=host) | ||
service.start() | ||
|
||
except InvalidSamDocumentException as ex: | ||
raise UserException(str(ex)) |
45 changes: 45 additions & 0 deletions
45
tests/unit/commands/local/lib/test_local_lambda_service.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from unittest import TestCase | ||
from mock import Mock, patch | ||
|
||
from samcli.commands.local.lib.local_lambda_service import LocalLambdaService | ||
|
||
|
||
class TestLocalLambdaService(TestCase): | ||
|
||
def test_initialization(self): | ||
lambda_runner_mock = Mock() | ||
stderr_mock = Mock() | ||
lambda_invoke_context_mock = Mock() | ||
|
||
lambda_invoke_context_mock.local_lambda_runner = lambda_runner_mock | ||
lambda_invoke_context_mock.stderr = stderr_mock | ||
|
||
service = LocalLambdaService(lambda_invoke_context=lambda_invoke_context_mock, port=3000, host='localhost') | ||
|
||
self.assertEquals(service.port, 3000) | ||
self.assertEquals(service.host, 'localhost') | ||
self.assertEquals(service.lambda_runner, lambda_runner_mock) | ||
self.assertEquals(service.stderr_stream, stderr_mock) | ||
|
||
@patch('samcli.commands.local.lib.local_lambda_service.LocalLambdaInvokeService') | ||
def test_start(self, local_lambda_invoke_service_mock): | ||
lambda_runner_mock = Mock() | ||
stderr_mock = Mock() | ||
lambda_invoke_context_mock = Mock() | ||
|
||
lambda_context_mock = Mock() | ||
local_lambda_invoke_service_mock.return_value = lambda_context_mock | ||
|
||
lambda_invoke_context_mock.local_lambda_runner = lambda_runner_mock | ||
lambda_invoke_context_mock.stderr = stderr_mock | ||
|
||
service = LocalLambdaService(lambda_invoke_context=lambda_invoke_context_mock, port=3000, host='localhost') | ||
|
||
service.start() | ||
|
||
local_lambda_invoke_service_mock.assert_called_once_with(lambda_runner=lambda_runner_mock, | ||
port=3000, | ||
host='localhost', | ||
stderr=stderr_mock) | ||
lambda_context_mock.create.assert_called_once() | ||
lambda_context_mock.run.assert_called_once() |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.