lesson ── terraform-beginner ── ~12 мин ── 5 шагов
Десять предыдущих уроков были про что Terraform делает. Этот урок,
про три команды, которые ты будешь запускать каждый день и которые
предотвращают 80% позора на код-ревью: fmt, validate, console.
Это не «бонус», это базовая гигиена. Без них HCL превращается в
спагетти, опечатки в именах атрибутов всплывают в plan или apply
(а без validate в pre-commit, иногда и того позже), а сложные
выражения дебажатся методом «правлю → plan → читаю → правлю».
интерактивный sandbox
Поднимется пара контейнеров: terraform 1.9 и localstack 3.8 в одной сети. В браузере откроется терминал, можно сразу terraform init. Каждый шаг проверяется автоматически. TTL 45 минут, без регистрации.
stack ── terraform · localstack · 1 GB RAM · самоуничтожается через 45 мин простоя
В ~/tf-hygiene создай main.tf со специально плохим форматированием:
resource "aws_s3_bucket" "demo" { bucket="linuxlab-hygiene-${random_id.suffix.hex}" tags={Owner="student"
Project ="hygiene-demo"
}
}
resource "random_id" "suffix" {byte_length=4
}
Кривые отступы, отсутствующие пробелы вокруг =, разнобой. Это
типичная картина после слияния PR от трёх разработчиков с разными
настройками IDE.
Не запускай terraform пока, сначала посмотрим как fmt с этим разберётся.
Можно скопировать целиком через `cat > main.tf <<EOF ... EOF`. Не правь отступы: пусть они будут кривыми.
✓ Файл сохранён. Теперь приведём его в порядок.
Запусти:
cd /home/student/tf-hygiene
terraform fmt
В выводе, main.tf. Это значит файл был неотформатирован, теперь
исправлен.
Открой файл и посмотри:
cat main.tf
Теперь там:
=.Owner и Project выровнены по =.Это тот же код, не другой. Только стиль. terraform plan
выдал бы одинаковый результат и до, и после fmt.
Привычка: fmt после каждого редактирования. Или поставь в IDE
на save. См. tf-fmt.
Если fmt ничего не вывел, значит уже отформатирован. Скопируй файл с кривыми отступами заново.
✓ После fmt -check проверка чистая: стиль каноничный.
Подкинем в HCL опечатку. Открой main.tf и поменяй bucket на
bucket_name:
resource "aws_s3_bucket" "demo" { bucket_name = "linuxlab-hygiene-${random_id.suffix.hex}"# ^^^^^^^^^^^ намеренная опечатка
tags = {Owner = "student"
Project = "hygiene-demo"
}
}
Запусти init + validate:
terraform init -backend=false -input=false
terraform validate
Получишь:
Error: Unsupported argument
on main.tf line 2, in resource "aws_s3_bucket" "demo":
2: bucket_name = "linuxlab-hygiene-..."
An argument named "bucket_name" is not expected here.
Did you mean "bucket"?
Заметь Did you mean "bucket"?, это автоматическая подсказка по
похожим именам. Спасает на опечатках.
Validate не ходит в облако. Это секунда дебага вместо минуты
apply → Error from AWS → разбор.
Если validate говорит 'no provider': забыл `terraform init -backend=false`.
✓ validate поймал опечатку. Теперь починим и проверим что стало чисто.
Верни bucket_name → bucket:
resource "aws_s3_bucket" "demo" { bucket = "linuxlab-hygiene-${random_id.suffix.hex}" tags = {Owner = "student"
Project = "hygiene-demo"
}
}
terraform fmt
terraform validate
Validate должен сказать:
Success! The configuration is valid.
Это правильный workflow: пиши HCL → fmt → validate. Только после этого имеет смысл делать plan/apply.
В CI этот же workflow автоматизирован через pre-commit hooks и сборку линтеров. См. tf-validate.
Если validate всё ещё ругается: поищи `bucket_name` в файле (`grep -n bucket_name main.tf`), мог остаться где-то.
✓ HCL валиден. Можно переходить к plan/apply.
OpenTofu держит CLI и state совместимыми с Terraform по командам
этого шага: миграция обычно проходит через mv .terraform .terraform.bak; tofu init -upgrade. Но при первом переходе
сделай backup state и прогон на feature-branch - расхождения
концентрируются в новых фичах (variables в backend,
state-encryption, OCI registry-backed модули). См.
tf-opentofu-parity для полной матрицы.
Перед тем как воткнуть сложное выражение в HCL, проверь его в console. Сначала применим конфигурацию чтобы был state:
terraform apply -auto-approve
Теперь:
terraform console
Появится >. Попробуй:
> 1 + 2 * 3
7
> upper("terraform")"TERRAFORM"
> length(aws_s3_bucket.demo.tags)
2
> aws_s3_bucket.demo.arn
"arn:aws:s3:::linuxlab-hygiene-..."
> [for k, v in aws_s3_bucket.demo.tags : "${k}=${v}"][
"Owner=student",
"Project=hygiene-demo",
]
Выйти, exit или Ctrl+D.
Это главный use case console: проверить выражение до того как воткнуть его в HCL. Сэкономит часы на этапе intermediate-трека (модули, dynamic blocks, сложные locals). См. tf-console.
Если console падает с 'configuration is invalid': сначала validate, потом console.
✓ Console работает, видит state, считает выражения. Это твой главный инструмент дебага HCL.
В console есть спецоператор type(...), печатает выведенный
тип выражения:
> type(var.region)
string
> type(aws_s3_bucket.demo.tags)
map of string
> type([1, 2, 3])
tuple([number, number, number])
Это спасает в двух местах:
Часто на код-ревью «почему этот тип, а не другой» решается одной строкой в console. См. hcl-types про различия типов.
Три инструмента, три привычки. fmt после каждого редактирования.
validate перед каждым plan. console для проверки локалов и
выражений до того как воткнуть их в HCL.
команды
terraform fmt -recursiveформатирование, включая модулиterraform validateпроверка HCL без обращения в облакоterraform consoleREPL для выражений и проверки stateecho 'type(var.X)' | terraform consoleне-интерактивная проверка типаконцепции