# CDKTF, Terraform на TypeScript/Python _Advanced · TerraformLab Knowledge Base_ **TL;DR:** CDKTF, Terraform на TypeScript/Python/Go/Java/C#. На выходе стандартный HCL + tfstate. Плюсы: типы, autocomplete, циклы и классы. Минусы: ещё одна абстракция, debug сложнее, не все фичи Terraform покрыты 1:1. Оправдан когда нужна программируемая генерация HCL (N stack'ов из CSV, например). ## Что это CDKTF, генератор HCL из кода. Пишешь на одном из языков: - TypeScript / JavaScript (основной) - Python - Java - C# - Go Запускаешь `cdktf synth`, на выходе папка `cdktf.out/stacks//` с обычным HCL (`cdk.tf.json`). Дальше, `terraform init && plan` как обычно (или `cdktf deploy`, который делает то же самое из CDKTF). Идея, Terraform-провайдеры остаются те же, state остаётся terraform-state, но **HCL пишется кодом**. ## Минимальный пример (TypeScript) ```bash cdktf init --template=typescript --local ``` Генерится `main.ts`: ```typescript import { App, TerraformStack } from "cdktf"; import { Construct } from "constructs"; import { AwsProvider } from "./.gen/providers/aws/provider"; import { S3Bucket } from "./.gen/providers/aws/s3-bucket"; class MyStack extends TerraformStack { constructor(scope: Construct, name: string) { super(scope, name); new AwsProvider(this, "aws", { region: "us-east-1" }); new S3Bucket(this, "logs", { bucket: "linuxlab-cdktf-logs", tags: { ManagedBy: "cdktf" }, }); } } const app = new App(); new MyStack(app, "main"); app.synth(); ``` Запуск: ```bash cdktf get # подтягивает type-bindings для провайдеров cdktf synth # генерит HCL в cdktf.out/ cdktf deploy main # apply ``` ## Что синтезируется `cdktf.out/stacks/main/cdk.tf.json`: ```json { "terraform": { "required_providers": {"aws": {...}} }, "provider": { "aws": [{"region": "us-east-1"}] }, "resource": { "aws_s3_bucket": { "logs": { "bucket": "linuxlab-cdktf-logs", "tags": {"ManagedBy": "cdktf"} } } } } ``` Это обычный JSON-HCL. Никаких CDKTF-специфик в облаке. ## Когда CDKTF оправдан ### Программируемая генерация 100 одинаковых stack'ов из CSV: ```typescript const tenants = require("./tenants.json"); tenants.forEach((tenant: any) => { new TenantStack(app, `tenant-${tenant.id}`, { name: tenant.name, tier: tenant.tier, }); }); ``` В HCL это была бы куча `terraform.tfvars` или `for_each`, но без типов и без if'ов на бизнес-логике. ### Сложная условная логика ```typescript if (config.env === "prod" && config.region.startsWith("eu-")) { new GDPRComplianceModule(this, "gdpr", { ... }); } ``` В HCL, count = ... ? 1 : 0 с кучей условий. На TypeScript, читается. ### Переиспользование через классы ```typescript class AuditedBucket extends Construct { constructor(scope: Construct, name: string, props: AuditedBucketProps) { super(scope, name); new S3Bucket(this, "bucket", { /* ... */ }); new S3BucketVersioningA(this, "versioning", { /* ... */ }); new S3BucketPublicAccessBlock(this, "pab", { /* ... */ }); } } new AuditedBucket(this, "logs", { name: "audit-logs" }); ``` Это аналог Terraform-модуля, но с типами и наследованием. ## Когда CDKTF, НЕ оправдан ### Маленький проект Один stack, 50 ресурсов, без сложной логики, нативный HCL понятнее и короче. CDKTF добавляет step'ы (init, get, synth, deploy) и build-зависимости (node_modules, 500 MB+). ### Команда не знает TypeScript/Python Reviewer ревьюит и HCL, и TypeScript. Если последнего никто не знает плохая идея. Reviewing 200-line `.ts` сложнее, чем `.tf`. ### Хочешь использовать community-modules Большинство Terraform Registry modules написаны на HCL. Использовать их из CDKTF можно (`TerraformHclModule`), но workflow менее естественный. ## Структура проекта ``` my-cdktf/ ├── main.ts # entrypoint ├── stacks/ │ ├── network.ts │ ├── compute.ts │ └── data.ts ├── constructs/ │ ├── audited-bucket.ts │ └── vpc-with-flow-logs.ts ├── cdktf.json # язык, providers, build ├── package.json └── cdktf.out/ # generated HCL (gitignore) ``` В `cdktf.json`: ```json { "language": "typescript", "app": "npx ts-node main.ts", "terraformProviders": ["aws@~> 5.60", "random@~> 3.6"], "terraformModules": [], "context": {} } ``` ## Tests Тесты, обычные Jest/pytest. CDKTF предоставляет helpers: ```typescript import { Testing } from "cdktf"; test("bucket has correct name", () => { const synth = Testing.synthScope((scope) => { new MyStack(scope, "test"); }); expect(synth).toHaveResourceWithProperties(S3Bucket, { bucket: "linuxlab-cdktf-logs", }); }); ``` Это assertion на сгенерированный JSON. Быстро, никакого облака. ## Подводные камни - **`cdktf get` нужен после смены провайдеров.** Type-bindings генерятся локально; добавил новый provider в `cdktf.json` → `cdktf get`. Без него TypeScript не видит типы. - **`node_modules/` тяжёлый.** 500-1500 MB на средний проект. В Docker билде CI медленный без `npm ci --omit=dev`. - **HCL-generated читать тяжело.** Синтезированный JSON неотформатирован под человека; debug через `cdktf synth && cat cdktf.out/.../cdk.tf.json | jq`, не самый приятный. - **State files те же.** CDKTF не создаёт собственный state; использует `terraform.tfstate`. Это плюс (миграция назад в HCL возможна), но означает что remote backend настраивается так же. - **Terraform-фичи не на 1:1.** `moved` / `removed` / `import` блоки в CDKTF поддерживаются, но менее идиоматично. Сложные `dynamic` блоки могут потребовать `escapeHatch`. - **Не путать с AWS CDK.** AWS CDK генерит CloudFormation; CDKTF генерит Terraform. Похожий синтаксис, разный backend. - **Performance:** `cdktf synth` на больших проектах, секунды-минуты. На каждом CI-run перегенерация. Для 1000+ ресурсов делается кэширование generated-HCL. ## Команды ```bash cdktf init --template=typescript --local ``` Скелет проекта на TypeScript с local-backend. ```bash cdktf get ``` Подтянуть type-bindings для провайдеров из cdktf.json. ```bash cdktf synth ``` Сгенерировать HCL в cdktf.out/. Не делает apply. ```bash cdktf deploy ``` synth + terraform apply одной командой. ```bash cdktf diff ``` synth + terraform plan. ## См. также - [Terragrunt, DRY-обёртка над Terraform](/terraform/kb/tf-terragrunt.md) - [Свой Terraform-провайдер, Plugin Framework](/terraform/kb/tf-provider-development.md) - [Terraform Stacks, нативная multi-stack оркестрация](/terraform/kb/tf-stacks.md)