Зачем нужен data
resource создаёт что-то новое. data читает что-то существующее. Разница, фундаментальная:
resource "aws_s3_bucket" "demo" { ... }→ Terraform отвечает за этот бакет. Создаёт, изменяет, удаляет.data "aws_caller_identity" "current" {}→ Terraform просто спрашивает у AWS «кто я сейчас?» и кладёт ответ в переменную. Никакого state-управления.
Data-блоки нужны когда:
- В вашем коде надо знать текущий AWS account ID, а его как-то надо получить.
- VPC создали другой командой, а вам нужен его ID для нового ресурса.
- Хотите выбрать самую свежую Ubuntu AMI без хардкодинга.
Синтаксис
Похож на resource, но с ключевым словом data:
data "aws_caller_identity" "current" {}data "aws_region" "current" {}output "my_account_id" {value = data.aws_caller_identity.current.account_id
}
output "my_region" {value = data.aws_region.current.name
}
Адрес: data.тип.имя.атрибут. Префикс data., обязателен, иначе Terraform решит что это resource.
Типичные data-источники AWS
Самые частые в реальной работе:
# Кто я сейчас (account ID, ARN, user ID)
data "aws_caller_identity" "current" {}# В каком регионе работаем
data "aws_region" "current" {}# Список AZ в этом регионе
data "aws_availability_zones" "available" {state = "available"
}
# Найти конкретную AMI
data "aws_ami" "ubuntu" {most_recent = true
owners = ["099720109477"] # Canonical
filter {name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
}
# Использовать
resource "aws_instance" "web" {ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
}
Когда data, а когда resource
Правило: если этим объектом управляете вы (создаёте/уничтожаете). resource. Если это «дано извне», data.
Признаки что нужен data:
- Объект уже существует, и не вы его создавали.
- Объектом управляет другая команда или другой Terraform-проект.
- Это вспомогательная информация (account ID, регион, latest AMI).
data в LocalStack
Не все AWS data-источники работают в LocalStack одинаково:
- Работают хорошо:
aws_caller_identity,aws_region,aws_availability_zones(возвращают захардкоженные значения для тестов). - Работают частично:
aws_ami(возвращает пустой список. AMI'ев в LocalStack нет). - Не работают: что-то завязанное на реальные AWS-сервисы которые LocalStack community не эмулирует.
В учебных задачах используйте только надёжные data-источники.
Подводные камни
-
data блок ничего не блокирует от изменения. Если вы читаете
data "aws_s3_bucket" "shared"и кто-то снаружи удалит этот бакет, следующийplanругнётся, но данные с прошлогоapplyвсё ещё могут быть в state. Это рассинхронизация. -
data выполняется на каждом plan/apply. Каждый запуск он ходит в API. Если у вас 50 data-блоков с медленными запросами, plan будет медленным.
-
(known after apply)бывает и у data. Если data-блок зависит от ресурса, который ещё не создан, его атрибуты будут «известны после apply». Это создаёт цепочку: создать resource → дёрнуть data → использовать атрибут → создать следующий resource. -
Не используйте data для проверки «существует ли». Если data-блок не нашёл объект, он упадёт с ошибкой. Это не способ сделать
if exists then ... else .... Для условной логики естьtry()иcan()функции. -
data не имеет lifecycle. Блок
lifecycle { ... }в data не работает, нечем управлять.