samcli/commands/remote/invoke/cli.py (162 lines of code) (raw):
"""CLI command for "invoke" command."""
import logging
from io import TextIOWrapper
import click
from samcli.cli.cli_config_file import ConfigProvider, configuration_option, save_params_option
from samcli.cli.context import Context
from samcli.cli.main import aws_creds_options, common_options, pass_context, print_cmdline_args
from samcli.cli.types import RemoteInvokeOutputFormatType
from samcli.commands._utils.command_exception_handler import command_exception_handler
from samcli.commands._utils.options import remote_invoke_parameter_option
from samcli.commands.remote.invoke.core.command import RemoteInvokeCommand
from samcli.lib.cli_validation.remote_invoke_options_validations import (
event_and_event_file_options_validation,
stack_name_or_resource_id_atleast_one_option_validation,
)
from samcli.lib.remote_invoke.remote_invoke_executors import RemoteInvokeOutputFormat
from samcli.lib.telemetry.event import EventTracker
from samcli.lib.telemetry.metric import track_command
from samcli.lib.utils.resources import AWS_LAMBDA_FUNCTION
from samcli.lib.utils.version_checker import check_newer_version
LOG = logging.getLogger(__name__)
HELP_TEXT = """
Invoke or send an event to resources in the cloud.
"""
SHORT_HELP = "Invoke a deployed resource in the cloud"
DESCRIPTION = """
Invoke or send an event to resources in the cloud.
An event body can be passed using either -e (--event) or --event-file parameter.
This command can be used to invoke a Lambda Function and get the output payload, start a State Machine execution
and wait for the output of the final step, send a message to SQS Queue, or put a data record to
Kinesis Data Streams.
Returned response will be written to stdout. Lambda logs and Step Function execution
errors will be written to stderr.
"""
@click.command(
"invoke",
cls=RemoteInvokeCommand,
help=HELP_TEXT,
description=DESCRIPTION,
short_help=SHORT_HELP,
requires_credentials=True,
context_settings={"max_content_width": 120},
)
@configuration_option(provider=ConfigProvider(section="parameters"))
@click.option("--stack-name", required=False, help="Name of the stack to get the resource information from")
@click.argument("resource-id", required=False)
@click.option(
"--event",
"-e",
help="The event that will be sent to the resource. The target parameter will depend on the resource type. "
"For instance: 'Payload' for Lambda which can be passed as a JSON string, 'Input' for Step Functions, "
"'MessageBody' for SQS, and 'Data' for Kinesis data streams.",
)
@click.option(
"--event-file",
type=click.File("r", encoding="utf-8"),
help="The file that contains the event that will be sent to the resource.",
)
@click.option(
"--test-event-name",
help="Name of the remote test event to send to the resource",
)
@click.option(
"--output",
help="Output the results from the command in a given output format. "
"The text format prints a readable AWS API response. The json format prints the full AWS API response.",
default=RemoteInvokeOutputFormat.TEXT.name.lower(),
type=RemoteInvokeOutputFormatType(RemoteInvokeOutputFormat),
)
@remote_invoke_parameter_option
@stack_name_or_resource_id_atleast_one_option_validation
@event_and_event_file_options_validation
@common_options
@aws_creds_options
@save_params_option
@pass_context
@track_command
@check_newer_version
@print_cmdline_args
@command_exception_handler
def cli(
ctx: Context,
stack_name: str,
resource_id: str,
event: str,
event_file: TextIOWrapper,
output: RemoteInvokeOutputFormat,
test_event_name: str,
parameter: dict,
save_params: bool,
config_file: str,
config_env: str,
) -> None:
"""
`sam remote invoke` command entry point
"""
do_cli(
stack_name,
resource_id,
event,
event_file,
output,
parameter,
test_event_name,
ctx.region,
ctx.profile,
config_file,
config_env,
)
def do_cli(
stack_name: str,
resource_id: str,
event: str,
event_file: TextIOWrapper,
output: RemoteInvokeOutputFormat,
parameter: dict,
test_event_name: str,
region: str,
profile: str,
config_file: str,
config_env: str,
) -> None:
"""
Implementation of the ``cli`` method
"""
from botocore.exceptions import (
NoCredentialsError,
NoRegionError,
ProfileNotFound,
)
from samcli.commands.exceptions import UserException
from samcli.commands.remote.remote_invoke_context import RemoteInvokeContext
from samcli.lib.remote_invoke.exceptions import (
ErrorBotoApiCallException,
InvalideBotoResponseException,
InvalidResourceBotoParameterException,
)
from samcli.lib.remote_invoke.remote_invoke_executors import RemoteInvokeEventType, RemoteInvokeExecutionInfo
from samcli.lib.utils.boto_utils import get_boto_client_provider_with_config, get_boto_resource_provider_with_config
try:
boto_client_provider = get_boto_client_provider_with_config(region_name=region, profile=profile)
boto_resource_provider = get_boto_resource_provider_with_config(region_name=region, profile=profile)
with RemoteInvokeContext(
boto_client_provider=boto_client_provider,
boto_resource_provider=boto_resource_provider,
stack_name=stack_name,
resource_id=resource_id,
) as remote_invoke_context:
if (
test_event_name
and remote_invoke_context.resource_summary
and remote_invoke_context.resource_summary.resource_type == AWS_LAMBDA_FUNCTION
):
lambda_test_event = remote_invoke_context.get_lambda_shared_test_event_provider()
LOG.debug("Retrieving remote event %s", test_event_name)
event = lambda_test_event.get_event(test_event_name, remote_invoke_context.resource_summary)
LOG.debug("Remote event contents: %s", event)
elif test_event_name:
LOG.info("Note: remote event is only supported for AWS Lambda Function resource.")
test_event_name = ""
event_type = RemoteInvokeEventType.get_event_type(
event=event,
event_file=event_file,
test_event_name=test_event_name,
)
EventTracker.track_event("RemoteInvokeEventType", event_type)
remote_invoke_input = RemoteInvokeExecutionInfo(
payload=event, payload_file=event_file, parameters=parameter, output_format=output
)
remote_invoke_context.run(remote_invoke_input=remote_invoke_input)
except (
ErrorBotoApiCallException,
InvalideBotoResponseException,
InvalidResourceBotoParameterException,
ProfileNotFound,
NoCredentialsError,
NoRegionError,
) as ex:
raise UserException(str(ex), wrapped_from=ex.__class__.__name__) from ex