In this article let us build necessary components which we need to setup a basic lambda stack which will be used in later in subsequent articles to act us a web hook taking some data into our ecosystem from other demo projects.
Beginners new to AWS CDK, please do look at my previous articles in this series.
If incase missed the previous article do find it with the below links.
π Original previous post at π Dev Post
π Reposted previous post at π dev to @aravindvcyber
First before we start moving forward let us try to do some cleanup on the current demo workshop stack and understand how it reflects this changes. This will give us good understanding on certain concepts before we move forward.
Removing the unwanted resources β
Open lib/cdk-workshop-stack.ts
.
Here let us simply comment out the components initially created which is the SQS queue and the SNS topic with subscriptions, it should look like the below.
export class CdkWorkshopStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// const queue = new sqs.Queue(this, 'CdkWorkshopQueue', {
// visibilityTimeout: Duration.seconds(300)
// });
// const topic = new sns.Topic(this, 'CdkWorkshopTopic');
// topic.addSubscription(new subs.SqsSubscription(queue));
}
}
What we have achieved is like something we can understand with the cdk diff
command.
IAM Statement Changes
βββββ¬ββββββββββββββββββββββββββββββββββ¬βββββββββ¬ββββββββββββββββββ¬ββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β Resource β Effect β Action β Principal β Condition β
βββββΌββββββββββββββββββββββββββββββββββΌβββββββββΌββββββββββββββββββΌββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β - β ${CdkWorkshopQueue50D9D426.Arn} β Allow β sqs:SendMessage β Service:sns.amazonaws.com β "ArnEquals": { β
β β β β β β "aws:SourceArn": "${CdkWorkshopTopicD368A42F}" β
β β β β β β } β
βββββ΄ββββββββββββββββββββββββββββββββββ΄βββββββββ΄ββββββββββββββββββ΄ββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)
Resources
[-] AWS::SQS::Queue CdkWorkshopQueue50D9D426 destroy
[-] AWS::SQS::QueuePolicy CdkWorkshopQueuePolicyAF2494A5 destroy
[-] AWS::SNS::Subscription CdkWorkshopQueueCdkWork
[-] AWS::SNS::Topic CdkWorkshopTopicD368A42F destroy
This signifies that while we delete the SQS and SNS, it eventually removes the newly created queue policy and the topic subscription associated to this.
Make sure you run cdk deploy
to cleanup the environment changes.
Simple lambda stack π
Now we have cleaned our environment, let us start now from basics by trying to build a simple lambda stack which will be acting as a common gateway for the messages coming into our environment as we build this forward.
import { Construct } from 'constructs';
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.
Before we proceed let us create a new stack by following the below steps
In the lib folder create a new file like CommonEventStack.ts
, where we will add the basic template as follows.
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class CommonEventStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
}
}
Then go to your bin\cdk-workshop.ts
and import the new stack we just created.
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { CdkWorkshopStack } from '../lib/cdk-workshop-stack';
// importing our new stack
import { CommonEventStack } from '../lib/common-event-stack';
const app = new cdk.App();
new CdkWorkshopStack(app, 'CdkWorkshopStack');
// initializing our new stack
new CommonEventStack(app, 'CommonEventStack');
It is time to run npm run build
to make sure we never introduced any error in the process.
Finally we can run cdk ls
to see the below output.
CdkWorkshopStack
CommonEventStack
And by the way I just gave the prefix CommonEvent*
to our new stack resources, which we are about create also to demonstrate that we can have multiple stacks in the same project.
It is now time to create our lambda function, let us create a folder called lambda
in the root of the project and add a new file event-entry.ts
, as shown below. Note I have started with TypeScript file and it needs to be transpiled to JavaScript when we deploy it into lambda.
exports.receiver = async function(event:any) {
console.log("request:", JSON.stringify(event, undefined, 2));
return {
statusCode: 200,
headers: { "Content-Type": "text/plain" },
body: `Message Received: ${event}\n`
};
};
Once you run npm build, you can notice the javascript files are created in the same folder, event-entry.js
"use strict";
exports.receiver = async function (event) {
console.log("request:", JSON.stringify(event, undefined, 2));
return {
statusCode: 200,
headers: { "Content-Type": "text/plain" },
body: `Message Received: ${event}\n`
};
};
//# sourceMappingURL*********
Let us use this function to build our lambda function inside our new stack CommonEventStack.ts
.
// A simple lambda Lambda resource definition
const eventEntry = new lambda.Function(this, 'EventEntryHandler', {
runtime: lambda.Runtime.NODEJS_14_X, // execution environment
code: lambda.Code.fromAsset('lambda'), // code loaded from "lambda" directory
handler: 'event-entry.receiver' // file is "event-entry", function is "receiver"
});
}
Don't forget to add the necessary imports if it complains π
import * as lambda from 'aws-cdk-lib/aws-lambda'
Here we are using NodeJs 14x runtime and specifying the handler function to be from the file named event-entry
with function name like receiver
.
It is time to run cdk synth CommonEventStack
, to find the changes in the yaml template or run cdk diff CommonEventStack
to find the changes more readable.
This to lookout for is listed below in the log below:
IAM Statement Changes
βββββ¬βββββββββββββββββββββββββββββββββββββββ¬βββββββββ¬βββββββββββββββββ¬βββββββββββββββββββββββββββββββ¬ββββββββββββ
β β Resource β Effect β Action β Principal β Condition β
βββββΌβββββββββββββββββββββββββββββββββββββββΌβββββββββΌβββββββββββββββββΌβββββββββββββββββββββββββββββββΌββββββββββββ€
β + β ${EventEntryHandler/ServiceRole.Arn} β Allow β sts:AssumeRole β Service:lambda.amazonaws.com β β
βββββ΄βββββββββββββββββββββββββββββββββββββββ΄βββββββββ΄βββββββββββββββββ΄βββββββββββββββββββββββββββββββ΄ββββββββββββ
IAM Policy Changes
βββββ¬βββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β Resource β Managed Policy ARN β
βββββΌβββββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β + β ${EventEntryHandler/ServiceRole} β arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole β
βββββ΄βββββββββββββββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Resources
[+] AWS::IAM::Role EventEntryHandler/ServiceRole EventEntryHandlerServiceRoleF9517B59
[+] AWS::Lambda::Function EventEntryHandler EventEntryHandler0826D724
Here two resources are created IAM:role
and Lambda:function
. Basically a new role is created to be assumed by the lambda function we created for its proper execution.
Let us deploy it, by running cdk deploy CommonEventStack
and confirming with y
for the above IAM policy changes.
CommonEventStack: creating CloudFormation changeset...
β
CommonEventStack
β¨ Deployment time: 46.9s
Stack ARN:
arn:aws:cloudformation:ap-south-1:********:stack/CommonEventStack/93688c10-a10a-11ec-b942-0ad3136ae540
β¨ Total time: 60.19s
Inspection in AWS console π
Now we can navigate to the lambda in AWS console into your default region and you will be able to identify the lambda.
Let us test this lambda now π
For which we have to have some sample test event as follows.
Let us create run the same test, we have created above.
You can also find this logged inside the cloud watch logs.
And that is it, we have a new lambda function running which is ready to receive our messages. So what we have achieved in this article is only tech demonstration, which can be further vertically integrated based on the use cases and is not considered to be the best approach, rather it is only a know-how.
Before we complete this article let us understand one more cdk cli which we would find to be very much helpful in your development environment.
Hot swapping deployments πΊ
cdk deploy --hotswap
This command deliberately introduces drift in CloudFormation stacks in order to speed up deployments. For this reason, only use it for development purposes. Never use hotswap for your production deployments!
Let us make a simple change in our code for lambda in the entry
exports.receiver = async function(event:any) {
console.log("request:", JSON.stringify(event, undefined, 2));
return {
statusCode: 200,
headers: { "Content-Type": "text/plain" },
body: `Hotswapped now! \nMessage Received: ${JSON.stringify(event)}\n`
};
};
Just be mindful of the fact this only publishes the assets already built for lambda, in certain cases you will have used typescript in lambda and forget to build it before hotswaping, in that case the distributable files configured will be published but the js
files would never have been updated yet. I make sure to add a script in my package json to run it like a script in package.json
.
"fast": "npm run build && cdk deploy CommonEventStack --hotswap"
The total time taken is reduced, but what is significant to notice here is the deployment time
which is reduced to very small value. Earlier it is 45+s for full deployment, now here it is only 2+ seconds, would be useful in the development environment.
β¨ hotswapping resources:
β¨ Lambda Function 'CommonEventStack-EventEntryHandler0826D724-xaVWqcUsxERH'
β¨ Lambda Function 'CommonEventStack-EventEntryHandler0826D724-xaVWqcUsxERH' hotswapped!
β
CommonEventStack
β¨ Deployment time: 2.22s
Stack ARN:
arn:aws:cloudformation:ap-south-1:575066707855:stack/CommonEventStack/93688c10-a10a-11ec-b942-0ad3136ae540
β¨ Total time: 15.81s
Here I introduced some jargon drift
, let us see what it means and how it can be helpful. To enable this you can select a stack or a resource under it and enable drift detection to capture it for tracking and audit.
Drift detection π’
Drift detection enables you to detect whether a stack's actual configuration differs, or has drifted, from its expected configuration. Use CloudFormation to detect drift on an entire stack, or on individual resources within the stack.
A resource is considered to have drifted if any of its actual property values differ from the expected property values. This even includes if the property or resource has been deleted. A stack is considered to have drifted if one or more of its resources have drifted.
Here instead of using native cloud formation deployment, a more simple swift deployment is carried out by hot-swapping deployment by making use of the drifting changes on top of the initial stack.
Resource drift status code and description π½
This is basically a comparison with the recent cloudformation deployment.
- DELETED The resource differs from its expected template configuration because the resource has been deleted.
- MODIFIED The resource differs from its expected template configuration.
- NOT_CHECKED CloudFormation has not checked if the resource differs from its expected template configuration.
- IN_SYNC The resource's current configuration matches its expected template configuration.
Before we wrap up let us see one more deploy cli command below.
CDK Watch πͺ
CDK watch helps to monitor the file changes and invoke cdk deploy when it is needed. It monitors the files specified in the include and the exclude list in the cdk.json
file.
{
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"lambda/*.ts",
"tsconfig.json",
"package*.json",
"yarn.lock",
"node_modules",
"test"
]
},
}
In the above snippet, I have purposefully updated the **/*.js
to lambda/*.ts
. This change is done to make sure the ts
file changes in our lambda source not detectable at the same time it will detect the .js file which be emitted by tsc
.
So I will be launching couple of windows to run tsc -w
and cdk watch CommonEventStack --hotswap
. Working in parallel this will automatically deploy the expect lambda code changes, basically these are developer friendly customizations.
tsc -w
this rewrites the js files.
[4:26:07 PM] File change detected. Starting incremental compilation...
[4:26:11 PM] Found 0 errors. Watching for file changes.
cdk watch CommonEventStack --hotswap
published my js files automatically and swiftly.
Detected change to 'lambda/event-entry.js' (type: change). Triggering 'cdk deploy'
β¨ Synthesis time: 21.92s
β¨ hotswapping resources:
β¨ Lambda Function 'CommonEventStack-EventEntryHandler0826D724-xaVWqcUsxERH'
β¨ Lambda Function 'CommonEventStack-EventEntryHandler0826D724-xaVWqcUsxERH' hotswapped!
β
CommonEventStack
β¨ Deployment time: 2.17s
Stack ARN:
arn:aws:cloudformation:ap-south-1:575066707855:stack/CommonEventStack/93688c10-a10a-11ec-b942-0ad3136ae540
current credentials could not be used to assume 'arn:aws:iam::575066707855:role/cdk-hnb659fds-lookup-role-575066707855-ap-south-1', but are for the right account. Proceeding anyway.
(To get rid of this warning, please upgrade to bootstrap version >= 8)
β¨ Total time: 24.09s
We will add more connections to this lambda and make it more usable in the coming articles stay subscribed.
β We have our next article in serverless, do check out
aws-cdk-101-api-gateway-construct-usage-throttle-quota-usage-plans-api-keys
Thanks for supporting! π
Would be really great if you like to β Buy Me a Coffee, to help boost my efforts.
Also follow my posts in the platform of your choice listed below.
π Original post at π Dev Post
π Reposted at π dev to @aravindvcyber
Top comments (0)