I received positive feedback on my AWS Lambda presentation in London. This post discusses how to package and deploy your lambda function.
I’m sure there are other ways but I wanted something simple. This allows me to maintain separate enviroments (i.e “dev”, “production”).
Makefile
I use Make to create a package (i.e “sample-app.zip”). The dependencies are installed into a virtualenv which are appended to the package.
Create the function
make build-dev
make create-dev
Deploy the package
make build-dev
make update-dev
PROJECT = sample-python-app | |
FUNCTION = $(PROJECT) | |
REGION = us-east-1 | |
.phony: clean | |
clean: | |
rm -f -r $(FUNCTION)* | |
rm -f -r site-packages | |
build-dev: clean | |
aws s3 cp s3://$(FUNCTION)/settings-dev.yml settings.yml | |
zip -r $(FUNCTION)-dev.zip . -x “*.git*“ “tests/*“ | |
mkdir -p site-packages | |
virtualenv $(FUNCTION)-dev | |
. $(FUNCTION)-dev/bin/activate | |
pip install -r requirements.txt | |
cd site-packages; cp -r $$VIRTUAL_ENV/lib/python2.7/site-packages/ ./ | |
cd site-packages; zip -g -r ../$(FUNCTION)-dev.zip . | |
create-dev: | |
aws lambda create-function \ | |
–handler main.lambda_handler \ | |
–function-name $(FUNCTION)-dev \ | |
–region $(REGION) \ | |
–zip-file fileb://$(FUNCTION)-dev.zip \ | |
–role arn:aws:iam::XXXX:role/$(FUNCTION)-dev \ | |
–runtime python2.7 \ | |
–timeout 120 \ | |
–memory-size 512 \ | |
update-dev: | |
aws lambda update-function-code \ | |
–function-name $(FUNCTION)-dev \ | |
–zip-file fileb://$(FUNCTION)-dev.zip \ | |
–publish \ | |
delete-dev: | |
aws lambda delete-function –function-name $(FUNCTION)-dev |
Lambda deployment package
Make sure you include all the dependencies in the package. You need to copy the contents of site-packages, NOT the directory itself. If you copy site-packages itself, lambda will not be able to find the modules.
The contents will look something similar to:
main.py | |
netstorage/ | |
netstorage/__init__.py | |
… | |
requests/ | |
requests/__init__.py | |
… |
Testing locally
Instead of constantly deploying the function, I wanted to test my changes locally.
When creating an AWS lambda function, you need to specify the handler gets executes. In the gist above, I specify it with –handler main.lambda_handler. So testing locally is simple as:
if __name__ == "__main__":
lambda_handler(None, None)