Зачем нужен output
Когда Terraform создаст ресурс, у него появятся атрибуты, id, arn, endpoint. Иногда эти значения нужны:
- Пользователю, посмотреть, какой URL получил создаваемый сервис.
- Другому Terraform-проекту, через remote state.
- Внешнему скрипту,
aws_endpoint=$(terraform output -raw endpoint). - Родительскому модулю, child-модуль возвращает свои значения.
output, это способ «открыть» нужные значения наружу.
Базовый синтаксис
resource "aws_s3_bucket" "demo" {bucket = "my-bucket-12345"
}
output "bucket_arn" {value = aws_s3_bucket.demo.arn
description = "ARN созданного бакета: нужен для cross-account IAM-политик."
}
output "bucket_url" { value = "https://${aws_s3_bucket.demo.bucket}.s3.amazonaws.com"}
После apply Terraform покажет:
Outputs:
bucket_arn = "arn:aws:s3:::my-bucket-12345"
bucket_url = "https://my-bucket-12345.s3.amazonaws.com"
sensitive, спрятать значение
output "db_password" {value = aws_db_instance.main.password
sensitive = true
}
Сейчас:
- В
terraform applyзначение покажется как(sensitive value). - В
terraform output db_passwordнапечатает реальное значение (для скриптов). - В
terraform output -raw db_password, то же. - В state-файле значение лежит открытым текстом. sensitive, только про логирование.
Если значение приходит из sensitive-переменной
Если output ссылается на переменную с sensitive = true, output тоже автоматически считается sensitive. Иначе Terraform упадёт с ошибкой «выводишь sensitive в non-sensitive output».
Чтобы вывести явно, пометьте output как sensitive.
depends_on в output
Редко но бывает: нужно гарантировать порядок создания ресурсов, на которые output ссылается косвенно:
output "endpoint" {value = aws_lb.web.dns_name
depends_on = [aws_lb_listener.https]
}
Зачем? Если другой проект читает этот output через remote state, можно гарантировать что listener настроен, иначе клиент будет получать пустоту.
В большинстве случаев depends_on в output не нужен.
Чтение output из CLI
# Все output одним JSON
terraform output -json
# Один output, в человеческом формате
terraform output bucket_arn
# "arn:aws:s3:::my-bucket-12345"
# Один output, без кавычек и JSON-обвязки, для подстановки в shell
terraform output -raw bucket_arn
# arn:aws:s3:::my-bucket-12345
# В переменную bash
BUCKET_ARN=$(terraform output -raw bucket_arn)
-raw работает только для простых типов (string/number). Для list/map, используйте -json + jq.
Output между модулями
Если есть child-модуль:
# modules/vpc/outputs.tf
output "vpc_id" {value = aws_vpc.main.id
}
В родительском HCL:
module "network" {source = "./modules/vpc"
}
resource "aws_subnet" "private" {vpc_id = module.network.vpc_id # ← обращение к output модуля
}
Префикс module.имя_модуля.имя_output. Это единственный способ child-модуля «отдать» значение наружу. Internal атрибуты модуля недоступны.
Подводные камни
-
State-файл не шифруется. Сколько ни ставьте
sensitive = true, значение лежит вterraform.tfstateв открытом виде. Для секретов нужно шифровать state на уровне backend (S3 с SSE-KMS, Terraform Cloud с шифрованием). -
output читается через
output()функцию не работает. В HCL нет способа сослаться на свой же output из другой части HCL. Хотите переиспользуемое значение, это tf-locals. -
При удалении ресурса output исчезает. Если другой проект завязан через remote state, у него поломается. Думайте перед удалением.
-
output value должно быть вычислимо. Нельзя
value = "${unknown_var}"еслиunknown_varне определён. Terraform упадёт с понятной ошибкой. -
description полезно. Это документация для тех, кто будет использовать ваш output (в том числе вы через год). Не ленитесь его заполнять.
-
-rawдля сложных типов, ошибка. Если попробоватьterraform output -raw all_tags(гдеall_tags, map), упадёт с ошибкой. Только string/number.