Hello AWS Lambda

In this module you are going to deploy sample AWS Lambda function using CDK.

Lambda handler code

We’ll start with the AWS Lambda handler code.

Create a directory lambda in the root of your project tree (next to src).

Lambda Nuget

Add a file called lambda/hello.js with the following contents:

exports.handler = async function(event) {
  console.log("request:", JSON.stringify(event, undefined, 2));
  return {
    statusCode: 200,
    headers: { "Content-Type": "text/plain" },
    body: `Hello, CDK! You've hit ${event.path}\n`
  };
};

This is a simple AWS Lambda function which returns the text “Hello, CDK! You’ve hit [url path]”. The function’s output also includes the HTTP status code and HTTP headers. These are used by API Gateway to formulate the HTTP response to the user.

Update project

The AWS CDK is shipped with an extensive library of constructs called the AWS Construct Library. The construct library is divided into modules, one for each AWS service. For example, if you want to define an AWS Lambda function, we will need to use the AWS Lambda construct library.

Install Amazon.CDK.AWS.Lambda Nuget package.

Lambda Nuget

Update CdkLabStack.cs with the following changes:

  • Add using statement
using Amazon.CDK.AWS.Lambda
  • Add Function resource
using Amazon.CDK;
using Amazon.CDK.AWS.Lambda;

namespace CdkLab
{
    public class CdkLabStack : Stack
    {
        internal CdkLabStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            // Defines a new lambda resource
            var hello = new Function(this, "HelloHandler", new FunctionProps
            {
                Runtime = Runtime.NODEJS_14_X, // execution environment
                Code = Code.FromAsset("lambda"), // Code loaded from the "lambda" directory
                Handler = "hello.handler" // file is "hello", function is "handler"
            });
        }
    }
}

A few things to notice:

  • Your function uses NodeJS 14.X runtime
  • The handler code is loaded from the lambda directory which we created earlier. Path is relative to where you execute cdk from, which is the project’s root directory
  • The name of the handler function is hello.handler (“hello” is the name of the file and “handler” is the exported function name)

Deploy

First run cdk diff to take a look at the changes that are going to be deployed.

cdk diff

The output should look like this:

Stack CdkLabStack
IAM Statement Changes
┌───┬─────────────────────────────────┬────────┬────────────────┬──────────────────────────────┬───────────┐
│   │ Resource                        │ Effect │ Action         │ Principal                    │ Condition │
├───┼─────────────────────────────────┼────────┼────────────────┼──────────────────────────────┼───────────┤
│ + │ ${HelloHandler/ServiceRole.Arn} │ Allow  │ sts:AssumeRole │ Service:lambda.amazonaws.com │           │
└───┴─────────────────────────────────┴────────┴────────────────┴──────────────────────────────┴───────────┘
IAM Policy Changes
┌───┬─────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐
│   │ Resource                    │ Managed Policy ARN                                                             │
├───┼─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${HelloHandler/ServiceRole} │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole │
└───┴─────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

..........

Resources
[+] AWS::IAM::Role HelloHandler/ServiceRole HelloHandlerServiceRole11EF7C63
[+] AWS::Lambda::Function HelloHandler HelloHandler2E4FBA4D

As you can see, this code synthesizes an AWS::Lambda::Function and AWS::IAM::Role resources. It also synthesized a couple of CloudFormation parameters that are used by the toolkit to propagate the location of the handler code.

Now it’s time to deploy the function.

cdk deploy

You should see a warning like the following:

This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
Please confirm you intend to make the following modifications:

IAM Statement Changes
┌───┬─────────────────────────────────┬────────┬────────────────┬──────────────────────────────┬───────────┐
│   │ Resource                        │ Effect │ Action         │ Principal                    │ Condition │
├───┼─────────────────────────────────┼────────┼────────────────┼──────────────────────────────┼───────────┤
│ + │ ${HelloHandler/ServiceRole.Arn} │ Allow  │ sts:AssumeRole │ Service:lambda.amazonaws.com │           │
└───┴─────────────────────────────────┴────────┴────────────────┴──────────────────────────────┴───────────┘
IAM Policy Changes
┌───┬─────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐
│   │ Resource                    │ Managed Policy ARN                                                             │
├───┼─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${HelloHandler/ServiceRole} │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole │
└───┴─────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Do you wish to deploy these changes (y/n)? y

Enter y to deploy the stack and create the resources.

Once stack is deployed, you should see the output like the following:

CdkLabStack: deploying...
[0%] start: Publishing eaef12906cbc069bda420d5a82f9ae982e64b429c73591ce865f7386404092b5:current
[100%] success: Published eaef12906cbc069bda420d5a82f9ae982e64b429c73591ce865f7386404092b5:current
CdkLabStack: creating CloudFormation changeset...
 0/4 | 5:57:04 AM | REVIEW_IN_PROGRESS   | AWS::CloudFormation::Stack | CdkLabStack User Initiated
 0/4 | 5:57:09 AM | CREATE_IN_PROGRESS   | AWS::CloudFormation::Stack | CdkLabStack User Initiated
 1/4 | 5:57:32 AM | CREATE_IN_PROGRESS   | AWS::IAM::Role        | HelloHandler/ServiceRole (HelloHandlerServiceRole11EF7C63)
 1/4 | 5:57:32 AM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata    | CDKMetadata/Default (CDKMetadata)
 1/4 | 5:57:32 AM | CREATE_IN_PROGRESS   | AWS::IAM::Role        | HelloHandler/ServiceRole (HelloHandlerServiceRole11EF7C63) Resource creation Initiated
 1/4 | 5:57:33 AM | CREATE_IN_PROGRESS   | AWS::CDK::Metadata    | CDKMetadata/Default (CDKMetadata) Resource creation Initiated
 1/4 | 5:57:34 AM | CREATE_COMPLETE      | AWS::CDK::Metadata    | CDKMetadata/Default (CDKMetadata)
 2/4 | 5:57:51 AM | CREATE_COMPLETE      | AWS::IAM::Role        | HelloHandler/ServiceRole (HelloHandlerServiceRole11EF7C63)
 2/4 | 5:57:53 AM | CREATE_IN_PROGRESS   | AWS::Lambda::Function | HelloHandler (HelloHandler2E4FBA4D)
 2/4 | 5:57:54 AM | CREATE_IN_PROGRESS   | AWS::Lambda::Function | HelloHandler (HelloHandler2E4FBA4D) Resource creation Initiated
 4/4 | 5:57:54 AM | CREATE_COMPLETE      | AWS::Lambda::Function | HelloHandler (HelloHandler2E4FBA4D)
 4/4 | 5:57:56 AM | CREATE_COMPLETE      | AWS::CloudFormation::Stack | CdkLabStack

 ✅  CdkLabStack

Stack ARN:
arn:aws:cloudformation:eu-west-1:969522832499:stack/CdkLabStack/c0262920-97a0-11eb-bef8-06821bb380e5

You’ll notice that cdk deploy not only deployed your CloudFormation stack, but also archived and uploaded the lambda directory from your disk to the bootstrap bucket.

Test the function

On the AWS Console page, click on the Lambda link under the Compute section (or search for Lambda).

Lambda Test

Find your Lambda function (name starts with CdkLabStack-HelloHandler) and open it.

Switch to Test tab and configure test event.

Choose Amazon API Gateway AWS Proxy as event template (please notice the value of path attribute in the sample payload).

Lambda Test

Click Invoke button to run the function.

Expand Details in the Execution result pane and you should see an expected output (please notice that path value comes from the sample workload you provided):

Lambda Test