5

How does one integrate DynamoDB Local into the development process when using aws-cdk? For example, the following app (using the "sample app" template) works, but how would one run sam local invoke <id of the backendHandler lambda> and point to a DynamoDB Local instance running on your machine (instead of having to run cdk deploy) to see in action?

// lib/minimal-app-stack.ts

import * as apiGateway from "@aws-cdk/aws-apigateway";
import * as cdk from "@aws-cdk/core";
import {MinimalBackend} from "./minimal-backend";

export class MinimalAppStack extends cdk.Stack {
    constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        const minimalBackend = new MinimalBackend(this, "MinimalBackend");

        new apiGateway.LambdaRestApi(this, "Endpoint", {
            handler: minimalBackend.handler
        });
    }
}

// lib/minimal-backend.ts

import * as cdk from "@aws-cdk/core";
import * as dynamodb from "@aws-cdk/aws-dynamodb";
import * as lambda from "@aws-cdk/aws-lambda";

export class MinimalBackend extends cdk.Construct {
    public readonly handler: lambda.Function;

    constructor(scope: cdk.Construct, id: string) {
        super(scope, id);

        const minimalTable = new dynamodb.Table(this, "MinimalTable", {
            partitionKey: {
                name: "id",
                type: dynamodb.AttributeType.STRING
            }
        });

        this.handler = new lambda.Function(this, "BackendHandler", {
            code: lambda.Code.fromAsset("lambda"),
            handler: "backendHandler.handler",
            runtime: lambda.Runtime.NODEJS_12_X,
            environment: {
                TABLE_NAME: minimalTable.tableName
            }
        });

        minimalTable.grantReadWriteData(this.handler);
    }
}

// lambda/backendHandler.ts

// @ts-ignore
/// <reference types="aws-sdk" />

import AWS = require("aws-sdk");

const tableName = process.env.TABLE_NAME || "";
const dynamo = new AWS.DynamoDB.DocumentClient();

async function getAllItems() {
    const scanResult = await dynamo
        .scan({
            TableName: tableName
        })
        .promise();

    return scanResult;
}

exports.handler = async function (event: AWSLambda.APIGatewayEvent) {
        const response = await getAllItems();
        const data = response.Items || [];
        const stringifiedData = JSON.stringify(data, undefined, 2);

        return {
            statusCode: 200,
            headers: {
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Methods": "OPTIONS,GET,POST,DELETE"
            },
            body: stringifiedData
        }
};

If I was inside a plain node app, I could access my DynamoDB Local instance with:

const docClient = new AWS.DynamoDB.DocumentClient( {
    region: "us-west-2",
    endpoint: "http://localhost:8000",
    convertEmptyValues: true
});

Not sure how to integrate that into aws-cdk though. Any ideas?

TDB
  • 367
  • 1
  • 3
  • 15
  • Why can you not use your 2nd snippet in your lambda? It's what I do to access a local DB - I just use a env var to determine if local and pass it endpoint of local dynamo if so. – cyberwombat Nov 16 '20 at 18:23

0 Answers0