I am using AWS SAM with Python. My goal is to have two Lambdas:
There are a couple other SO questions which deal with this scenario, but as far as I can tell none have touched on how to do it when deploying SAM locally.
Here is my SAM template file:
# template.yaml
Resources:
FunctionA:
# PUT /functions/a, should invoke FunctionB asynchronously
Type: AWS::Serverless::Function
Properties:
CodeUri: api/
Handler: functions.a
Runtime: python3.7
Events:
FunctionA:
Type: Api
Properties:
Path: /functions/a
Method: put
FunctionB:
# Long-running asynchronous function
Type: AWS::Serverless::Function
Properties:
FunctionName: 'FunctionB'
CodeUri: api/
Handler: functions.b
Runtime: python3.7
EventInvokeConfig:
MaximumRetryAttempts: 2
DestinationConfig:
OnSuccess:
Type: SQS
OnFailure:
Type: SQS
And my Python lambda handler logic:
# functions.py
def a(event, context):
boto3.client('lambda').invoke(
FunctionName='FunctionB',
InvocationType='Event',
Payload='some_data'.encode('UTF-8')
)
return { "statusCode": 200, "body": {} }
def b(data):
print("SUCCESS!")
I deploy it locally:
# deploy.sh
sam build
sam local start-api
All is well until this point. When I call PUT /functions/a
, I get the following error indicating that Function B could not be invoked from Function A:
[ERROR] ResourceNotFoundException: An error occurred (ResourceNotFoundException) when calling the Invoke operation: Function not found: arn:aws:lambda:us-east-2:[iam-user-id]:function:FunctionB
Has anyone found a fix for this? Here's what I've tried:
sam local invoke FunctionB # works great
InvocationType=Event
to InvocationType=RequestResponse
and received the same errorboto3.client('lambda', endpoint_url='http://localhost:3000')
# [ERROR] EndpointConnectionError: Could not connect to the endpoint URL: "http://localhost:3000/2015-03-31/functions/ScheduleShowsAsyncFunction/invocations"
Setting up the Policy for ParentFunction. In order to allow the ParentFunction to call the ChildFunction, we need to provide the ParentFunction with specific rights to call another lambda function. This can be done by adding specific policies to a role and then assign that role to the lambda function.
You can invoke your function locally by using the sam local invoke command and providing its function logical ID and an event file. Alternatively, sam local invoke also accepts stdin as an event. For more information about events, see Event in the AWS Lambda Developer Guide.
The sam local invoke command is useful for developing serverless functions that handle asynchronous events, such as Amazon Simple Storage Service (Amazon S3) or Amazon Kinesis events. It can also be useful if you want to compose a script of test cases. You can pass in the event body using the --event parameter.
You can use sam local start-lambda to run FunctionA, it will emulates on port 3001, and call it from FunctionB with lambda client:
boto3.client('lambda', endpoint_url='http://docker.for.mac.localhost:3001')
You have to use InvocationType=RequestResponse
because Event is not yet supported https://github.com/awslabs/aws-sam-cli/pull/749
If FunctionB is long-running and because you can only use RequestResponse you can change lambda client config to increase timeout:
config_lambda = Config(retries={'total_max_attempts': 1}, read_timeout=1200)
lambda_client = boto3.client('lambda',
config=config_lambda,
endpoint_url='http://docker.for.mac.localhost:3001')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With