Section 3: Add a DynamoDB table for Todo application

In this step, we’ll replace the in-memory database with an Amazon DynamoDB table.

Initial Setup

The starting code for this step is in the chalice-workshop/code/todo-app/part1/03-add-dynamodb file. If necessary, you can copy over those files as a starting point for this step:

$ cp ../chalice-workshop/code/todo-app/part1/03-add-dynamodb/app.py app.py
$ cp ../chalice-workshop/code/todo-app/part1/03-add-dynamodb/createtable.py createtable.py
$ cp ../chalice-workshop/code/todo-app/part1/03-add-dynamodb/chalicelib/db.py chalicelib/db.py
$ cp ../chalice-workshop/code/todo-app/part1/03-add-dynamodb/.chalice/policy-dev.json .chalice/policy-dev.json
$ cp ../chalice-workshop/code/todo-app/part1/03-add-dynamodb/.chalice/config.json .chalice/config.json

Create a DynamoDB table

In this section, we’re going to create a DynamoDB table and configure chalice to pass in the table name to our application.

  1. First, we’ll need to install boto3, the AWS SDK for Python. Run this command:

    $ pip install boto3
    
  2. Add boto3 to our requirements.txt file. Chalice uses this file when building the deployment package for your app:

    $ pip freeze | grep boto3 >> requirements.txt
    
  3. Now that boto3 is installed, we can create the DynamoDB table Run the createtable.py script with the --table-type app option. This will take a few seconds to run.

    $ python createtable.py --table-type app
    
  1. Verify that this script added the table name to the .chalice/config.json file. You should see a key named APP_TABLE_NAME in this file:

    $ cat .chalice/config.json
    {
      "stages": {
        "dev": {
          "environment_variables": {
            "APP_TABLE_NAME": "todo-app-...."
          },
          "api_gateway_stage": "api"
        }
      },
      "version": "2.0",
      "app_name": "testapp"
    }
    
  2. Next, we’ll add a test route to double check we’ve configured everything correctly. Open the app.py file and these import lines to the top of the file:

    import os
    import boto3
    
  3. Add a new test route:

@app.route('/test-ddb')
def test_ddb():
    resource = boto3.resource('dynamodb')
    table = resource.Table(os.environ['APP_TABLE_NAME'])
    return table.name

Verification

  1. Start up the local dev server: chalice local

  2. Make a request to this test route and verify you get a 200 response:

    $ http localhost:8000/test-ddb
    HTTP/1.1 200 OK
    Content-Length: 45
    Content-Type: application/json
    Server: BaseHTTP/0.3 Python/2.7.14
    
    todo-app-0b116e7b-f0f8-4548-91d8-95c75898b8b6
    

Switching the InMemoryTodoDB to a DynamoDBTodo

Now that we’ve verified our DynamoDB table is plumbed into our chalice app correctly, we can update to use a new DynamoDBTodo backend instead of the InMemoryTodoDB.

The chalicelib/db.py file you copied from code/todo-app/part1/03-add-dynamodb/chalicelib/db.py has a new DynamoDBTodo class. This has the same interface as InMemoryTodoDB except that is uses DynamoDB as the backend. We’re going to update our app.py to use this new class.

  1. Remove the @app.route('/test-ddb') view function. We no longer need it now that we’ve verified that DynamoDB is correctly configured for our app.

  2. Go to the get_app_db() function in your app.py file. Modify this function to use the DynamoDBTodo backend:

    def get_app_db():
        global _DB
        if _DB is None:
            _DB = db.DynamoDBTodo(
                boto3.resource('dynamodb').Table(
                    os.environ['APP_TABLE_NAME'])
            )
        return _DB
    
  3. Go to the top of the app.py file. Modify the line from chalicelib.db import InMemoryTodoDB to reference db instead:

    from chalicelib import db
    

Verification

  1. Start up the local dev server chalice local

  2. Create a Todo item:

    $ echo '{"description": "My first Todo", "metadata": {}}' | \
        http POST localhost:8000/todos
    HTTP/1.1 200 OK
    Content-Length: 36
    Content-Type: application/json
    Date: Thu, 19 Oct 2017 23:44:24 GMT
    Server: BaseHTTP/0.3 Python/2.7.10
    
    de9a4981-f7fd-4639-97fb-2af247f20d79
    
  3. Retrieve the Todo item you just created. Keep in mind that your UID will be different from what’s shown below:

    $ http localhost:8000/todos/de9a4981-f7fd-4639-97fb-2af247f20d79
    HTTP/1.1 200 OK
    Content-Length: 140
    Content-Type: application/json
    Date: Fri, 20 Oct 2017 00:03:26 GMT
    Server: BaseHTTP/0.3 Python/2.7.10
    
    {
        "description": "My first Todo",
        "metadata": {},
        "state": "unstarted",
        "uid": "de9a4981-f7fd-4639-97fb-2af247f20d79",
        "username": "default"
    }
    

Deploy your app

  1. Now that we’ve tested locally, we’re ready to deploy:

    $ chalice deploy
    

Verification

  1. First create a Todo item using the API Gateway endpoint:

    $ chalice url
    https://your-chalice-url/
    $ echo '{"description": "My second Todo", "metadata": {}}' | \
        http POST https://your-chalice-url/todos
    HTTP/1.1 200 OK
    Content-Length: 36
    Content-Type: application/json
    
    abcdefg-abcdefg
    
  2. Verify you can retrieve this item:

    $ http https://your-chalice-url/todos/abcdefg-abcdefg
    HTTP/1.1 200 OK
    Content-Length: 140
    Content-Type: application/json
    
    {
        "description": "My second Todo",
        "metadata": {},
        "state": "unstarted",
        "uid": "abcdefg-abcdefg",
        "username": "default"
    }