AWS Developer 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           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 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')

                 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,
        with as img:
            img.thumbnail((256, 256))
            out_filename = + '.thumbnail.jpg'
    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

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 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.