We’ll start with the AWS Lambda handler code.
lambda
in the root of your project tree (next to bin
and lib
).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 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.
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.
To discover and learn about AWS constructs, you can browse the AWS Construct Library reference.
Okay, let’s use npm install
(or in short npm i
) to install the AWS Lambda
module and all it’s dependencies into our project:
npm install @aws-cdk/aws-lambda@0.22.0
Output should look like this:
+ @aws-cdk/aws-lambda@0.22.0
updated 1 package and audited 1571 packages in 5.098s
You can safely ignore any warnings from npm about your package.json file.
In this workshop, we highly recommended to type CDK code instead of copying & pasting (there’s usually not much to type). This way, you’ll be able to fully experience what it’s like to use the CDK. It’s especially cool to see your IDE help you with auto-complete, inline documentation and type safety.
Add an import
statement at the beginning of lib/cdk-workshop-stack.ts
, and a
lambda.Function
to your stack.
import cdk = require('@aws-cdk/cdk');
import lambda = require('@aws-cdk/aws-lambda');
export class CdkWorkshopStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// defines an AWS Lambda resource
const hello = new lambda.Function(this, 'HelloHandler', {
runtime: lambda.Runtime.NodeJS810, // execution environment
code: lambda.Code.asset('lambda'), // code loaded from the "lambda" directory
handler: 'hello.handler' // file is "hello", function is "handler"
});
}
}
A few things to notice:
npm run watch
window that hello is declared but never use. Cool huh?lambda
directory which we created
earlier. Path is relative to where you execute cdk
from, which is the
project’s root directoryhello.handler
(“hello” is the name of
the file and “handler” is the exported function name)As you can see, the class constructors of both CdkWorkshopStack
and
lambda.Function
(and many other classes in the CDK) have the signature
(scope, id, props)
. This is because all of these classes are constructs.
Constructs are the basic building block of CDK apps. They represent abstract
“cloud components” which can be composed together into higher level abstractions
via scopes. Scopes can include constructs, which in turn can include other
constructs, etc.
Constructs are always created in the scope of another construct and must always have an identifier which must be unique within the scope it’s created. Therefore, construct initializers (constructors) will always have the following signature:
scope
: the first argument is always the scope in which this construct
is created. In almost all cases, you’ll be defining constructs within the
scope of current construct, which means you’ll usually just want to pass
this
for the first argument. Make a habit out of it.id
: the second argument is the local identity of the construct.
It’s an ID that has to be unique amongst construct within the same scope. The
CDK uses this identity to calculate the CloudFormation Logical
ID
for each resource defined within this scope. To read more about IDs in the
CDK, see the CDK user
manual.props
: the last (sometimes optional) argument is always a set of
initialization properties. Those are specific to each construct. For example,
the lambda.Function
construct accepts properties like runtime
, code
and
handler
. You can explore the various options using your IDE’s auto-complete
or in the online
documentation.Save your code, and let’s take a quick look at the diff before we deploy:
cdk diff
Output would look like this:
The CdkWorkshopStack stack uses assets, which are currently not accounted for in the diff output! See https://github.com/awslabs/aws-cdk/issues/395
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 http://bit.ly/cdk-2EhF7Np)
Parameters
[+] Parameter HelloHandler/Code/S3Bucket HelloHandlerCodeS3Bucket4359A483: {"Type":"String","Description":"S3 bucket for asset \"CdkWorkshopStack/HelloHandler/Code\""}
[+] Parameter HelloHandler/Code/S3VersionKey HelloHandlerCodeS3VersionKey07D12610: {"Type":"String","Description":"S3 key for asset version \"CdkWorkshopStack/HelloHandler/Code\""}
Resources
[+] AWS::IAM::Role HelloHandler/ServiceRole HelloHandlerServiceRole11EF7C63
[+] AWS::Lambda::Function HelloHandler HelloHandler2E4FBA4D
As you can see, this code synthesizes an AWS::Lambda::Function resource. It also synthesized a couple of CloudFormation parameters that are used by the toolkit to propagate the location of the handler code.
Let’s deploy:
cdk deploy
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.
Let’s go to the AWS Lambda Console and test our function.
Open the AWS Lambda Console (make sure you are in the correct region).
You should see our function:
Click on the function name to go to the console.
Click on the Test button to open the Configure test event dialog:
Select Amazon API Gateway AWS Proxy from the Event template list.
Enter test
under Event name.
Hit Create.
Click Test again and wait for the execution to complete.
Expand Details in the Execution result pane and you should see our expected output: