Skip to content
6 changes: 3 additions & 3 deletions samcli/lib/remote_invoke/lambda_invoke_executors.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,16 @@ class DefaultConvertToJSON(RemoteInvokeRequestResponseMapper[RemoteInvokeExecuti
def map(self, test_input: RemoteInvokeExecutionInfo) -> RemoteInvokeExecutionInfo:
if not test_input.is_file_provided():
if not test_input.payload:
LOG.debug("Input event not found, invoking Lambda Function with an empty event")
LOG.debug("Input event not found, invoking resource with an empty event")
test_input.payload = "{}"
LOG.debug("Mapping input Payload to JSON string object")
LOG.debug("Mapping input event to JSON string object")
try:
_ = json.loads(cast(str, test_input.payload))
except JSONDecodeError:
json_value = json.dumps(test_input.payload)
LOG.info(
"Auto converting value '%s' into JSON '%s'. "
"If you don't want auto-conversion, please provide a JSON string as payload",
"If you don't want auto-conversion, please provide a JSON string as event",
test_input.payload,
json_value,
)
Expand Down
17 changes: 9 additions & 8 deletions tests/integration/remote/invoke/remote_invoke_integ_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
run_command,
)
from tests.integration.deploy.deploy_integ_base import DeployIntegBase
from samcli.lib.remote_invoke.remote_invoke_executor_factory import RemoteInvokeExecutorFactory

from samcli.lib.utils.boto_utils import get_boto_resource_provider_with_config, get_boto_client_provider_with_config
from samcli.lib.utils.cloudformation import get_resource_summaries
Expand Down Expand Up @@ -47,17 +48,17 @@ def remote_invoke_deploy_stack(stack_name, template_path):
@classmethod
def create_resources_and_boto_clients(cls):
cls.remote_invoke_deploy_stack(cls.stack_name, cls.template_path)
stack_resource_summaries = get_resource_summaries(
boto_client_provider = get_boto_client_provider_with_config()
cls.stack_resource_summaries = get_resource_summaries(
get_boto_resource_provider_with_config(),
get_boto_client_provider_with_config(),
boto_client_provider,
cls.stack_name,
)
cls.stack_resources = {
resource_full_path: stack_resource_summary.physical_resource_id
for resource_full_path, stack_resource_summary in stack_resource_summaries.items()
}
cls.cfn_client = get_boto_client_provider_with_config()("cloudformation")
cls.lambda_client = get_boto_client_provider_with_config()("lambda")
cls.supported_resources = RemoteInvokeExecutorFactory.REMOTE_INVOKE_EXECUTOR_MAPPING.keys()
cls.cfn_client = boto_client_provider("cloudformation")
cls.lambda_client = boto_client_provider("lambda")
cls.stepfunctions_client = boto_client_provider("stepfunctions")
cls.xray_client = boto_client_provider("xray")

@staticmethod
def get_command_list(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class TestInvokeResponseStreamingLambdas(RemoteInvokeIntegBase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.stack_name = f"{TestInvokeResponseStreamingLambdas.__name__}-{uuid.uuid4().hex}"
cls.stack_name = f"{cls.__name__}-{uuid.uuid4().hex}"
cls.create_resources_and_boto_clients()

def test_invoke_empty_event_provided(self):
Expand Down
218 changes: 181 additions & 37 deletions tests/integration/remote/invoke/test_remote_invoke.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"is_developer": true
}
26 changes: 25 additions & 1 deletion tests/integration/testdata/remote_invoke/lambda-fns/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,28 @@ def echo_event(event, context):
return event

def raise_exception(event, context):
raise Exception("Lambda is raising an exception")
raise Exception("Lambda is raising an exception")

def stock_transaction_recommender(event, context):
stock_price = int(event["stock_price"])
balance = event["balance"]
qty = event["qty"]
if qty*stock_price < 100:
stock_action = "Buy"
else:
stock_action = "Sell"
return {"stock_price": stock_price, "action": stock_action, "balance": balance, "qty": qty}

def stock_buyer(event, context):
current_balance = event["balance"]
new_balance = current_balance - (event["qty"]*event["stock_price"])
return {
"balance": new_balance
}

def stock_seller(event, context):
current_balance = event["balance"]
new_balance = current_balance + (event["qty"]*event["stock_price"])
return {
"balance": new_balance
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def handler(event, context):
return {
"message": "Hello world",
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"Comment": "A Hello World example of the Amazon States Language using Pass states",
"StartAt": "Hello",
"States": {
"Hello": {
"Type": "Pass",
"Result": "Hello",
"Next": "World"
},
"World": {
"Type": "Pass",
"Result": "World",
"End": true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@ Resources:
Handler: app.handler
Runtime: python3.9
CodeUri: function/
Timeout: 30
Timeout: 30

HelloWorldStateMachine:
Type: AWS::Serverless::StateMachine
Properties:
DefinitionUri: ./state-machines/hello-world-state-machine-definition.asl.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"Comment": "A Simple example of the Amazon States Language using Pass and Fail states",
"StartAt": "Hello",
"States": {
"Hello": {
"Type": "Pass",
"Result": "Hello",
"Next": "World"
},
"World": {
"Type": "Fail",
"Cause": "Mock Invalid response.",
"Error": "MockError"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"Comment": "A Hello World example of the Amazon States Language using Pass states",
"StartAt": "Type of World",
"States": {
"Type of World": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.is_developer",
"IsPresent": false,
"Next": "World"
},
{
"Variable": "$.is_developer",
"BooleanEquals": true,
"Next": "Developer World"
}
],
"Default": "World"
},
"World": {
"Type": "Pass",
"Result": "Hello World",
"End": true
},
"Developer World": {
"Type": "Pass",
"Result": "Hello Developer World",
"End": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"Comment": "A state machine that does mock stock trading.",
"StartAt": "Recommend Stock Transaction",
"States": {
"Recommend Stock Transaction": {
"Type": "Task",
"Resource": "${StockActionRecommenderFunction}",
"Retry": [
{
"ErrorEquals": [
"States.TaskFailed"
],
"IntervalSeconds": 14,
"MaxAttempts": 1,
"BackoffRate": 1.5
}
],
"Next": "Buy or Sell?"
},
"Buy or Sell?": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.action",
"StringEquals": "Buy",
"Next": "Buy Stock"
}
],
"Default": "Sell Stock"
},
"Sell Stock": {
"Type": "Task",
"Resource": "${StockSellerFunctionArn}",
"Retry": [
{
"ErrorEquals": [
"States.TaskFailed"
],
"IntervalSeconds": 2,
"MaxAttempts": 3,
"BackoffRate": 1
}
],
"End": true
},
"Buy Stock": {
"Type": "Task",
"Resource": "${StockBuyerFunctionArn}",
"Retry": [
{
"ErrorEquals": [
"States.TaskFailed"
],
"IntervalSeconds": 2,
"MaxAttempts": 3,
"BackoffRate": 1
}
],
"End": true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,46 @@ Resources:
Handler: main.raise_exception
Runtime: python3.9
CodeUri: ./lambda-fns
Timeout: 5
Timeout: 5

StateMachineExecutionFails:
Type: AWS::Serverless::StateMachine
Properties:
DefinitionUri: ./state-machines/execution-fails-state-machine-definition.asl.json

StockPriceGuideStateMachine:
Type: AWS::Serverless::StateMachine
Properties:
DefinitionUri: ./state-machines/stock-trader-state-machine-definition.asl.json
DefinitionSubstitutions:
StockActionRecommenderFunction: !GetAtt StockActionRecommenderFunction.Arn
StockSellerFunctionArn: !GetAtt StockSellerFunction.Arn
StockBuyerFunctionArn: !GetAtt StockBuyerFunction.Arn
Policies: # Find out more about SAM policy templates: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-policy-templates.html
- LambdaInvokePolicy:
FunctionName: !Ref StockActionRecommenderFunction
- LambdaInvokePolicy:
FunctionName: !Ref StockSellerFunction
- LambdaInvokePolicy:
FunctionName: !Ref StockBuyerFunction

StockActionRecommenderFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html
Properties:
CodeUri: lambda-fns/
Handler: main.stock_transaction_recommender
Runtime: python3.9

StockSellerFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: lambda-fns/
Handler: main.stock_seller
Runtime: python3.9

StockBuyerFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: lambda-fns/
Handler: main.stock_buyer
Runtime: python3.9
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: A hello world application with a step function.

Resources:
HelloWorldStateMachine:
Type: AWS::Serverless::StateMachine
Properties:
DefinitionUri: ./state-machines/hello-world-state-machine-definition.asl.json
Tracing:
Enabled: true