I am working with AWS SAM (Serverless Application Model) to build Python 3.6 lambda code in an API Gateway setup.
As such, I have a single template.yaml
file that creates several Lambda functions. They are organized with the lambda functions each in their own sub-directory within the project. The lambda also share several common files which I keep in a shared folder.
project-home
-lambda_a_dir
-lambda_a.py
-lambda_b_dir
-lambda_b.py
-shared_dir
-shared.py
The problem is that while Pycharm can clearly see the shared.py
, SAM cannot and refuses to recognize the shared files, with the following error: Unable to import module 'lambdaA': No module named 'shared'
If I move a copy of the shared.py
file into each lambda directory, both Pycharm and SAM are happy and I can build/deploy to AWS.
My question: how can I build the SAM template with the shared files living in the shared directory?
So far, I have tried:
CodeUri
alternatives __init__
and setup.py
. (I can't use a public package because the code is private and cannot not be put on a public repository.)Here is my template file:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
lambdaA:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./lambda_a_dir/
Handler: lambda_a.lambda_handler
Runtime: python3.6
lambdaB:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./lambda_b_dir/
Handler: lambda_b.lambda_handler
Runtime: python3.6
There is no in-built technique for sharing data between Lambda functions. Each function runs independently and there is no shared datastore. You will need to use an external datastore -- that is, something outside of Lambda that can persist the data.
Before lambda layers, developers used to either duplicate common code in every lambda function or create local npm packages and refer them in lambdas. Now with lambda layers, you can securely share code among your lambda functions in the same AWS account, cross-accounts or in public.
AWS Lambda Permission Policies (aka resource-based policies) can allow functions to be invoked from AWS accounts other than the one it is running in.
You can now mount EFS volumes in Lambda functions, which makes it simpler to share data across invocations. The file system grows and shrinks as you add or delete data, so you do not need to manage storage limits. The Lambda service mounts EFS file systems when the execution environment is prepared.
In the Lambda function window, choose Actions, and then select Export Function. 4. In the Export function window, choose Download AWS SAM file. 5. After the AWS SAM file is downloaded, return to the Export function window and choose Download deployment package to download the deployment package.
Use the AWS SAM file and AWS CloudFormation to deploy and manage a new Lambda function in another AWS account or Region. For more information, see Deploying a Hello World application. Note: You can also migrate a Lambda function using the Lambda console or the AWS Command Line Interface (AWS CLI). 1.
Or you can use a Lambda function to process files uploaded by a web application running on EC2. In this way, some use cases are much easier to implement with Lambda functions. For example:
With Amazon EFS, your function code can access and modify shared resources safely and at high concurrency. Lambda uses your function's permissions to mount file systems.
Following the recommendation from @Dunedan I created a Layers object for each lambda function with the shared code, this effectively added those routines to the PythonPath for those functions. I also added the following to the API template definition with the new Layers
properties:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
lambdaA:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./lambda_a_dir/
Handler: lambda_a.lambda_handler
Runtime: python3.6
Layers:
- arn:aws:lambda:us-west-1:012345678:layer:my_shared_zip:1
lambdaB:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./lambda_b_dir/
Handler: lambda_b.lambda_handler
Runtime: python3.6
Layers:
- arn:aws:lambda:us-west-1:012345678:layer:my_shared_zip:1
Note that the code needs to be zipped before it is uploaded and needs to have a directory structure of the following, with the code inside a directory with the name of the language. In this case since I was using Python, the code needed to be in the python
directory, and the python
directory was then zipped:
my_shared_zip.zip
-python
-shared.py
-other_shared.py
-more_shared.py
Last note. While ideally, this shared-python directory should be deployed directly by the sam deploy
command into the Layer objects, I have found that support for Layers
in the AWS SAM CLI is still so new and so buggy, that at this point its not functional. Hopefully in the coming months it will be fixed. In the meantime, I need to manually install new versions of the shared-zip file myself. Sigh.
The layers solution looks like a hack. I tried creating symlink to "shared" folder and it worked - the shared folder was successfully packed along with my lambda function.
cd lambda_a_dir
ln -s ../shared
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