# terraform validate: проверка HCL без облака _Workflow · TerraformLab Knowledge Base_ **TL;DR:** `terraform validate` проверяет HCL на синтаксис и базовую логику: неизвестные аргументы, неправильные типы, ссылки на несуществующие ресурсы. Не ходит в облако, не трогает state: быстрая проверка. В CI запускается после `init -backend=false` и перед `plan`. ## Что делает validate `terraform validate` отвечает на простой вопрос: **скомпилируется ли ваш HCL вообще, если бы его попытались выполнить?** Без обращения к AWS, без чтения state, без скачивания provider'ов (если они уже скачаны). Конкретно validate ловит: - Битый синтаксис HCL: незакрытая скобка, потерянная кавычка. - Неизвестные аргументы: `bucket_name` вместо `bucket` у `aws_s3_bucket`. - Неправильные типы: `count = "три"` (нужно число). - Ссылки на несуществующие ресурсы/переменные/locals. - Циклы в зависимостях (cycle detected). - Неправильную сигнатуру функций: `format()` без аргументов. Что validate **не** ловит: - Что бакет с таким именем уже занят (это plan/apply). - Что у тебя нет прав в AWS (это plan/apply). - Что drift в state (это refresh/plan). - Что результат `data` будет пустым. ## Базовое использование ```bash cd ~/myproject terraform init -backend=false # один раз, скачать provider terraform validate ``` Успех: ``` Success! The configuration is valid. ``` Ошибка: ``` Error: Unsupported argument on main.tf line 5, in resource "aws_s3_bucket" "demo": 5: bucket_name = "my-bucket" An argument named "bucket_name" is not expected here. Did you mean "bucket"? ``` Заметьте. Terraform даёт **подсказку** через "Did you mean". Это работает на похожих именах: `bucket_name` → `bucket`, `tag` → `tags`. ## Зачем нужен init -backend=false Чтобы валидировать, нужны provider'ы, без них Terraform не знает схемы ресурсов. Но `terraform init` без флагов попытается настроить backend (если он remote, пойдёт в S3, спросит credentials). В CI на каждом PR это не нужно. Поэтому: ```bash terraform init -backend=false -input=false terraform validate ``` - `-backend=false`, не настраивать backend, не подключаться к remote state. - `-input=false`, не задавать интерактивных вопросов (CI ничего не введёт). Это типичный паттерн для PR-ревью: «проверим что HCL валиден, без доступа к prod-state». ## Машинно-читаемый вывод Для IDE-интеграций и автоматизации есть `-json`: ```bash terraform validate -json ``` Вывод: ```json { "format_version": "1.0", "valid": false, "error_count": 1, "warning_count": 0, "diagnostics": [ { "severity": "error", "summary": "Unsupported argument", "detail": "An argument named \"bucket_name\" is not expected here.", "range": { "filename": "main.tf", "start": {"line": 5, "column": 3}, "end": {"line": 5, "column": 14} } } ] } ``` Это парсится в любом IDE и подсвечивается прямо в редакторе. Все Terraform-плагины (VS Code, JetBrains) под капотом гоняют этот же JSON. ## Чем validate отличается от plan | | validate | plan | |---|---|---| | Ходит в облако | нет | да (refresh) | | Читает state | нет | да | | Скачивает provider | да (через init) | да | | Скорость | секунда | от секунд до минут | | Ловит «неправильно написано» | да | да | | Ловит «такого ресурса нет в облаке» | нет | да | | Можно ли запустить в PR без AWS-credentials | да | нет | **Правило большого пальца:** validate, на каждое сохранение в IDE. Plan, на каждый PR (с credentials). ## Подводные камни - **Validate требует `init` хотя бы раз.** Без `.terraform/providers/` в директории validate не знает схемы ресурсов и упадёт с «provider not configured». В свежей CI-сборке нужен `init -backend=false` перед каждым validate. - **Validate проверяет один root-module.** Если в репозитории `environments/prod/`, `environments/staging/`. Нужно валидировать каждый отдельно. Один общий validate из корня всё не покроет. - **Validate не подставляет переменные.** Если в HCL `var.foo`, но переменная не объявлена, это ошибка. Если объявлена и нет `default`, validate **пройдёт**, потому что значение может прийти в runtime. - **Validate не ловит логические ошибки.** `count = var.enabled ? 1 : 0` пройдёт, даже если `var.enabled` всегда false: валидное выражение, просто бесполезное. - **Между версиями TF меняется строгость.** В TF 1.5+ validate стал жёстче к provider-schema несовместимостям. После апгрейда TF, проверьте validate на ваших старых проектах. ## Команды ```bash terraform validate ``` Локально, после init. Проверить что HCL валиден. ```bash terraform init -backend=false -input=false && terraform validate ``` В CI: скачать провайдеры без подключения к remote state, валидировать. ```bash terraform validate -json ``` Машинно-читаемый вывод. Используется IDE-плагинами и CI-агрегаторами. ```bash terraform validate -no-color ``` Без ANSI-цветов. Полезно в логах CI которые не умеют рендерить escape-коды. ## См. также - [HCL: язык, на котором пишут Terraform](/terraform/kb/hcl-syntax.md) - [terraform fmt: каноничное форматирование HCL](/terraform/kb/tf-fmt.md) - [terraform init: первая команда в любом проекте](/terraform/kb/tf-init.md) - [terraform plan: посмотреть, что Terraform собирается сделать](/terraform/kb/tf-plan.md)