chrismitchellonline

Using AWS CDK and SAM

2021-09-12

With the AWS CDK framework, we can define cloud application resources using familiar programming languages and deploy to CloudFormation to build our resources. Combining this with AWS SAM, the serverless application model, we can deploy Lambda source code and our cloud resources at the same time.

Prerequisits

Along with an AWS account with sufficient permissions, you’ll need the following installed on your local machine:

  • NPM installed, required to manage NodeJS packages.
  • AWS CLI Tools: The Command Line Interface to interact with AWS with access keys.
  • AWS CDK Library: Install the CDK library and run a bootstrap command to create necessary resources. More information: AWS CDK
  • AWS SAM Library and SAM CLI Beta: To use SAM with CDK, we’ll need the beta version installed. Installation instructions are here: AWS SAM Library with CDK. Essentially we’ll be using the command sam-beta-cdk in this article.

CDK Template

To get started we’ll use a predefined folder structure to hold both of our CDK code, which will define our CloudFormation templates, along with our Lambda source code. For our template we will be using Javascript. From your project directory run the following command:

cdk init app --language javascript

Note: My project directory is called aws_cdk_and_sam so files will be named according to this folder name.

This will create the structure for our CDK project. A few important files to look at:

  • bin/aws-cdk-and-sam.js: This is the bootstrap file created for our project. This file will initiate our stack, in this example AwsCdkAndSamStack.
  • lib/aws-cdk-and-sam-stack.js: This file is called from bin/aws-cdk-and-sam.js to create our stack resources.

Adding Lambda Resource

From our file lib/aws-cdk-and-sam-stack.js we’ll create our Lambda resource. To do this we’ll need to add the Lamba NPM package to CDK. We can do this with NPM:

npm i @aws-cdk/aws-lambda

And then add this to the top of your lib/aws-cdk-and-sam-stack.js file:

const lambda = require("@aws-cdk/aws-lambda");

Then in same file add the following snippet to your class to create a Lambda resource. In this example the Lambda function is called lambda-cdk and will use local path for the source code (more on this later):

new lambda.Function(this, "lambda-cdk", {
    runtime: lambda.Runtime.NODEJS_14_X,
    code: lambda.Code.fromAsset('src/lambda/lambda-cdk'),      
    handler: "index.handler",
    functionName: "lambda-cdk",
});

For more information about the Lambda class, see here: Lambda CDK

The Lambda class will use the code: lambda.Code.fromAsset(‘src/lambda/lambda-cdk’), property to load our source code from a local folder.

Next we’ll add source code for our lambda-cdk function.

Lambda Source Code

We’ll store the source code for the Lambda function in the folder src/lambda/lambda-cdk. We will need to create this folder structure, along with an index.js file.

Use the following source code for our Lambda function in index.js:

exports.handler = function(event, context, callback) {
   console.log("Received event: ", event);
   var data = {
       "greeting": event.greeting
   };
   callback(null, data);
}

We’ll also need to create a new package.json file for our function, which is a requirement of SAM to build our function. Use NPM with the following command:

npm init -y

Now we can run and test our source code with SAM local and use CDK to deploy our infrastructure as code.

SAM Local

To run our Lambda function locally, we’ll need a template.yml file to define our function. Create this file along with index.js at src/lambda/lambda-cdk/template.yml with the following:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Lambda with CDK
    
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
    Function:
        Timeout: 600
        MemorySize: 1024


Resources:
    
    test:
        Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
        Properties:
            CodeUri: ./
            Handler: index.handler
            Runtime: nodejs12.x
            Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
                Variables:
                    PARAM1: VALUE
    
Outputs:    

    test:
      Description: "Test it!"
      Value: !GetAtt test.Arn    

Along with the template.yml file, we need a test events file. Create a file at src/lambda/lambda-cdk/test-events/test.json, with the following content:

{
    "greeting":"Hello from Lambda"
}

Now we can test our local Lambda function with the following command, run from src/lambda/lambda-cdk:

sam-beta-cdk local invoke test -e test-events/test.json

Note: I am using the beta version of SAM, which includes the CDK integration. The beta version of SAM CLI command is sam_beta_cdk. If you have SAM already installed, it will still work alongside the beta version.

You should see a successful run of SAM CLI, with your Lamba output, similar to { greeting: ‘Hello from Lambda’ }.

Now we can add this Lambda source code to our CDK stack. Change to the root directory and run following SAM command:

sam-beta-cdk build

With a successful run, you’ll get the following. Notice the Deploy command:

Build Succeeded

Built Artifacts  : .aws-sam/build

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: cdk deploy -a .aws-sam/build

Next we can use CDK to deploy our CloudFormation template.

CDK Deploy

We can use CDK to push our template to AWS and have CloudFormation build our resources. With the output from SAM, use the following command to deploy:

cdk deploy -a .aws-sam/build

Review and accept any output. For example, CDK warned me about creating a new service role for Lambda. After finishing you should see:

✅  AwsCdkAndSamStack
arn:...

Checking in AWS, I now see the CloudFormation stack and my Lambda function.

Publish Updates

To publish new source code for you Lambda function, modify the source in src/lambda/ and run the commands to build and deploy again:

sam-beta-cdk build
cdk deploy -a .aws-sam/build

This will update the CloudFormation stack locally, and then deploy changes to AWS.

Finally, to update or add new resources to CloudFormation, update the CDK class at lib/aws-cdk-and-sam-stack.js, and run the same build and deploy commands again.

Conclusion

With this CDK + SAM setup you can now package and deploy both Lambda source code updates along with infrastructure as code using familiar programming languages and AWS supported CLI tools.

Additional Resources

comments powered by Disqus
Social Media