Having not done much infrastructure before, writing Terraform seemed a pretty daunting task. Learning HCL and its nuances in a declarative manner and configuring it all for different environments is a bit of a learning curve. Creating the same in code using an imperative style seems a better path for a developer.
Setting Up
This is a simple example of using Terraforms cloud development kit (CDKTF) to create a Lambda function in AWS in Typescript.
To get started, follow their installation setup here.
Create a new project:
mkdir cdktf-lambda
cd cdktf-lambda
cdktf init --template="typescript" --providers="aws@~>4.0"
Follow the cmd prompts, and lastly:
npm i @cdktf/provider-archive@5.0.1
At the time, the dependencies were:
"dependencies": { "@cdktf/provider-archive": "^5.0.1", "@cdktf/provider-aws": "13.0.0", "cdktf": "^0.15.5", "constructs": "^10.1.310" }, "devDependencies": { "@types/jest": "^29.5.1", "@types/node": "^20.1.0", "jest": "^29.5.0", "ts-jest": "^29.1.0", "ts-node": "^10.9.1", "typescript": "^5.0.4" }
The directory structure will have been created like so:
The init
command provides some boilerplate code to get up and running with.
The main.ts
is the central file from which the code will run, and this is known as a TerraformStack. In this stack is where all the IaC will be placed.
Let’s Go
CDKTF has the concept of providers, which are Terraform wrappers for third-party APIs such as AWS. We need to add one for AWS and one to handle the lambda archive bindings:
There should be enough here to do a sanity check run:
cdktf diff
At this stage, it error’d and the tsconfig file requires the following to be added:"ignoreDeprecations": "5.0"
A successful run should show:
cdktf-lambda No changes. Your infrastructure matches the configuration.
Roles
Next, add an IAM role and a policy for the Lambda:
const role = new IamRole(this, this.prefix + "iam_for_lambda", { assumeRolePolicy: new DataAwsIamPolicyDocument(this, this.prefix + "assume_role", { statement: [ { actions: [ "sts:AssumeRole" ], effect: "Allow", principals: [ { identifiers: ["lambda.amazonaws.com"], type: "Service", }, ], } ], }).json, name: this.prefix + "iam_for_lambda", }); new IamRolePolicy(this, this.prefix + "iamPolicy", { name: this.prefix + `iamPolicy-state`, role: role.id, policy: new DataAwsIamPolicyDocument(this, this.prefix + "iamPolicyDoc", { version: "2012-10-17", statement: [ { effect: "Allow", actions: ["logs:CreateLogGroup"], resources: [`arn:aws:logs:${this.region}:${this.accountId}:*`] }, { effect: "Allow", actions: [ "logs:CreateLogStream", "logs:PutLogEvents" ], resources: [ `arn:aws:logs:${this.region}:${this.accountId}:log-group:/aws/lambda/dale-test-manual:*` ] } ] }).json });
Lambda
We’ll create a simple form and place index.html
and index.js
into the dist
folder:
CDKTF Lambda Demo
{formResults} {debug}