# Блок variable: вход в конфигурацию _Переменные и outputs · TerraformLab Knowledge Base_ **TL;DR:** variable, параметр, который принимает значение снаружи (CLI, env, .tfvars). Объявляешь в HCL: type, default, description, validation. Используешь как var.name. Нужен чтобы убрать хардкод и переиспользовать один HCL для разных окружений. ## Зачем нужны переменные Без переменных каждое окружение требует свой HCL-файл. С переменными, один HCL и три набора значений. Плохо: ```hcl resource "aws_s3_bucket" "demo" { bucket = "my-app-prod-logs" # хардкод } ``` Хорошо: ```hcl variable "env" { type = string default = "dev" } resource "aws_s3_bucket" "demo" { bucket = "my-app-${var.env}-logs" } ``` Теперь один и тот же HCL можно запустить с `-var="env=prod"` для прода, без правки кода. ## Минимальная переменная ```hcl variable "bucket_name" {} ``` Это валидная переменная. Тип не объявлен (будет `any`), description не задан, default не задан → значит, **обязательно** передать значение снаружи. Если не передал, apply упадёт с вопросом. ## Все поля variable ```hcl variable "bucket_name" { type = string # ожидаемый тип (см. Ниже) description = "Имя S3-бакета. Должно быть глобально уникальным." default = "my-default-bucket-12345" # если не задано снаружи nullable = false # запрет на null (default true) sensitive = false # маркер «не светить в логах» ephemeral = false # только в памяти, не в state (1.10+) validation { condition = length(var.bucket_name) >= 3 && length(var.bucket_name) <= 63 error_message = "Имя бакета должно быть длиной 3-63 символа." } validation { condition = can(regex("^[a-z0-9][a-z0-9.-]*[a-z0-9]$", var.bucket_name)) error_message = "Имя бакета: только нижний регистр, цифры, точки и дефисы." } } ``` Не все поля обязательны. Достаточно `type` и (если нет default): передачи снаружи. ## Типы переменных Можно простые типы и сложные: ```hcl # примитивы variable "region" { type = string } variable "count" { type = number } variable "enabled" { type = bool } # коллекции variable "tags" { type = map(string) } variable "azs" { type = list(string) } variable "values" { type = set(string) } # уникальные, неупорядоченные # объект (как map, но с фиксированной структурой) variable "db" { type = object({ instance_class = string allocated_storage = number multi_az = bool }) } # без типа, всё подходит (плохая практика для прода) variable "anything" {} ``` Если значение не подходит по типу. Terraform упадёт с понятной ошибкой. См. [hcl-types](/terraform/kb/hcl-types.md). ## Validation, проверки на корректность Условия, которые проверяются перед использованием переменной: ```hcl variable "env" { type = string description = "Окружение (dev/staging/prod)" validation { condition = contains(["dev", "staging", "prod"], var.env) error_message = "env должен быть один из: dev, staging, prod." } } ``` Validation выполняется при `plan`. Если condition вернёт `false`, apply не запустится, и пользователь увидит `error_message`. Можно несколько validation-блоков для одной переменной. Все проверяются. ## sensitive, защита от логирования ```hcl variable "db_password" { type = string sensitive = true } ``` Сейчас: - В `plan` и `apply` значение маскируется на `(sensitive value)`. - В output, который ссылается на эту переменную, тоже маскируется (если только output не помечен sensitive отдельно). - **В state-файле значение всё равно сохраняется в открытом виде.** sensitive, это про лог-вывод, не про шифрование. Для **реальной** секретности используйте Vault, AWS Secrets Manager, или хотя бы зашифрованный remote state с ограниченным доступом. ## Использование ```hcl variable "env" { type = string default = "dev" } resource "aws_s3_bucket" "demo" { bucket = "my-app-${var.env}-bucket" tags = { Environment = var.env } } ``` Префикс `var.`, обязателен. Без него Terraform решит, что это resource или data. ## Подводные камни - **type объявляйте всегда.** «Без типа» работает, но любая ошибка проявится поздно. Тип ловит проблему на стадии валидации. - **default не означает «значение по умолчанию».** Это значение **если не задано снаружи**. Если задано, default игнорируется. - **sensitive не равно шифрованию.** Маскирует только в выводе CLI. В state, открытым текстом. - **Переменные нельзя ссылаться друг на друга.** `variable "b" { default = var.a }`, невалидно. Для зависимых выражений используйте [tf-locals](/terraform/kb/tf-locals.md). - **validation работает только на этап plan.** Если значение получено из data-источника и оно "known after apply", validation может пропустить ошибку. - **Переменные глобальны на конфигурацию.** Нельзя «локальные» переменные внутри блока. Если нужна локальная переменная, это `locals { ... }`. ## Команды ```bash terraform plan -var='env=prod' ``` Передать значение переменной через CLI. Можно несколько -var флагов. ```bash terraform plan -var-file=prod.tfvars ``` Загрузить все переменные из файла. См. [[tf-tfvars]] про формат. ```bash TF_VAR_env=prod terraform plan ``` Через env-переменную. Префикс TF_VAR_ + имя переменной. ## См. также - [Откуда Terraform берёт значения переменных](/terraform/kb/tf-variable-sources.md) - [.tfvars: файлы со значениями переменных](/terraform/kb/tf-tfvars.md) - [Типы данных в HCL: string, number, list, map, object](/terraform/kb/hcl-types.md) - [Блок output: что Terraform возвращает наружу](/terraform/kb/tf-output.md) - [locals: вычисляемые внутренние имена](/terraform/kb/tf-locals.md)