Hey HN! I built tf2cdk - a CLI that converts Terraform configurations to native AWS CDK code. GitHub: https://github.com/jtaylortech/tf2cdk https://github.com/jtaylortech/tf2cdk Important: This is NOT cdktf cdktf (CDK for Terraform): cdktf Write CDK code that generates Terraform Outputs HCL, uses Terraform state For teams who want CDK's programming model with Terraform's engine Write CDK code that generates Terraform Outputs HCL, uses Terraform state For teams who want CDK's programming model with Terraform's engine tf2cdk (this project): tf2cdk Converts existing Terraform TO native CDK Outputs CDK code, uses CloudFormation stacks For teams migrating OFF Terraform entirely Converts existing Terraform TO native CDK Outputs CDK code, uses CloudFormation stacks For teams migrating OFF Terraform entirely Different problems. Not competitors. The Problem I've worked with multiple organizations migrating to AWS Control Tower. Every time, same issue: Control Tower requires CloudFormation. Existing infrastructure is Terraform. Manual conversion takes 2-4 months for large codebases. This also happens with: Landing Zone Accelerator (LZA) - CloudFormation only AWS Service Catalog - Native CloudFormation integration Terraform licensing concerns - Teams want to eliminate Terraform entirely Landing Zone Accelerator (LZA) - CloudFormation only AWS Service Catalog - Native CloudFormation integration Terraform licensing concerns - Teams want to eliminate Terraform entirely How It Works tf2cdk is a Python CLI that: Parses HCL - Uses python-hcl2 to parse Terraform files Maps resources - 30+ Terraform resources → CDK constructs Generates code - Idiomatic TypeScript or Python Validates - Type-safe with comprehensive error handling Parses HCL - Uses python-hcl2 to parse Terraform files Parses HCL Maps resources - 30+ Terraform resources → CDK constructs Maps resources Generates code - Idiomatic TypeScript or Python Generates code Validates - Type-safe with comprehensive error handling Validates tf2cdk convert ./terraform --output ./cdk-app --language typescript tf2cdk convert ./terraform --output ./cdk-app --language typescript All generated code lives in the output directory. You can inspect/modify it. Example Input (Terraform): Input (Terraform): resource "aws_s3_bucket" "data" { bucket = "my-data-bucket" tags = { Environment = "production" } } resource "aws_s3_bucket_versioning" "data" { bucket = aws_s3_bucket.data.id versioning_configuration { status = "Enabled" } } resource "aws_s3_bucket" "data" { bucket = "my-data-bucket" tags = { Environment = "production" } } resource "aws_s3_bucket_versioning" "data" { bucket = aws_s3_bucket.data.id versioning_configuration { status = "Enabled" } } Output (CDK TypeScript): Output (CDK TypeScript): import * as cdk from 'aws-cdk-lib'; import * as s3 from 'aws-cdk-lib/aws-s3'; export class InfrastructureStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const data = new s3.Bucket(this, 'Data', { bucketName: 'my-data-bucket', versioned: true, tags: { Environment: 'production' }, }); } } import * as cdk from 'aws-cdk-lib'; import * as s3 from 'aws-cdk-lib/aws-s3'; export class InfrastructureStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const data = new s3.Bucket(this, 'Data', { bucketName: 'my-data-bucket', versioned: true, tags: { Environment: 'production' }, }); } } Notice how it: Merges aws_s3_bucket_versioning into the bucket (CDK pattern) Converts snake_case to camelCase Generates clean, idiomatic code Merges aws_s3_bucket_versioning into the bucket (CDK pattern) aws_s3_bucket_versioning Converts snake_case to camelCase Generates clean, idiomatic code Technical Details Architecture: Architecture: Terraform HCL ↓ (python-hcl2) Parsed Config ↓ (Resource Mapper) CDK Model ↓ (Code Generator) TypeScript/Python Terraform HCL ↓ (python-hcl2) Parsed Config ↓ (Resource Mapper) CDK Model ↓ (Code Generator) TypeScript/Python Resource Mappings: Resource Mappings: RESOURCE_MAPPINGS = { 'aws_s3_bucket': { 'cdk_class': 's3.Bucket', 'module': 'aws-cdk-lib/aws-s3', 'props': {'bucket': 'bucketName', 'tags': 'tags'} }, # 30+ more... } RESOURCE_MAPPINGS = { 'aws_s3_bucket': { 'cdk_class': 's3.Bucket', 'module': 'aws-cdk-lib/aws-s3', 'props': {'bucket': 'bucketName', 'tags': 'tags'} }, # 30+ more... } Error Handling: Error Handling: Validates source files exist Catches HCL parse errors with helpful tips Warns about unsupported resources Shows conversion progress Proper exit codes for automation Validates source files exist Catches HCL parse errors with helpful tips Warns about unsupported resources Shows conversion progress Proper exit codes for automation Testing: Testing: 28 tests (parser, converter, generator, CLI, edge cases) Tests empty configs, unsupported resources, complex props CLI integration tests for all commands All tests passing 28 tests (parser, converter, generator, CLI, edge cases) Tests empty configs, unsupported resources, complex props CLI integration tests for all commands All tests passing Supported Resources (30+) Compute: EC2, Lambda, ECS, Auto Scaling Storage: S3, EBS, EFS Database: RDS, DynamoDB, ElastiCache Network: VPC, Subnet, Security Groups, Route53, ALB/NLB Security: IAM, KMS, Secrets Manager Monitoring: CloudWatch, SNS, SQS Compute: Storage: Database: Network: Security: Monitoring: Community contributions welcome for additional resources. Special Patterns # Control Tower account factory structure tf2cdk convert ./terraform --pattern control-tower # Landing Zone Accelerator format tf2cdk convert ./terraform --pattern lza # GovCloud compliance annotations tf2cdk convert ./terraform --pattern govcloud # Control Tower account factory structure tf2cdk convert ./terraform --pattern control-tower # Landing Zone Accelerator format tf2cdk convert ./terraform --pattern lza # GovCloud compliance annotations tf2cdk convert ./terraform --pattern govcloud Why Open Source? Terraform→CDK conversion is a one-time migration problem. You need it once, then you're done. one-time migration problem Making it free and open source: Maximizes adoption Gets community contributions (more resource mappings) Helps the entire AWS community Builds credibility Maximizes adoption Gets community contributions (more resource mappings) Helps the entire AWS community Builds credibility For large migrations needing implementation services, those are available separately. But the tool itself is free forever (MIT License). Limitations Complex Terraform expressions may need manual adjustment Custom providers need manual mapping configuration State migration is guided, not fully automated Some Terraform-specific features (provisioners) have no CDK equivalent Complex Terraform expressions may need manual adjustment Custom providers need manual mapping configuration State migration is guided, not fully automated Some Terraform-specific features (provisioners) have no CDK equivalent Roadmap v0.1.0 (current): 30+ resources, TypeScript/Python, basic patterns v0.2.0: 50+ resources, state import planning, more patterns v0.3.0: 100+ resources, module conversion, advanced expressions v1.0.0: Comprehensive resource coverage, GUI (optional) v0.1.0 (current): v0.2.0: v0.3.0: v1.0.0: Try It # Homebrew brew tap jtaylortech/tf2cdk brew install tf2cdk # pip pip install tf2cdk # Convert tf2cdk convert ./terraform --output ./cdk-app --dry-run # Homebrew brew tap jtaylortech/tf2cdk brew install tf2cdk # pip pip install tf2cdk # Convert tf2cdk convert ./terraform --output ./cdk-app --dry-run Feedback Wanted What Terraform resources are you using that aren't supported? What patterns would help (multi-account, multi-region, etc.)? What's your Terraform→CDK migration pain point? Documentation gaps? What Terraform resources are you using that aren't supported? What patterns would help (multi-account, multi-region, etc.)? What's your Terraform→CDK migration pain point? Documentation gaps? All code is on GitHub, MIT licensed. Issues and PRs welcome. Related: If you're looking for CDK→Terraform (opposite direction), check out cdktf from HashiCorp. Different use case, both tools are useful. Related: