AWS CDK - Building Telegram bot with AWS Lambda and API Gateway Proxy Integration - Part 1
Tags: aws, javascript, cloud, webdev
Published: 2021-11-02 09:31:59

This is the first part of the Building Telegram bot with AWS Lambda and API Gateway Proxy Integration Series and this article would feel easy incase you come from Cloudformation or Terraform background. For beginners, this would make more sense if you follow this article along with AWS CDK Official Guide.


As per official documentation, The AWS Cloud Development Kit (AWS CDK) is an open source software development framework to define your cloud application resources using familiar programming languages. 

It means that now you can use TypeScript, JavaScript, Python, Java, or C# to create Infrastructure instead of JSON/YAML used in Cloudformation template.

Advantage of AWS CDK over Cloudformation:
- Use logic (if statements, for-loops, etc) when defining your infrastructure
- Use object-oriented techniques to create a model of your system
- Define high level abstractions, share them, and publish them to your team, company, or community
- Organize your project into logical modules
- Share and reuse your infrastructure as a library
- Testing your infrastructure code using industry-standard protocols
- Use your existing code review workflow
Code completion within your IDE


With AWS CDK you can design your own reusable components that meet your organization’s security, compliance, and governance requirements. It also provides high-level components that preconfigure cloud resources with proven defaults, helping you build on AWS without needing to be an expert.

Which means Construct props can have default values for some key as mentioned in document for API-Gateway Stage. Do check the Construct Props section and scroll down to see default values for some properties.

https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-apigateway.Stage.html


```javascript
new Stage(scope: Construct, id: string, props: StageProps)
```


This is part 1 of building Telegram bot using AWS SDK Series.

The AWS CDK Toolkit provides the cdk command-line interface that can be used to work with AWS CDK applications.



## How to setup AWS CDK Project
https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html

- Install CDK using Nodejs Package Manager
  - Lets install : ```npm install -g aws-cdk``` 
  - Check version using : ```cdk --version```

- Configure AWS Credential on your local Machine
  - Copy and Paste Access Keys and Secret Keys : ```aws configure```
  - Confirm if you gained the AWS Identity. ```aws sts get-caller-identity```


Many AWS CDK stacks that you write will include assets: external files that are deployed with the stack, such as AWS Lambda functions or Docker images. The AWS CDK uploads these to an Amazon S3 bucket or other container so they are available to AWS CloudFormation during deployment. Deployment requires that these containers already exist in the account and region you are deploying into. Creating them is called bootstrapping. 

To bootstrap, paste this :  
```
cdk bootstrap aws://$(aws sts get-caller-identity --output text --query Account)/$(aws configure get region)
```



```
mkdir telegram-bot
cd telegram-bot
```

We will create separate directory for managing aws-cdk file and lambda file.

```
mkdir cdk-tool
mkdir lambda
```


Now go to cdk-tool empty directory and initialize the app using the cdk init command, specifying the desired template ("app") and programming language. That is:

```
cd cdk-tool
cdk init app --language javascript
```

![CDK Installation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yf2oecd6j5c3x874jpe9.JPG)

Default directory structure would look like this:

![CDK Directory Structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/clylgoepf002bc8h5ret.JPG)

- `lib/cdk-tool-stack.js` : is where your CDK application's main stack is defined. You will write the infrastructure configuration over here in this file.
- `bin/cdk-tool.js` : This is the entrypoint of the CDK application. It will load the stack defined in `lib/cdk-tool-stack.js`
- `package.json` : is your npm module manifest. It includes information like the name of your app, version, dependencies and build scripts.
- `cdk.json`:  tells the toolkit how to run your app.
- `.gitignore and .npmignore` tell git and npm which files to include/exclude from source control and when publishing this module to the package manager.
- `node_modules` is maintained by npm and includes all your project’s dependencies.


## Creating Sample Lambda Function

Do you remember you created one more directory to store lambda function, ie. lambda directory. Lets switch to that directory from parent directory and create index.js file into telegram-bot directory containing nodejs function sourcecode.

```
cd lambda
mkdir telegram-bot
touch index.js
```

Paste this into `index.js` file.
```javascript
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`
    };
  };
```

Now, lets go back to `cdk-tool` directory from parent directory and link the lambda function sourcecode with AWS Lambda Construct and later bind it with API Gateway route.

Before that, you would need to install lambda and apigateway cdk constructs using

```
npm install @aws-cdk/aws-lambda
npm install @aws-cdk/aws-apigateway
```

Now move to cdk-tool directory :

`cd cdk-tool`

Go to `lib/cdk-tool-stack.js` and paste this imports at top:
```javascript
const lambda = require("@aws-cdk/aws-lambda");
const apigw = require("@aws-cdk/aws-apigateway");
```

A Lambda CDK construct would look lik below.
```javascript
    const lambdaTelegram = new lambda.Function(this, "telegramBotHandler", {
      runtime: lambda.Runtime.NODEJS_14_X,
      handler: "index.handler",
      code: lambda.Code.fromAsset("../lambda/telegram-bot"), // from parent directory containing package.json
      architecture: lambda.Architecture.ARM_64,
      environment: {
        'CURRENT_ENV': 'dev',
      }
    });
```

As seen above, we have mapped lamba sourcecode using `lambda.Code.fromAsset` and have setup runtime environment, entry of the function, architecture and Lambda Environment variables. 

We would also require API Gateway Proxy integration to map it with this lambda function and get invokable API Link using `apigw.RestApi`

```javascript
    const restApi = new apigw.RestApi(this, "telegrambot-api", { deploy: false });
```

Create a new resource path and setup GET method with it and attach it with lambda function construct.
```javascript
    const method = restApi.root
      .addResource("bot")
      .addMethod("GET", new apigw.LambdaIntegration(lambdaTelegram, { proxy: true }));
```

Since, we have passed `{ deploy: false }` inside api.RestApi construct props, we would need to create manual deployment and stage by ourselves. Incase, if you do not pass that option, it would create deployment and default `prod` stage for you and you can ignore next 2 snippet as well.

```javascript
    const devDeploy = new apigw.Deployment(this, "dev-deployment", { api: restApi });
```

Creating our own Stage with customized properties using `apigw.Stage`
```javascript
    const devStage = new apigw.Stage(this, "devStage", {
      deployment: devDeploy,
      stageName: 'dev' // If not passed, by default it will be 'prod'
    });
```

Emitting the output values after deployment using  `cdk.CfnOutput`.

```javascript
    new cdk.CfnOutput(this, "BotURL", {
      value: `https://${restApi.restApiId}.execute-api.${this.region}.amazonaws.com/dev/bot`,
    });
```

Final code of lib/cdk-tool-stack.js should look as below.

{% gist https://gist.github.com/arki7n/8a699db59c42c9e1aa11c88e18321807 %}

Now, lets validate the written constructs and see if it generates valid cloudformation template.

Enter command in root directory

 `cdk synth `
 and then you will see some new directories in your folder structure which contains cloudformation templates and metadata.
![CDK Synth](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w1ehuskfn8w7mhdmjeoj.JPG)

Lets deploy this application using:

 `cdk deploy`
![CDK Deploy start](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bcelarf5dv5ppov6sr1w.JPG)
You can see in above screenshot with resources that would be created. Confirm by pressing `y`.
![CDK Deploy done](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hm64i5qqux3w3b32pp3m.JPG)

Now, call the API on browser and check the response.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zf2bzxpocwanjgf1pw81.JPG)


 To destroy the application:

 `cdk destroy`

![CDK Destroy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t5lrpb5riu6pgf4gma05.JPG)

Confirm deletion by pressing `y`.
![CDK Destroyed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x74dkefde1j2urr885qw.JPG)

You can find the sourcecode on Git repository at :
https://github.com/arki7n/aws-cdk-telegram-bot-example.git

That's it! Hope you have get to complete all of the above steps and achieved the desired output. You can customize the lambda function source code and experiment things on your own as well. I shall be back with part 2 of this series in next blog post. Feel free to follow me to remain updated with next part 2 post.

{% user arki7n %}