AWS Developer Tools Blog
AWS Chalice 1.5.0 adds support for more AWS Lambda event sources
Version 1.5.0 of AWS Chalice, a microframework for writing serverless applications in python, adds support for three new event sources in AWS Lambda. You can now configure a Lambda function to be invoked automatically in response to an Amazon SNS message being published to a topic, an Amazon SQS message being sent to a queue, or when an event occurs in an Amazon S3 bucket. Chalice automatically handles configuring the event sources and adding the appropriate permissions to allow the various AWS services to invoke your Lambda function.
Let’s look at an example using Amazon S3 events. We’ll see how we can create a thumbnail generator by using Chalice and the new S3 event source support in version 1.5.0.
In our serverless application, we’ll create a Lambda function that is automatically invoked whenever an object is uploaded to an S3 object. Our Lambda function will download the object from Amazon S3, generate a thumbnail, and upload the file back to Amazon S3.
Initial setup
First, let’s create a virtual environment for our application.
$ virtualenv --python python3.6 venv $ source venv/bin/acticate
Next, we install Chalice and check to be sure we have the latest version installed.
$ pip install chalice ... $ chalice --version chalice 1.5.0, python 3.6.5, darwin 16.7.0
We use the chalice new-project
command to create our application.
$ chalice new-project s3-thumbnail-generator $ cd s3-thumbnail-generator $ ls app.py requirements.txt
Our application will also need an S3 bucket. We’ll use one S3 bucket as both the input and output source. Be sure to choose a unique name for your bucket. In the example below we’ll use the AWS CLI to create our bucket.
$ pip install awscli $ aws s3 mb s3://chalice-s3-thumbnail-demo/ make_bucket: chalice-s3-thumbnail-demo
Now we’re ready to write our application code.
Application code
We update the app.py
file with our new code.
import tempfile
import boto3
from PIL import Image
from chalice import Chalice
app = Chalice(app_name='s3-thumbnail-generator')
app.debug = True
s3 = boto3.client('s3')
@app.on_s3_event(bucket='chalice-s3-thumbnail-demo',
prefix='images/', suffix='.jpg')
def handler(event):
app.log.debug("Resize image for: s3://%s/%s",
event.bucket, event.key)
with tempfile.NamedTemporaryFile('w') as f:
s3.download_file(event.bucket, event.key, f.name)
with Image.open(f.name) as img:
img.thumbnail((256, 256))
out_filename = f.name + '.thumbnail.jpg'
img.save(out_filename)
s3.upload_file(out_filename, event.bucket,
f'thumbnails/{event.key.split('/', 1)[1]}')
On line 7, we set app.debug = True
. This enables the app.debug.log(...)
statements on lines 13-14 to show up in Amazon CloudWatch logs, which we’ll look at when we test our app.
Lines 10-11 are using the new @app.on_s3_event()
decorator that was added in the 1.5.0 Chalice release. This configures our Lambda function to be invoked automatically whenever an object is uploaded to the chalice-s3-thumbnail-demo
bucket, with a prefix of images/
and a file name extension of .jpg
, or in other words s3://chalice-s3-thumbnail-demo/images/**/*.jpg
.
The remaining lines 15-22 download the image from S3, generate a thumbnail no larger than 256 x 256 pixels, and upload the thumbnail to s3://chalice-s3-thumbnail-demo/thumbnails/{filename}.jpg
.
In our application code, we use 2 libraries in our Lambda function:
- PIL – Image manipulation library. This is used to generate our thumbnails.
- Boto3 – The AWS SDK for Python, used to upload and download from S3.
We need to ensure our requirements.txt
file is updated with these packages.
$ cat requirements.txt boto3==1.7.54 Pillow==5.2.0
We next install our dependencies in our requirements.txt
file.
$ pip install -r requirements.txt
Now we’re ready to deploy our code.
Deploying our Chalice app
To deploy our application, we’ll use the chalice deploy
command. You’ll see output similar to the following:
$ chalice deploy Creating deployment package. Creating IAM role: s3-thumbnail-generator-dev Creating lambda function: s3-thumbnail-generator-dev-handler Configuring S3 events in bucket chalice-s3-thumbnail-demo to function s3-thumbnail-generator-dev-handler Resources deployed: - Lambda ARN: arn:aws:lambda:us-west-2:12345:function:s3-thumbnail-generator-dev-handler
Chalice has created all the resources needed for our serverless application. Now we’re ready to test.
Testing our application
To test our application, you can pick any .jpg images and upload them to the S3 bucket you initially created. I’ll use the AWS CLI to upload an object to S3.
$ file /tmp/test-image.jpg /tmp/test-image.jpg: JPEG image data, baseline, precision 8, 2048x1365, frames 3 $ aws s3 cp /tmp/test-image.jpg s3://chalice-s3-thumbnail-demo/images/ upload: /tmp/test-image.jpg to s3://chalice-s3-thumbnail-demo/images/test-image.jpg
Note that the image size is 2048×1365 pixels. We can now list the contents of our S3 bucket, and we’ll see that our application has generated a thumbnail.
$ aws s3 ls s3://chalice-s3-thumbnail-demo/ --recursive 2018-07-10 17:47:12 240712 images/test-image.jpg 2018-07-10 17:47:15 5956 thumbnails/test-image.jpg
If we download the image, we can see that our image is resized to 256×170 pixels.
$ aws s3 cp s3://chalice-s3-thumbnail-demo/thumbnails/test-image.jpg /tmp/test-thumbnail.jpg download: s3://chalice-s3-thumbnail-demo/thumbnails/test-image.jpg to /tmp/test-thumbnail.jpg $ file /tmp/test-thumbnail.jpg /tmp/test-thumbnail.jpg: JPEG image data, baseline, precision 8, 256x170, frames 3
Wrapping Up
We now have our Chalice app up and running. To experiment more, you can modify your app.py
file and rerun chalice deploy
to redeploy your changes. To delete all the resources for your app you can run the chalice delete
command.
In addition to Amazon S3 events, version 1.5.0 of Chalice also adds support for Amazon SNS events and Amazon SQS events. Both of these have an API that’s similar to the @app.on_s3_event
that we used for our thumbnail generator application.
Try out the latest version of Chalice today and let us know what you think! You can give us feedback on our GitHub repo.