CDK for Terraform with TypeScript
AWS With CDKTF
AWS With CDKTF
Welcome back to this lesson!
In our previous session, we built a basic app using the Terraform local provider. Today, we leverage the AWS provider to deploy resources on Amazon Web Services (AWS) using CDKTF.
In this module, we start by defining the problem and reviewing prerequisites and essential tools for deploying AWS resources.
We will deploy to AWS with CDKTF, following the journey of Arthur—a developer facing a household dilemma about who does the washing up each night. Arthur’s solution is to build an application that randomly assigns the chore.
Manual AWS Deployment Demo
Before automating with CDKTF, let's walk through a manual deployment process using the AWS Console.
To get started, we manually create all the necessary AWS resources for Arthur’s Name Picker application.
The target architecture is straightforward: Arthur calls an API Gateway on AWS, which then triggers an AWS Lambda function to pick a family member for the chore.
Deploying the Lambda Function Manually
- Open the KodeKloud Labs console and log in using the provided URL, username, and password.
- In the Lambda console, create a new function with the name “console name picker.” Select Node.js 20 as the runtime and click Create Function.
- Rename the file to use the .js extension and paste in the following basic business logic:
export const handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
Later, you'll enhance this function with logic to randomly select a name from a hardcoded array or to shuffle the array when needed. The final version of the Lambda function code is shown below:
let shuffledNames = [];
let currentIndex = 0;
exports.handler = async (event) => {
console.log('Received event', event);
// Parse environment variables with default values
const names = JSON.parse(process.env.NAMES || '["Arthur","Martin","Douglas","Carolyn"]');
const shuffle = process.env.SHUFFLE === 'true';
if (!shuffle) {
// Return a random name if not shuffling
const randomName = names[Math.floor(Math.random() * names.length)];
return {
statusCode: 200,
body: JSON.stringify(randomName),
};
} else {
// Shuffle names and persist the order in memory
if (shuffledNames.length === 0 || currentIndex >= shuffledNames.length) {
shuffledNames = shuffleArray([...names]); // Shuffle a copy of the names array
currentIndex = 0; // Reset index
}
const nameToReturn = shuffledNames[currentIndex];
currentIndex += 1; // Move to the next index
return {
statusCode: 200,
body: JSON.stringify(nameToReturn),
};
}
};
Note
The implementation of the function shuffleArray
is assumed to be available elsewhere in the code.
After pasting the code, deploy the Lambda function and test it to ensure that a random name from the hardcoded list is returned with each invocation.
When tested, the function returns a response similar to:
{
"statusCode": 200,
"body": "\"Douglas\""
}
Creating the API Gateway
Next, create a REST API using API Gateway to integrate with the Lambda function.
- In the AWS API Gateway console, create a new API named “console name picker API.”
- Once a root resource is created, add a new method that integrates with the Lambda function.
- Select “ANY” as the method type to support all HTTP methods, and create a proxy resource using the path parameter
{proxy+}
. This ensures that any path (e.g.,/hello
,/goodbye
) will route to your Lambda function.
- Configure the integration to map the method to your Lambda function.
- Deploy the API by creating a stage (e.g., “dev”). Once deployed, the invoke URL will return a random name when accessed in a browser. Refreshing the URL should yield a new random name for each request.
Although the manual deployment process works, it is time-consuming, prone to human error, and difficult to reproduce. This is where CDKTF proves invaluable.
Automating with CDKTF
CDKTF enables you to share your project as a single script. A simple command like yarn deploy
automates the entire setup.
AWS CLI and Authentication
To configure your AWS account locally (or in any environment outside KodeKloud Labs):
Install the AWS CLI (for example, via Homebrew):
brew install awscli
In the AWS Management Console, navigate to IAM and create a user with command line access. Generate an access key and a secret access key.
Configure the AWS CLI by running:
aws configure
Fill in your access key ID and secret key when prompted. To verify that authentication is working, run:
aws sts get-caller-identity
You should see output similar to:
{ "UserId": "AIDA3FLDW3LPP24HQUEN", "Account": "767397779696", "Arn": "arn:aws:iam::767397779696:user/kk_labs_user_335488" }
When you run CDKTF with the AWS provider, it uses the default profile configured in your AWS CLI.
Setting Up a CDKTF App
Create a basic CDKTF application by replacing the contents of main.ts
with the following code that simply outputs a message:
import { Construct } from 'constructs';
import { App, TerraformStack, TerraformOutput } from 'cdktf';
class MyStack extends TerraformStack {
constructor(scope: Construct, id: string) {
super(scope, id);
// Define resources here
new TerraformOutput(this, 'lets-go', { value: 'lets go!' });
}
}
const app = new App();
new MyStack(app, 'cdktf-name-picker');
app.synth();
Install dependencies and deploy the app by running:
yarn install
yarn deploy
You should see output similar to:
Outputs:
lets-go = "lets go!"
Adding the AWS Provider
To enable AWS resource deployment via CDKTF, add the AWS provider. First, install it by executing:
yarn add @cdktf/provider-aws
Next, update your main.ts
stack as follows:
import { Construct } from 'constructs';
import { App, TerraformStack, TerraformOutput } from 'cdktf';
import { provider } from '@cdktf/provider-aws';
class MyStack extends TerraformStack {
constructor(scope: Construct, id: string) {
super(scope, id);
new provider.AwsProvider(this, 'aws-provider', {
region: 'us-east-1',
});
// Define resources here
new TerraformOutput(this, 'lets-go', { value: 'lets go!' });
}
}
const app = new App();
new MyStack(app, 'cdktf-name-picker');
app.synth();
If you're using KodeKloud Labs, use the US East 1 region; otherwise, choose the region that suits your requirements.
Deploying an AWS IAM Role for Lambda
AWS Lambda functions require an execution role with the appropriate permissions. Deploy an IAM role specifically for the Lambda function by adding the following code. Ensure that you import the necessary modules for IAM:
import * as iamRole from '@cdktf/provider-aws/lib/iam-role';
const lambdaRole = new iamRole.IamRole(this, 'lambda-execution-role', {
name: 'cdktf-name-picker-api-execution-role',
assumeRolePolicy: JSON.stringify({
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: {
Service: 'lambda.amazonaws.com'
},
Action: 'sts:AssumeRole'
}
]
}),
});
After running yarn deploy
, Terraform will display output similar to:
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_iam_role.lambda-execution-role: Creating...
aws_iam_role.lambda-execution-role: Creation complete after 1s [id=cdktf-name-picker-api-execution-role]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
lets-go = "lets go!"
You can also verify the role in the AWS IAM Console.
Recap
In this lesson, we have:
- Defined the problem and set up prerequisites.
- Deployed Arthur’s Name Picker application manually using the AWS Console.
- Configured the AWS CLI and authenticated with AWS.
- Created a basic CDKTF application.
- Added the AWS provider and deployed our first AWS resource (an IAM role).
In the next section, we will continue developing Arthur’s Game Picker app by further defining and deploying the necessary AWS resources using CDKTF.
For more details on AWS deployments and CDKTF, explore the AWS Documentation and Terraform Registry.
Watch Video
Watch video content