AWS Infrastructure as Code with CDK

Wishing you could move away from JSON or YAML and instead implement your infrastructure with an imperative programming language?Released for developer preview since July 2018, the AWS Cloud Development Kit (CDK) is an open-source project that aims to address these concerns.

Currently supporting Java, JavaScript, TypeScript, and .

NET, the CDK makes it easier than ever before to define your AWS stacks.

With a simple, serverless application in mind to save requests to a NoSQL table, let’s build the stack for this app using the latest release of the CDK (version 0.

25.

0 at the time of writing).

Whilst we wait for Python support to roll out, I’ll run through this example with TypeScript.

DesignWe require three AWS services for this app: API Gateway to send requests, DynamoDB to store these requests in a NoSQL table, and Lambda to execute the code that validates and saves these requests to DynamoDB.

API Gateway will consist of a single endpoint, /send.

This endpoint will support POST requests.

Every time a POST request is made to this endpoint, we will trigger the Lambda function.

When the Lambda is triggered, we want requests to be inserted into a DynamoDB table called “request”.

The partition key to uniquely identify requests in this table will be called id , and the operations we execute using this key will be billed on-demand.

This means that we pay for the number of read and write operations we execute per second, without any upper bound constraints.

The Lambda will use existing Python 3.

7 code, which validates requests — making sure an id property is provided — before writing to the request table.

There’s three responses this Lambda can provide:a 400 BAD REQUEST if the request is missing the id property,a 500 INTERNAL SERVER ERROR if an error occurs writing to DynamoDB, ora 200 OK if everything goes swimmingly.

ConfigurationWith a design in place, we need to configure and install the CDK.

The CDK Install and Configure page explains this in great detail, saving me the trouble!.Working from a new directory called save-request, runcdk init –language=typescriptto initialise the CDK.

Within bin/save-request.

ts, we have the CDK app.

Whenever we deploy our stack, the CDK will run this app to execute deployment.

We have no need to make any modifications to this file.

The stack itself will live in lib/save-request-stack.

ts, which so far consists of an empty SaveRequestStack.

Each AWS service has its own CDK package.

Following our design, we require packages for API Gateway, Lambda, and DynamoDB.

We’ll also require the AWS IAM package, which will allow us to grant the Lambda permission to write to DynamoDB.

We’ll see this later in the CDK code.

Adding these libraries to the initial dependencies, we have the below package.

json.

To install these packages, run npm i.

ImplementationNow we’re ready to implement the stack.

Returning to lib/save-request-stack.

ts, we’ll include all our stack code within the SaveRequestStack class.

Let’s begin with the DynamoDB request table.

Importing the DynamoDB package from package.

json, we begin by instantiating a dynamodb.

Table.

Similar to the other CDK constructors, dynamodb.

Table takes three parameters:a scope (often a reference to the stack itself with this keyword),a unique name, anda JSON blob of CDK properties, which varies between constructors.

For the request table, let’s provide unique name “request-table”.

Keep in mind that this is the name of the CDK construct, not the name of the table itself!.We provide the latter within our JSON blob of CDK properties, along with the partition key and billing mode from our design.

The Lambda constructor takes a similar form with unique name “request-handler”.

Within the properties, we include a pointer to the Lambda code, which I’ve saved in .

/request-handler/app.

py.

The code property specifies which file or files contain the code, whilst the handler property indicates which method serves as the main method amongst those files.

Within the code, we reference a DYNAMODB_TABLE environment variable for the DynamoDB table name.

Using the environment property, we can populate this variable.

Better still, with CDK, we can dynamically reference the tableName property from the table we just defined.

After referencing the REQUEST_TABLE environment variable, the code executes the DynamoDB PutItem operation to write to the table.

Without an IAM policy explicitly granting Lambda permission to do this, the Lambda will fail each time the PutItem method is called.

With a few lines of CDK, we grant the required permission, referencing the table’s unique Amazon Resource Name (ARN) with the tableArn property.

With both DynamoDB and Lambda set up, now we need to create an API Gateway to send requests to the Lambda.

Starting with a new REST API LambdaRestApi, we add a “send” resource that serves as our endpoint.

This endpoint will always receive one of three responses from the Lambda code: a Bad Request, an Internal Server Error, or an OK.

We define each of these using the IntegrationResponse type.

We proceed to integrate this endpoint to Lambda using a LambdaIntegration, which includes all three possible responses within its properties.

Finally, we add the POST method support to this integration.

That forms our full stack!.A total of 60 lines of TypeScript, which is available to view in GitLab.

This translates into 254 lines of YAML once it’s converted into a CloudFormation template — over four times the size of our CDK!UsageIt’s time to build and deploy this app to AWS.

First run npm run build, followed by cdk deploy.

The CDK will alert you to any security-related changes in your deployment — make sure you’re happy with these changes before proceeding!When deployment is complete, sign into the AWS Console and find the API Gateway service, where you will see our newly created request-api.

Click on this API, and navigate to the “POST” method in the /send endpoint.

To test this endpoint, click Test on the left-hand side, then scroll down to the Request Body box and insert {"id": "test-uuid"} .

Clicking “Test”, the Lambda should return an OK response, indicating that our Lambda successfully processed the request.

Turning to the DynamoDB console, we should find that test-uuid is inserted into the request table.

Built entirely using the CDK, we have ourselves a serverless application to save requests!.Great stuff.

Now with testing complete, feel free to tear down the CDK stack by running cdk destroy request-stack.

ConclusionBy reducing the amount of infrastructure code from 254 lines to 60, the CDK has left a fantastic impression on me.

The code is easy to read, and new releases on a regular basis deliver wider support for AWS functionality across the majority of its services.

Whilst the code reads well, working out how to write it in the first place occasionally proved a challenge — the documentation wasn’t always straightforward to follow.

Given the young age of this tool, there’s few examples online to assist us.

Be prepared to spend more time on features which you would expect to implement with ease.

As the CDK approaches the end of its developer preview, hopefully we’ll see improvements to the documentation.

Whilst it’s been great to brush up on my TypeScript knowledge, it’ll be better still to see Python support roll out for the CDK, and perhaps support for other languages like Ruby and Go further down the line.

The CDK is an exciting project, and it would be great to hear your thoughts on this.

It’s open-source, so if you fancy contributing then feel free to browse the CDK GitHub project.

If you would like to play around with my example, you’re welcome to fork it on GitLab.

That’s all from me, enjoy!.

. More details

Leave a Reply