CDKTF Cheat Sheet
Overview
CDKTF (Cloud Development Kit for Terraform) allows developers to define infrastructure using familiar programming languages like TypeScript, Python, Go, Java, and C# instead of HashiCorp Configuration Language (HCL). It synthesizes standard Terraform JSON configuration, leveraging the full Terraform ecosystem of providers and modules while offering the benefits of general-purpose programming languages.
CDKTF provides constructs that map to Terraform resources, data sources, and modules. Developers can use loops, conditionals, functions, classes, and other language features to create reusable infrastructure patterns. The tool integrates with the Terraform CLI for planning and applying changes.
Installation
# Install via npm (requires Node.js)
npm install -g cdktf-cli
# Verify
cdktf --version
# Prerequisites: Terraform CLI
brew install terraform # macOS
# or
sudo apt install terraform # Linux
Core Commands
| Command | Description |
|---|---|
cdktf init | Initialize a new CDKTF project |
cdktf synth | Synthesize Terraform configuration |
cdktf plan | Plan infrastructure changes |
cdktf deploy | Apply infrastructure changes |
cdktf destroy | Destroy infrastructure |
cdktf diff | Show diff of changes |
cdktf output | Show stack outputs |
cdktf provider add | Add a Terraform provider |
cdktf get | Generate provider bindings |
cdktf convert | Convert HCL to CDKTF code |
Project Setup
Initialize Project
# Interactive init
cdktf init
# TypeScript project
cdktf init --template=typescript --local
# Python project
cdktf init --template=python --local
# Go project
cdktf init --template=go --local
# Add providers
cdktf provider add aws
cdktf provider add google
cdktf provider add azurerm
# Generate provider bindings
cdktf get
TypeScript Usage
Basic Infrastructure
import { Construct } from 'constructs';
import { App, TerraformStack, TerraformOutput } from 'cdktf';
import { AwsProvider } from '@cdktf/provider-aws/lib/provider';
import { Instance } from '@cdktf/provider-aws/lib/instance';
import { Vpc } from '@cdktf/provider-aws/lib/vpc';
import { Subnet } from '@cdktf/provider-aws/lib/subnet';
class MyStack extends TerraformStack {
constructor(scope: Construct, id: string) {
super(scope, id);
new AwsProvider(this, 'AWS', { region: 'us-east-1' });
const vpc = new Vpc(this, 'vpc', {
cidrBlock: '10.0.0.0/16',
tags: { Name: 'my-vpc' },
});
const subnet = new Subnet(this, 'subnet', {
vpcId: vpc.id,
cidrBlock: '10.0.1.0/24',
availabilityZone: 'us-east-1a',
});
const instance = new Instance(this, 'web', {
ami: 'ami-0c55b159cbfafe1f0',
instanceType: 't3.micro',
subnetId: subnet.id,
tags: { Name: 'web-server' },
});
new TerraformOutput(this, 'public_ip', {
value: instance.publicIp,
});
}
}
const app = new App();
new MyStack(app, 'my-infrastructure');
app.synth();
Reusable Constructs
import { Construct } from 'constructs';
import { S3Bucket } from '@cdktf/provider-aws/lib/s3-bucket';
import { S3BucketVersioningA } from '@cdktf/provider-aws/lib/s3-bucket-versioning';
class SecureBucket extends Construct {
public readonly bucket: S3Bucket;
constructor(scope: Construct, id: string, props: { name: string }) {
super(scope, id);
this.bucket = new S3Bucket(this, 'bucket', {
bucket: props.name,
tags: { ManagedBy: 'cdktf' },
});
new S3BucketVersioningA(this, 'versioning', {
bucket: this.bucket.id,
versioningConfiguration: { status: 'Enabled' },
});
}
}
Python Usage
from constructs import Construct
from cdktf import App, TerraformStack, TerraformOutput
from cdktf_cdktf_provider_aws.provider import AwsProvider
from cdktf_cdktf_provider_aws.instance import Instance
from cdktf_cdktf_provider_aws.vpc import Vpc
class MyStack(TerraformStack):
def __init__(self, scope: Construct, id: str):
super().__init__(scope, id)
AwsProvider(self, "AWS", region="us-east-1")
vpc = Vpc(self, "vpc",
cidr_block="10.0.0.0/16",
tags={"Name": "my-vpc"})
instance = Instance(self, "web",
ami="ami-0c55b159cbfafe1f0",
instance_type="t3.micro",
tags={"Name": "web-server"})
TerraformOutput(self, "public_ip",
value=instance.public_ip)
app = App()
MyStack(app, "my-infrastructure")
app.synth()
Configuration
cdktf.json
{
"language": "typescript",
"app": "npx ts-node main.ts",
"projectId": "abc123",
"sendCrashReports": false,
"terraformProviders": [
"hashicorp/aws@~> 5.0",
"hashicorp/google@~> 5.0"
],
"terraformModules": [
{
"name": "vpc",
"source": "terraform-aws-modules/vpc/aws",
"version": "5.4.0"
}
],
"context": {
"excludeStackIdFromLogicalIds": true
}
}
Multiple Stacks
const app = new App();
new NetworkStack(app, 'network');
new DatabaseStack(app, 'database');
new AppStack(app, 'application');
app.synth();
# Deploy specific stack
cdktf deploy network
cdktf deploy database application
# Deploy all
cdktf deploy '*'
Advanced Usage
Using Terraform Modules
import { TerraformHclModule } from 'cdktf';
new TerraformHclModule(this, 'vpc', {
source: 'terraform-aws-modules/vpc/aws',
version: '5.4.0',
variables: {
name: 'my-vpc',
cidr: '10.0.0.0/16',
azs: ['us-east-1a', 'us-east-1b'],
private_subnets: ['10.0.1.0/24', '10.0.2.0/24'],
public_subnets: ['10.0.101.0/24', '10.0.102.0/24'],
enable_nat_gateway: true,
},
});
Remote State Backend
import { S3Backend } from 'cdktf';
new S3Backend(this, {
bucket: 'my-terraform-state',
key: 'cdktf/terraform.tfstate',
region: 'us-east-1',
dynamodbTable: 'terraform-locks',
encrypt: true,
});
Convert HCL to CDKTF
# Convert existing HCL to TypeScript
cdktf convert --language typescript < main.tf
# Convert to Python
cdktf convert --language python < main.tf
Iterators and Loops
import { TerraformIterator } from 'cdktf';
const environments = ['dev', 'staging', 'prod'];
const iterator = TerraformIterator.fromList(environments);
new S3Bucket(this, 'buckets', {
forEach: iterator,
bucket: `my-app-${iterator.value}`,
tags: { Environment: iterator.value },
});
Troubleshooting
| Issue | Solution |
|---|---|
| Provider bindings not found | Run cdktf get after adding providers |
| Synth fails | Check TypeScript/Python syntax; run cdktf synth --debug |
| State conflict | Configure remote backend before deploying |
| Import not resolving | Check cdktf.json provider versions |
| Circular dependency | Restructure stacks; use cross-stack references |
| Deploy timeout | Check Terraform provider for slow resources |
# Debug synthesis
cdktf synth --debug
# View generated Terraform JSON
cat cdktf.out/stacks/my-stack/cdk.tf.json | jq .
# Plan without deploying
cdktf plan
# Show outputs
cdktf output
# Destroy infrastructure
cdktf destroy