# terraform plan: посмотреть, что Terraform собирается сделать _Основы Terraform · TerraformLab Knowledge Base_ **TL;DR:** plan, это сухая прогонка: Terraform читает ваш HCL, читает state, и показывает diff между ними. Ничего не меняет в облаке. Главный инструмент, чтобы не сломать прод по ошибке. ## Зачем нужен plan `terraform plan`, это **примерка**. Вы пишете HCL: «хочу один бакет с тегами». Terraform смотрит, что уже создано (это записано в state-файле), и показывает разницу: «нужно создать один новый бакет, изменений и удалений нет». Главное: **plan ничего не меняет**. Он не звонит в AWS с командой «создай». Он только смотрит и сравнивает. Это безопасная команда, её можно запускать сколько угодно раз. ## Что показывает plan Допустим, вы написали: ```hcl resource "aws_s3_bucket" "demo" { bucket = "my-bucket-12345" tags = { Owner = "student" } } ``` И запустили `terraform plan`. Вывод примерно такой: ``` Terraform will perform the following actions: # aws_s3_bucket.demo will be created + resource "aws_s3_bucket" "demo" { + bucket = "my-bucket-12345" + id = (known after apply) + tags = { + "Owner" = "student" } } Plan: 1 to add, 0 to change, 0 to destroy. ``` Разбор: - **`+ resource ...`**, этот ресурс будет создан. Знак `+` = добавить. - **`+ bucket = "my-bucket-12345"`**, значение, которое Terraform отправит в API. - **`+ id = (known after apply)`**, атрибут появится только после создания, сейчас его не знаем. - **`Plan: 1 to add, 0 to change, 0 to destroy`**, итоговая сводка. Это самая важная строчка. ## Знаки в diff'е (запомните) | Знак | Что значит | |---|---| | `+` | Создать новый ресурс или атрибут | | `-` | Удалить ресурс или атрибут | | `~` | Изменить значение (можно сделать без пересоздания) | | `-/+` | Удалить и создать заново (force replacement) | Самый опасный, `-/+`. Он значит «ресурс нужно пересоздать с нуля». Если это база данных, данные пропадут. Если EC2, потеряете IP-адрес. Всегда вчитывайтесь в строки с `-/+`. ## Exit code: 0, 1, 2 По умолчанию `terraform plan` всегда возвращает exit code 0, даже если есть изменения. Это удобно для CI: команда не падает. Но если запустить с флагом `-detailed-exitcode`, появляется новая логика: - `0`, изменений нет, state == HCL. **«No changes»**. - `1`, ошибка (синтаксис, провайдер не отвечает, токен невалиден). - `2`, план есть, изменения требуются. ```bash terraform plan -detailed-exitcode echo $? # 0, 1 или 2 ``` Это незаменимо в скриптах: «если есть drift, пришли мне алерт». ## Сохранение плана в файл `plan` можно сохранить и потом применить ровно его (без пересчёта): ```bash terraform plan -out=tfplan.bin # сохранили terraform apply tfplan.bin # применяем именно этот план ``` Зачем так делают: - В CI: ревьюер видит plan в PR, мержит, и apply применяет ровно то, что было показано. Между показом и применением никакой код не успеет «подсунуться». - **`tfplan.bin` может содержать секреты** (если они в state). Не коммитьте его в git. ## Подводные камни - **«No changes», это инвариант, к которому надо стремиться после apply.** Если сразу после `apply` повторный `plan` показывает изменения, значит, у вас drift (что-то изменилось вне Terraform), или ваш HCL не отражает реальность. Это плохой признак. - **Plan читает state, а не реальный AWS.** Если кто-то руками удалил бакет в консоли, plan этого не заметит, пока не сделаете `terraform refresh` или `terraform plan -refresh=true` (это default, но иногда отключают). См. [tf-state](/terraform/kb/tf-state.md). - **Plan может выполняться долго.** На больших проектах (тысячи ресурсов) plan может занимать минуты. Terraform опрашивает облако про каждый. Это нормально. Если очень больно, `-target=resource.name` для точечного плана. - **Plan не предсказывает всё.** Некоторые атрибуты вычисляются на стороне облака. Plan покажет `(known after apply)`, это нормально, это не «секрет», просто значение появится после создания. - **`-target` использовать редко.** Это «костыль для непредвиденных ситуаций». Регулярное использование `-target`, признак, что ваш HCL неправильно структурирован. ## Команды ```bash terraform plan ``` Базовый запуск: показать diff между HCL и state. ```bash terraform plan -detailed-exitcode ``` Exit 0: нет изменений; 1: ошибка; 2, есть изменения. Для CI-скриптов. ```bash terraform plan -out=tfplan.bin ``` Сохранить план в файл: чтобы apply применил ровно его. ```bash terraform plan -no-color ``` Без ANSI-цветов: для логов в CI или сравнения diff'ов. ```bash terraform plan -target=aws_s3_bucket.demo ``` Точечный план только для одного ресурса. Использовать редко. ## См. также - [terraform init: первая команда в любом проекте](/terraform/kb/tf-init.md) - [terraform apply: применить план в реальном облаке](/terraform/kb/tf-apply.md) - [terraform destroy: снести всё, что было создано](/terraform/kb/tf-destroy.md) - [State: память Terraform о созданном](/terraform/kb/tf-state.md)