Skip to main content

Using Terraform CDK

1. Installing CDK for Terraform

The CDK for Terraform allows you to define infrastructure using familiar programming languages like TypeScript, Python, C#, or Go. It compiles your code into Terraform configuration files.

Language Installation Command Notes
TypeScript npm install -g cdktf Requires Node.js 18+
Python pip install cdktf Requires Python 3.8+
C# dotnet tool install -g cdktf Requires .NET 6+
Go go install github.com/hashicorp/cdktf-cli/cmd/cdktf Requires Go 1.20+

Example: Initialize a CDK Project

cdktf init --template=typescript
Note: The cdktf init command creates a new project directory with boilerplate code and necessary dependencies.

2. Creating CDKTF Projects

Example: Initialize a CDKTF Project

cdktf init --template=typescript --provider-version=5.0.0
Command Description Notes
cdktf init Initialize a new CDKTF project Creates necessary files and configuration
--template Specify the project template Options: typescript, python, csharp, java
--provider-version Set provider version Ensures compatibility with Terraform providers
Note: The cdktf init command generates a cdktf.json configuration file and sets up the project structure for CDKTF.
Warning: Ensure that the provider version specified is compatible with your Terraform version to avoid runtime errors.

3. Defining Infrastructure in Code

Property Description Example
construct Base class for all CDK constructs new Construct(scope, id)
resource Represents a cloud resource in the infrastructure new aws.S3Bucket(this, 'MyBucket')
stack Logical grouping of constructs new Stack(scope, id)

Example: Defining an S3 Bucket

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class MyStack extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    new cdk.aws_s3.Bucket(this, 'MyBucket', {
      bucketName: 'my-unique-bucket-name',
      versioned: true,
    });
  }
}

Example: Using Parameters

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class MyStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new cdk.aws_s3.Bucket(this, 'MyBucket', {
      bucketName: props?.bucketName || 'default-bucket',
      versioned: true,
    });
  }
}
Note: CDK constructs are composable and can be nested to build complex infrastructure.

4. Synthesizing Configuration

When using the Terraform CDK, configuration synthesis involves generating HCL (HashiCorp Configuration Language) code from your high-level programming constructs. This process happens during the synthesis phase, which occurs before deployment.

Aspect Description Details
Synthesis Process How CDK translates code into HCL CDK libraries provide constructs that map to HCL resources. During synthesis, these constructs are translated into HCL configuration files.
Output Format Generated HCL files Generated HCL files are written to the cdktf.out directory by default. These can be used directly with Terraform CLI.
Language Support Supported languages for CDK Currently supports TypeScript, JavaScript, Python, C#, and Go. Each language has its own CDK library (e.g., cdktf, cdk8s).

Example: Synthesizing a Simple Resource

import { App, TerraformStack } from 'cdktf';
import { AwsProvider } from '@cdktf/provider-aws';
import { S3Bucket } from '@cdktf/provider-aws';

const app = new App();
const stack = new TerraformStack(app, 'my-stack');

new AwsProvider(stack, 'aws', {
  region: 'us-west-2'
});

new S3Bucket(stack, 'my-bucket', {
  bucket: 'my-unique-bucket-name'
});

app.synth();
Note: The synth() method generates the HCL files in the cdktf.out directory. These files can then be used with Terraform CLI commands like terraform init, terraform plan, and terraform apply.

Synthesis Workflow

  • Define infrastructure using CDK constructs in your preferred language.
  • Call synth() to generate HCL files.
  • Use the generated HCL with Terraform CLI for deployment.

5. Deploying with CDKTF

Command Description Notes
cdktf deploy Deploys the generated Terraform configuration to the cloud provider Must be run after cdktf synth
cdktf deploy --auto-approve Deploys without requiring manual confirmation Use with caution in production environments
cdktf deploy --target <resource> Deploys only a specific resource or module Allows selective deployment of parts of the infrastructure

Example: Deploying a CDKTF Stack

cdktf deploy
Note: Ensure that all required credentials and permissions are configured before deploying to avoid deployment failures.
Warning: Using --auto-approve can lead to unintended changes in production environments. Always verify the generated Terraform configuration before auto-approving.

6. Using CDKTF Providers

Property Values Description
provider aws, azure, gcp Cloud provider to use with CDKTF
version 5.0.0 Version of the provider to use
alias us-west-1 Alias to use for multiple provider instances

Example: Using AWS Provider

import { Construct } from 'constructs';
import { TerraformStack } from 'cdktf';
import { AwsProvider } from '@cdktf/provider-aws';

class MyStack extends TerraformStack {
  constructor(scope: Construct, name: string) {
    super(scope, name);

    new AwsProvider(this, 'aws', {
      region: 'us-west-2'
    });
  }
}

Example: Using Multiple AWS Regions

import { Construct } from 'constructs';
import { TerraformStack } from 'cdktf';
import { AwsProvider } from '@cdktf/provider-aws';

class MyStack extends TerraformStack {
  constructor(scope: Construct, name: string) {
    super(scope, name);

    new AwsProvider(this, 'aws-west', {
      region: 'us-west-2',
      alias: 'west'
    });

    new AwsProvider(this, 'aws-east', {
      region: 'us-east-1',
      alias: 'east'
    });
  }
}
Note: Ensure that the provider version matches your Terraform version for compatibility.
Warning: Using multiple provider instances can lead to complex state management.

7. Converting HCL to CDKTF

Converting existing HCL (HashiCorp Configuration Language) code to CDKTF (Cloud Development Kit for Terraform) involves translating your infrastructure-as-code definitions from HCL syntax into TypeScript or Python using the CDKTF constructs.

Step Description Action
1 Prepare your HCL code Ensure your HCL files are organized and validated.
2 Install CDKTF CLI Run npm install -g cdktf-cli or brew install cdktf.
3 Initialize CDKTF project Use cdktf init --template typescript or python.
4 Import HCL modules Use cdktf import to convert HCL resources into CDKTF constructs.
5 Review and adjust Manually review generated code to ensure correctness and idiomatic usage.

Example: Converting a simple HCL resource to CDKTF

resource "aws_s3_bucket" "my_bucket" {
  bucket = "my-unique-bucket-name"
  acl    = "private"
}
import { Construct } from "constructs";
import { TerraformStack } from "cdktf";
import { S3Bucket } from "@cdktf/provider-aws/lib/s3-bucket";

export class MyStack extends TerraformStack {
  constructor(scope: Construct, name: string) {
    super(scope, name);

    new S3Bucket(this, "my_bucket", {
      bucket: "my-unique-bucket-name",
      acl: "private"
    });
  }
}
Note: The CDKTF CLI does not fully automate HCL to CDKTF conversion. You must manually adjust the generated code to ensure it aligns with your project's structure and best practices.

8. Managing CDKTF State

Property Description Default Value Notes
backend Defines the backend to use for storing Terraform state local Can be local, s3, azurerm, gcs, or custom
key Unique identifier for the state file in the backend terraform.tfstate Used to distinguish multiple state files in the same backend
workspace Name of the workspace to use for state management default Allows multiple environments to be managed with the same configuration

Example: Setting up S3 backend for CDKTF

import { App, TerraformStack } from "cdktf";
import { S3Backend } from "cdktf/lib/backends";

const app = new App();
const stack = new TerraformStack(app, "example");

new S3Backend(stack, {
  bucket: "my-terraform-state-bucket",
  key: "cdktf.tfstate",
  region: "us-west-2"
});

app.synth();
Note: When using a remote backend like S3, ensure that the IAM role or credentials used have appropriate permissions to read and write state files.
Warning: Changing the backend configuration after state has been initialized can lead to data loss or corruption. Always backup your current state before making changes.

9. Testing CDKTF Code

Testing CDKTF code involves verifying that your infrastructure as code definitions behave as expected. Terraform provides several mechanisms to test your CDKTF modules and constructs.

Testing Approach Description Tools/Methods
Unit Testing Testing individual components or modules in isolation. Use cdktf with testing frameworks like Jest or Mocha.
Integration Testing Testing how components interact with each other or external systems. Use cdktf with real AWS/GCP/Azure resources via test stacks.
Acceptance Testing Validating that the infrastructure meets business requirements. Use cdktf with real environments or mocks to simulate infrastructure behavior.

Example: Unit Testing with Jest

import { Testing } from "cdktf";
import { App } from "cdktf";

const app = new App();
const stack = Testing.assertions("test-stack", {
  // Example assertion logic
});

// Jest test case
describe("Test Stack", () => {
  it("should have a valid configuration", () => {
    expect(stack).toBeDefined();
  });
});
Note: CDKTF testing is still evolving, and the ecosystem around it is growing. Ensure you're using the latest version of cdktf for best support.

Testing Best Practices

  • Use cdktf synth to generate Terraform HCL before running tests.
  • Write tests for all major constructs and modules in your CDKTF project.
  • Use mocks or test stacks to isolate components during unit tests.
  • Integrate testing into your CI/CD pipeline for automated validation.

10. Integrating CDKTF with CI/CD

Example: GitHub Actions Workflow

name: CDKTF CI/CD
on:
  push:
    branches: [ main ]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"
      - name: Install CDKTF
        run: npm install -g cdktf-cli
      - name: Deploy
        run: cdktf deploy --auto-approve
        env:
          TF_TOKEN: ${{ secrets.TF_TOKEN }}
Step Description Notes
Checkout Code Fetches the repository code Required for all CI/CD pipelines
Setup Node.js Installs Node.js runtime Version must match local development
Install CDKTF Installs the CDKTF CLI Use latest stable version
Deploy Applies the infrastructure Requires Terraform Cloud token
Note: Ensure TF_TOKEN is set in repository secrets for Terraform Cloud integration.

Best Practices

  • Use cdktf validate before deployment to catch errors early
  • Enable --auto-approve in CI only for trusted environments
  • Store sensitive values like TF_TOKEN in secure vaults or CI/CD secrets
  • Use cdktf diff in pre-deployment checks to review changes

Was this article helpful?