As part of my work in creating the content of Practical AWS training, this article is a prototype. The complete lesson will be included in the training with better examples and explanations.

When using AWS cloud, there are some considerations a user should take like IAM management. Chalice provides automatic IAM policy generation, which makes faster deploying an application.

Why Chalice ?

First of all, because it is created by AWS.

It allows also the development and deployment of Python serverless applications. Other frameworks will only help you develop serverless Javascript applications.

Finally, because I found it stable, easy and intuitive.

Requirements

To follow this tutorial, make sure you are using python2.7 or python3.6.

For Ubuntu 14 and 16, use:

sudo add-apt-repository ppa:jonathonf/python-3.6

sudo apt-get update

sudo apt-get install python3.6

Other OSs installation instructions, could be found here.

Before starting, you should have an AWS account and you should have configured your credentials in:

~/.aws/credentials

If you haven’t executed AWS configuration command, you’ll not find anything in your .aws folder. Use:

aws configure

Now create a virtual environment if you don’t like to touch your system libraries. Then activate it.

virtualenv -p python3.6 chalice_example

cd chalice_example

. bin/activate

Now install Chalice.

pip install chalice

Don’t forget to get 8 Great Tips to Learn AWS.

Creating a Chalice Project

Now create a Chalice project:

chalice new-project chalice_project

cd chalice_project

You’ll find 2 files inside the project file:

.

├── app.py

└── requirements.txt

This is the default app.py program:

from chalice import Chalice app = Chalice(app_name='chalice_project')

def index():

return {'hello': 'world'} @app .route('/')def index():return {'hello': 'world'}

# whenever you make an HTTP GET request to '/'.

#

# Here are a few more examples:

#

#

# def hello_name(name):

# # '/hello/james' -> {"hello": "james"}

# return {'hello': name}

#

#

# def create_user():

# # This is the JSON body the user sent in their POST request.

# user_as_json = app.current_request.json_body

# # We'll echo the json body back to the user in a 'user' key.

# return {'user': user_as_json}

#

# See the README documentation for more examples.

# # The view function above will return {"hello": "world"}# whenever you make an HTTP GET request to '/'.# Here are a few more examples: @app .route('/hello/{name}')# def hello_name(name):# # '/hello/james' -> {"hello": "james"}# return {'hello': name} @app .route('/users', methods=['POST'])# def create_user():# # This is the JSON body the user sent in their POST request.# user_as_json = app.current_request.json_body# # We'll echo the json body back to the user in a 'user' key.# return {'user': user_as_json}# See the README documentation for more examples.

Creating our Function

In our example, we will create a function that will give you the md5sum of any string.

e.g:

import hashlib

m = hashlib.md5()

m.update("testing")

print m.hexdigest()

We need to install hashlib using PIP.

pip install hashlib

Open app.py, add the libraries we want to import:

from chalice import Chalice

import hashlib

Create an application

app = Chalice(app_name='chalice_project')

Add the default / route function:

Now create the main function we are going to use:



def hash_it(string_to_hash):

m = hashlib.md5()

m.update(string_to_hash.encode("utf-8"))

return {'response': m.hexdigest()} @app .route('/md5/{string_to_hash}')def hash_it(string_to_hash):m = hashlib.md5()m.update(string_to_hash.encode("utf-8"))return {'response': m.hexdigest()}

Notice that the route we are going to use is /md5/{string_to_hash}

We are using “{}” because string_to_hash is a variable.

Deploying

Now when you execute the deployment command

chalice deploy

, these instructions will be executed:



Creating deployment package.

Creating lambda function: chalice_project-dev

Initiating first time deployment.

Deploying to API Gateway stage: api

https://a23wxp5cve.execute-api.eu-west-1.amazonaws.com/api/ Creating role: chalice_project-devCreating deployment package.Creating lambda function: chalice_project-devInitiating first time deployment.Deploying to API Gateway stage: api

When you visit the provided URL, you’ll get the configured message for the / route:

Let’s test this URL to create the md5sum of the string “PracticalAWS”:

You should see something similar to the previous screenshot.

If you made an error in your code and don’t want to deploy each time you’d like to test, activate the debug of Chalice. This is how our code looks like:

from chalice import Chalice

import hashlib app = Chalice(app_name='chalice_project')

app.debug = True

def index():

return {'response': 'ok'} @app .route('/')def index():return {'response': 'ok'}

def hash_it(string_to_hash):

m = hashlib.md5()

m.update(string_to_hash.encode("UTF-8"))

return {'response': str(m.hexdigest())} @app .route('/md5/{string_to_hash}')def hash_it(string_to_hash):m = hashlib.md5()m.update(string_to_hash.encode("UTF-8"))return {'response': str(m.hexdigest())}

Have you noticed that the last deployment was for the development environment? If yes, nice! Keep focusing like this :-)

chalice deploy --stage prod

Creating deployment package.

Creating lambda function: chalice_project-prod

Initiating first time deployment.

Deploying to API Gateway stage: api

https://27rezyfu06.execute-api.eu-west-1.amazonaws.com/api/ Creating role: chalice_project-prodCreating deployment package.Creating lambda function: chalice_project-prodInitiating first time deployment.Deploying to API Gateway stage: api

Now we have two APIs, one for dev and the other for prod. Execute these commands to show both URLs:

chalice url --stage dev chalice url --stage prod

Now, we have a new API Gateway rest API, Lambda function, and IAM.

Configurations

You can view our environments configurations by typing:

cat .chalice/deployed.json

e.g:

{

"dev": {

"api_handler_name": "chalice_project-dev",

"api_handler_arn": "arn:aws:lambda:eu-west-1:998335703874:function:chalice_project-dev",

"lambda_functions": {},

"backend": "api",

"chalice_version": "1.0.2",

"rest_api_id": "rcnce4er7c",

"api_gateway_stage": "api",

"region": "eu-west-1"

},

"prod": {

"api_handler_name": "chalice_project-prod",

"api_handler_arn": "arn:aws:lambda:eu-west-1:998335703874:function:chalice_project-prod",

"lambda_functions": {},

"backend": "api",

"chalice_version": "1.0.2",

"rest_api_id": "4wf2ohyot4",

"api_gateway_stage": "api",

"region": "eu-west-1"

}

}

Using Your Own Domain

In order to use your own domain name, you need to go to the API Gateway dashboard and click on the newly created API.

If you followed the same instructions and kept the same names, your API will be called “chalice_project”.

Click on “Custom Domain Name” and add a new domain. In my case, I made the choice of using md5sum.practicalaws.com.

Generate a certificate for md5sum.practicalaws.com using Amazon Certificate Manager.

If you choose “Edge Optimised”, which means that AWS is going to create a CloudFront distribution for us, remember to only use the region us-east-1 for the certificate generation using ACM (Amazon Certificate Manager).

Clicking on save will give you the CloudFront distribution subdomain.

The latter should be used in Route53, in order to make md5sum.practicalaws.com point to its alias (the alias of the CloudFront distribution).

If you are using another domain or subdomain, make sure to use it instead of md5sum.practicalaws.com.

Now our md5sum function could be called using:

Deleting Resources

You can delete an environment resources, for instance, for development, type :

chalice delete --stage dev

Don’t also forget to remove the production resources if you need that: