The AWS CDK and Typescript – Part 1

This first little tutorial is all about the AWS CDK and how we can write a simple app using Typescript. What is the AWS CDK might you ask? You might also ask what AWS is? Or what is Typescript!?!?

If so I apologise in advance as you are sh*t out of luck. I’m far too lazy to explain AWS and to be honest if you don’t know what it is then this blog probably doesn’t make any sense whatsoever. Same with Typescript. Also theres a distinct danger I’ll explain them both poorly and make you look as stupid as I am.

Anywho, working on the basis that you have some understanding of what AWS is we can jump into talking about the AWS CDK. Understanding Typescript isn’t such a big deal as we can write CDK apps in a variety of languages, it simply serves a purpose and anything we do here can be translated into your language of choice with a bit of elbow grease.

Before we get stuck in, we first need to have a quick chat about CloudFormation and what it involves.

The below is shamelessly stolen from AWS Documentation.

AWS CLOUDFORMATION

AWS CloudFormation enables you to:

  • Create and provision AWS infrastructure deployments predictably and repeatedly.
  • Leverage AWS products such as Amazon EC2, Amazon Elastic Block Store, Amazon SNS, Elastic Load Balancing, and Auto Scaling.
  • Build highly reliable, highly scalable, cost-effective applications in the cloud without worrying about creating and configuring the underlying AWS infrastructure.
  • Use a template file to create and delete a collection of resources together as a single unit (a stack).

An example CloudFormation file might look something like the below . *Note – The below is written in YAML but we can also write these templates in JSON depending on your preference.

Description: Create a VPC with 2 private and 1 public subnets, with an EC2 instance in each.
Mappings:
  RegionMap:
    us-east-1:
      # amzn-ami-hvm-2016.09.1.20161221-x86_64-gp2
      "opal": "ami-9be6f38c"
      "rstudio": "ami-9be6f38c"
Parameters:
  InstanceType:
    Description: EC2 instance type
    Type: String
    Default: t2.medium
    AllowedValues: [t2.nano, t2.micro, t2.small, t2.medium, t2.large, t2.xlarge, t2.2xlarge,
      m4.large, m4.xlarge, m4.2xlarge, m4.4xlarge, m4.10xlarge, m4.16xlarge,
      c4.large, c4.xlarge, c4.2xlarge, c4.4xlarge, c4.8xlarge,
      r4.large, r4.xlarge, r4.2xlarge, r4.4xlarge, r4.8xlarge, r4.16xlarge]
    ConstraintDescription: Please choose a valid instance type.
  AvailabilityZones:
    Description: List of 2 Availability Zones to use for the subnets in the VPC.
    Type: "List<AWS::EC2::AvailabilityZone::Name>"
  KeyPairName:
    Description: Public/private key pair to provide SSH access to the EC2 instances.
    Type: "AWS::EC2::KeyPair::KeyName"
Resources:
  VPCStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: 'https://s3.amazonaws.com/quickstart-reference/aws/vpc/latest/templates/aws-vpc.template'
      Parameters:
        AvailabilityZones: !Join [',', !Ref AvailabilityZones]
        KeyPairName: !Ref KeyPairName
        NumberOfAZs: 2
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: VPC Security Group
      VpcId: !GetAtt VPCStack.Outputs.VPCID
  OpalServer1:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !FindInMap [ RegionMap, !Ref "AWS::Region", opal]
      InstanceType: !Ref InstanceType
      SecurityGroupIds: [!Ref SecurityGroup]
      SubnetId: !GetAtt VPCStack.Outputs.PrivateSubnet1AID
      KeyName: !Ref KeyPairName
  OpalServer2:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !FindInMap [ RegionMap, !Ref "AWS::Region", opal]
      InstanceType: !Ref InstanceType
      SecurityGroupIds: [!Ref SecurityGroup]
      SubnetId: !GetAtt VPCStack.Outputs.PrivateSubnet2AID
      KeyName: !Ref KeyPairName
  RStudioClient:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !FindInMap [ RegionMap, !Ref "AWS::Region", rstudio]
      InstanceType: !Ref InstanceType
      SecurityGroupIds: [!Ref SecurityGroup]
      SubnetId: !GetAtt VPCStack.Outputs.PublicSubnet1ID
      KeyName: !Ref KeyPairName

If you need to learn more about CloudFormation I recommend checking out this really handy article from Tung Nguyen over at https://medium.com/boltops/a-simple-introduction-to-aws-cloudformation-part-1-1694a41ae59d

THE AWS CDK

So getting back to “What is the AWS CDK?”. The AWS CDK is simply a way for developers to create their cloud infrastructure by writing code like C#, Typescript, Python etc…

This code is then translated into a CloudFormation template and can be deployed on AWS using a simple and very friendly developer friendly CLI.

This is a new way for developers to provision cloud infrastructure and allows them to deploy resources easily, without deep knowledge about complicated services like Identity and Access Management (IAM).

LETS GET GOING

So first things first, to use the AWS CDK we need to install NodeJS. Not sure what NodeJS or how to install? Then go do some reading at https://nodejs.org/

Providing you have NodeJS installed, you can run the following command in your terminal to install the CDK as a global npm package.

npm install -g aws-cdk
Provided everything installs ok you should see something like the above in your terminal

Before we continue you need to make sure you have an AWS credentials profile configured. If you’ve used the AWS CLI before chances are you already have.

You must specify your credentials and an AWS Region to use the CDK CLI. The CDK looks for credentials and region in the following order:

  • Using the –profile option to cdk commands.
  • Using environment variables.
  • Using the default profile as set by the AWS Command Line Interface (AWS CLI).

Your AWS credentials can be configured by editing the config file found at  ~/.aws/config (Linux or Mac) or %USERPROFILE%\.aws\config (Windows)

Or by using the AWS CLI (See the AWS CLI documentation for more info on this)

Below you can see an example of a configured profile

[YOUR_PROFILE_NAME]
aws_access_key_id=AKIAYSUIAOSOPSEXAMPLE
aws_secret_access_key=je7MtGbClwBF/2Zp9Utk/YuxkajsEXAMPLEKEY
region=us-east-1

To keep things simple we’ll use the AWS CLI configure command

$ aws configure
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: us-east-1
Default output format [None]: JSON

You should now be at a point where you can setup the project folder structure for your CDK app. I won’t bother going over this because frankly I don’t care. Just make sure to make a note of the foldername(you’ll need it) created and using your terminal or cmd prompt navigate to that folder.

In this example we’re using Typescript. The below command will create a simple empty CDK app in Typescript

cdk init --language typescript

Hopefully that worked and you now have a new default cdk app ready to go. If it didn’t…. well….. copy paste the error into google and good luck.

So anyway, you have the app, now this is where nodejs comes in, or rather NPM(node package manager). Run the following command to download all the dependencies for the CDK app

npm run install

So depending on the foldername you used, the CDK app will have been created with an entry file with the same name as your folder. i.e. If your folder was called testcdkapp. The entrypoint of the application will be found in the bin directory with the name  testcdkapp.ts (if you initialized the application in a directory with a different name, this file will have a different name).

#!/usr/bin/env node
import 'source-map-support/register';
import cdk = require('@aws-cdk/cdk');
import { testcdkappStack } from '../lib/testcdkapp-stack';

const app = new cdk.App();
new testcdkappStack(app, 'testcdkappStack');

All we need is the above to create a boilerplate template for our app. We first create a new CDK app and add the  testcdkappStack to it. This stack is created in the lib directory. Have a look at the testcdkapp-stack file in this directory.

What you will find is an empty stack. To generate a CloudFormation stack from this Typescript code, run cdk synth. You will see a YAML file with only a CDKMetadata resource. Let’s add our first resource to this stack!

As this is a typescript project the code we write will be converted to Javascript. In a new terminal, run npm run watch. This will watch for any changes to the Typescript code, and generate Javascript.

Now, below the line // The code that defines your stack goes here, add the following code:

const queue = new Queue(this, 'queue', {
    queueName: 'testQueue'
});

Also, add the top of the file add the following import:

import { Queue } from '@aws-cdk/aws-sqs';

Finally, in the package.json file in the root of your project, be sure to add the following dependency in the dependencies object:

"@aws-cdk/aws-sqs": "^0.33.0",

Be sure to run npm install again to download the SQS dependency.

Now, run cdk synth again and note that the generated CloudFormation now contains a SQS queue:

queue276F7297:
    Type: AWS::SQS::Queue
    Properties:
        QueueName: testQueue
    Metadata:
        aws:cdk:path: testcdkapp2Stack/queue/Resource

So basically this CloudFormation stack will generate a queue with the name “testQueue” as we have defined in the CDK. Assuming you have properly configured the AWS CLI on your system, you can now deploy this stack using the following command:

cdk deploy

Very soon an SQS queue will be deployed to your AWS environment. Whilst not anything groundbreaking it demonstrates how easy it is to write a simple bit of code to deploy your infrastructure.

Coming up in Part 2

For part 2 of this tutorial we’ll take things further and we’ll look at building and deploying the foundations of a simple serverless application using the CDK.

Leave a comment

Design a site like this with WordPress.com
Get started