Обратите внимание, что это мое понимание. Надеемся, М. Аткинс сможет подтвердить.
Почему у Terraform нет зависимости_ для модуля
В качестве подготовки сначала хотелось бы прояснить недоразумение, которое у нас может быть (которое у меня было) относительно Terraform module .
Цель состоит в том, чтобы sh установить, что нет никакой зависимости от модуля TF к другому модулю TF . Тот факт, что объявление модуля A предшествует модулю B, как в файле Root module tf ниже, не означает, что создание ресурса в модуле B не произойдет, пока все ресурсы в модуле A не будут завершены.
Что бы произошло, если бы у нас было два модуля A и B, и они зависели друг от друга?

Root module
resource "aws_vpc" "this" {
cidr_block = var.vpc_cidr
}
#--------------------------------------------------------------------------------
# Create PRIVATE subnets but create EC2 in PUBLIC subnets (cross module reference)
#--------------------------------------------------------------------------------
module "private_subnet_public_ec2" {
source = "../private_subnet_public_ec2"
vpc_id = aws_vpc.this.id
private_subnet_cidr_blocks = var.private_subnet_cidr_blocks
public_subnet_ids = module.public_subnet_private_ec2.public_subnet_ids
ami_id = data.aws_ami.this.id
}
#--------------------------------------------------------------------------------
# Create PUBLIC subnets but create EC2 in PRIVATE subnets (cross module reference)
#--------------------------------------------------------------------------------
module "public_subnet_private_ec2" {
source = "../public_subnet_private_ec2"
vpc_id = aws_vpc.this.id
public_subnet_cidr_blocks = var.public_subnet_cidr_blocks
private_subnet_ids = module.private_subnet_public_ec2.private_subnet_ids
ami_id = data.aws_ami.this.id
}
Модуль A
Создает частные подсети и EC2 в общедоступных c подсетях, созданных в модуле B.
resource "aws_subnet" "private" {
count = length(var.private_subnet_cidr_blocks)
vpc_id = var.vpc_id
cidr_block = var.private_subnet_cidr_blocks[count.index]
}
output "private_subnet_ids" {
value = aws_subnet.private[*].id
}
resource "aws_instance" "public_ec2" {
count = length(var.public_subnet_ids)
subnet_id = var.public_subnet_ids[count.index]
ami = var.ami_id
instance_type = "t2.micro"
tags = {
Name = "PublicEC2${count.index}}"
}
provisioner "local-exec" {
command = <<EOF
echo "Public EC2 ${count.index} ID is ${self.id}"
EOF
}
}
Модуль B
Создает pubi c подсетей и EC2 в частных подсетях, созданных в модуле A.
resource "aws_subnet" "public" {
count = length(var.public_subnet_cidr_blocks)
vpc_id = var.vpc_id
cidr_block = var.public_subnet_cidr_blocks[count.index]
}
output "public_subnet_ids" {
value = aws_subnet.public[*].id
}
resource "aws_instance" "private_ec2" {
count = length(var.private_subnet_ids)
subnet_id = var.private_subnet_ids[count.index]
ami = var.ami_id
instance_type = "t2.micro"
tags = {
Name = "privateEC2${count.index}}"
}
provisioner "local-exec" {
command = <<EOF
echo "private EC2 ${count.index} ID is ${self.id}"
EOF
}
}
Результат выполнения:
$ terraform apply --auto-approve
Apply complete! Resources: 13 added, 0 changed, 0 destroyed.
Итак, нам нужно иметь в виду то, что на самом деле видит Terraform, это сплющенный мир без модулей, где существуют только ресурсы. Terraform создает DAG из ресурсов, и в этой группе нет module как узла .
Вот почему мы не можем использовать ависимый_он от модуля, потому что в DAG Terraform модуль не является узлом , для которого можно создавать вершины для представления зависимостей.

Механизм монитора синхронизации
Terraform выполняет несколько потоков для одновременного создания ресурсов. Нам нужна синхронизация monitor , в которой потоки могут ожидать, чтобы эти потоки запускались только после создания ресурса зависимости.
Механизм мониторинга в Terraform (кроме оператора HCL depen_on) использует атрибут (ы) созданного ресурса (или ссылку через локальный).

В СОВЕТАХ: Как реализовать модуль зависит от эмуляции , Мартин Аткинс показал пример использования переменной модуля "vm_depends_on", ссылающейся на атрибут созданного ресурса брандмауэра, модуль . fw_core01.firewall , чтобы эти ресурсы в модуле "example" могли быть созданы только после создания брандмауэра.

Problem
В моем понимании причина проблемы в этом вопросе - отсутствие monitor , ссылки на атрибут ресурса, который должен был быть уже создан при запуске потока выполнение data "aws_subnet" "self"
.
Поскольку у меня нет полного источника исходного вопроса, вот пример для воспроизведения ошибки.

Root модуль
variable "vpc_cidr" {
default = "10.5.0.0/20"
}
variable "private_subnet_cidr_blocks" {
default = ["10.5.3.0/24","10.5.4.0/24","10.5.5.0/24"]
}
resource "aws_vpc" "this" {
cidr_block = var.vpc_cidr
}
module "private_subnet" {
source = "../private_subnet"
vpc_id = aws_vpc.this.id
private_subnet_cidr_blocks = var.private_subnet_cidr_blocks
}
module "private_ec2" {
source = "../private_ec2"
vpc_id = aws_vpc.this.id
private_subnet_cidr_blocks = var.private_subnet_cidr_blocks
ami_id = data.aws_ami.this.id
}
Модуль Су bnet
variable "vpc_id" {}
variable "private_subnet_cidr_blocks" {
type = list(string)
}
resource "aws_subnet" "private" {
count = length(var.private_subnet_cidr_blocks)
vpc_id = var.vpc_id
cidr_block = var.private_subnet_cidr_blocks[count.index]
}
Модуль EC2
variable "vpc_id" {}
variable "private_subnet_cidr_blocks" {
type = list(string)
}
variable "ami_id" {}
data aws_subnet "private" {
count = length(var.private_subnet_cidr_blocks)
vpc_id = var.vpc_id
cidr_block = var.private_subnet_cidr_blocks[count.index]
}
resource "aws_instance" "private_ec2" {
count = length(data.aws_subnet.private[*].id)
subnet_id = data.aws_subnet.private[count.index].id
ami = var.ami_id
instance_type = "t2.micro"
tags = {
Name = "privateEC2${count.index}}"
}
provisioner "local-exec" {
command = <<EOF
echo "private EC2 ${count.index} ID is ${self.id}"
EOF
}
}
Результат выполнения:
$ terraform apply --auto-approve
...
Error: no matching subnet found
on ../private_ec2/main.tf line 1, in data "aws_subnet" "private":
1: data aws_subnet "private" {
Причина
Причиной является передача частного su bnet CIDR с использованием константных переменных, а НЕ атрибутов созданного AWS su bnet.
Если используются атрибуты созданного ресурса AWS su bnet, то он работает как монитор, на котором будет ожидать поток, выполняющий data "aws_subnet" "self"
.
Root module
variable "private_subnet_cidr_blocks" {
default = ["10.5.3.0/24","10.5.4.0/24","10.5.5.0/24"]
}
module "private_ec2" {
source = "../private_ec2"
vpc_id = aws_vpc.this.id
private_subnet_cidr_blocks = var.private_subnet_cidr_blocks # <----- Here
ami_id = data.aws_ami.this.id
}
Поскольку нет никакой зависимости между ресурсом в модуле Su bnet и ресурсом в модуле EC2, создание ресурса в обоих модулях выполняется параллельно.
В первоначальном вопросе
Я полагаю, что причиной первоначального вопроса является передаваемая переменная private_subnets , а не атрибуты фактически созданного ресурса AWS su bnet.
module "smurf_subnet_grp" {
source = "../../modules/networking/subnet_grp_per_az-test"
vpc_id = "${module.networking_uswe2.vpc_id}"
azs = "${local.az_list_uswe2}"
private_subnets = "${var.private_subnets_uswe2}" <----- Here
}
Следовательно, data "aws_subnet" "self"
выполняется одновременно, пока AWS su bnet создается или еще не создан.
Fix
Исправление для примера:

Root module
resource "aws_vpc" "this" {
cidr_block = var.vpc_cidr
}
module "private_subnet" {
source = "../private_subnet"
vpc_id = aws_vpc.this.id
private_subnet_cidr_blocks = var.private_subnet_cidr_blocks
}
module "private_ec2" {
source = "../private_ec2"
vpc_id = aws_vpc.this.id
#--------------------------------------------------------------------------------
# Pass the attributes of created aws_subnet resource attributes
#--------------------------------------------------------------------------------
#private_subnet_cidr_blocks = var.private_subnet_cidr_blocks
private_subnet_cidr_blocks = module.private_subnet.private_subnet_cidr_blocks # <--- Here
#--------------------------------------------------------------------------------
ami_id = data.aws_ami.this.id
}
Module su bnet
resource "aws_subnet" "private" {
count = length(var.private_subnet_cidr_blocks)
vpc_id = var.vpc_id
cidr_block = var.private_subnet_cidr_blocks[count.index]
}
#--------------------------------------------------------------------------------
# Output the cidr_block attributes of the AWS subnet resources created
#--------------------------------------------------------------------------------
output "private_subnet_cidr_blocks" {
value = aws_subnet.private[*].cidr_block # <----- Here
}
Результат
$ terraform apply --auto-approve
data.aws_availability_zones.all: Refreshing state...
aws_vpc.this: Refreshing state... [id=vpc-0b338898d18a5986e]
data.aws_ami.this: Refreshing state...
data.aws_region.current: Refreshing state...
module.private_subnet.data.aws_ami.ubuntu: Refreshing state...
module.private_subnet.aws_subnet.private[2]: Refreshing state... [id=subnet-0cf916b6b9003f71f]
module.private_subnet.aws_subnet.private[1]: Refreshing state... [id=subnet-0b39beb22b23eef5d]
module.private_subnet.aws_subnet.private[0]: Refreshing state... [id=subnet-0c80c92f4023ba893]
aws_vpc.this: Creating...
aws_vpc.this: Still creating... [10s elapsed]
aws_vpc.this: Still creating... [20s elapsed]
aws_vpc.this: Creation complete after 24s [id=vpc-00069d144b5f76182]
module.private_subnet.aws_subnet.private[1]: Creating...
module.private_subnet.aws_subnet.private[2]: Creating...
module.private_subnet.aws_subnet.private[0]: Creating...
module.private_subnet.aws_subnet.private[2]: Creation complete after 5s [id=subnet-0252c6047cd56abac]
module.private_subnet.aws_subnet.private[1]: Creation complete after 6s [id=subnet-019f8cbd30db10edb]
module.private_subnet.aws_subnet.private[0]: Creation complete after 6s [id=subnet-0a1028bf17d7d81be]
module.private_ec2.data.aws_subnet.private[1]: Refreshing state...
module.private_ec2.data.aws_subnet.private[2]: Refreshing state...
module.private_ec2.data.aws_subnet.private[0]: Refreshing state...
module.private_ec2.aws_instance.private_ec2[2]: Creating...
module.private_ec2.aws_instance.private_ec2[1]: Creating...
module.private_ec2.aws_instance.private_ec2[0]: Creating...
module.private_ec2.aws_instance.private_ec2[2]: Still creating... [10s elapsed]
module.private_ec2.aws_instance.private_ec2[1]: Still creating... [10s elapsed]
module.private_ec2.aws_instance.private_ec2[0]: Still creating... [10s elapsed]
module.private_ec2.aws_instance.private_ec2[2]: Still creating... [20s elapsed]
module.private_ec2.aws_instance.private_ec2[1]: Still creating... [20s elapsed]
module.private_ec2.aws_instance.private_ec2[0]: Still creating... [20s elapsed]
module.private_ec2.aws_instance.private_ec2[2]: Still creating... [30s elapsed]
module.private_ec2.aws_instance.private_ec2[1]: Still creating... [30s elapsed]
module.private_ec2.aws_instance.private_ec2[0]: Still creating... [30s elapsed]
module.private_ec2.aws_instance.private_ec2[2]: Still creating... [40s elapsed]
module.private_ec2.aws_instance.private_ec2[1]: Still creating... [40s elapsed]
module.private_ec2.aws_instance.private_ec2[0]: Still creating... [40s elapsed]
module.private_ec2.aws_instance.private_ec2[1]: Provisioning with 'local-exec'...
module.private_ec2.aws_instance.private_ec2[1] (local-exec): Executing: ["/bin/sh" "-c" "echo \"private EC2 1 ID is i-0ced265565dfec85c\"\n"]
module.private_ec2.aws_instance.private_ec2[1] (local-exec): private EC2 1 ID is i-0ced265565dfec85c
module.private_ec2.aws_instance.private_ec2[1]: Creation complete after 46s [id=i-0ced265565dfec85c]
module.private_ec2.aws_instance.private_ec2[0]: Provisioning with 'local-exec'...
module.private_ec2.aws_instance.private_ec2[0] (local-exec): Executing: ["/bin/sh" "-c" "echo \"private EC2 0 ID is i-0f6ce62c29376c6fe\"\n"]
module.private_ec2.aws_instance.private_ec2[0] (local-exec): private EC2 0 ID is i-0f6ce62c29376c6fe
module.private_ec2.aws_instance.private_ec2[0]: Creation complete after 47s [id=i-0f6ce62c29376c6fe]
module.private_ec2.aws_instance.private_ec2[2]: Provisioning with 'local-exec'...
module.private_ec2.aws_instance.private_ec2[2] (local-exec): Executing: ["/bin/sh" "-c" "echo \"private EC2 2 ID is i-03be32b7b803eb0cc\"\n"]
module.private_ec2.aws_instance.private_ec2[2] (local-exec): private EC2 2 ID is i-03be32b7b803eb0cc
module.private_ec2.aws_instance.private_ec2[2]: Creation complete after 50s [id=i-03be32b7b803eb0cc]
Apply complete! Resources: 7 added, 0 changed, 0 destroyed.
Исправить исходный вопрос
Полагаю, что приведенное ниже исправит проблему.
module "smurf_subnet_grp" {
source = "../../modules/networking/subnet_grp_per_az-test"
vpc_id = "${module.networking_uswe2.vpc_id}"
azs = "${local.az_list_uswe2}"
#--------------------------------------------------------------------------------
# Pass the cidr_block attribute of aws_subnet resource created in module.networking_uswe2
#------------------------------------------------------------------------------
#private_subnets = "${var.private_subnets_uswe2}"
private_subnets = module.networking_uswe2.private_subnet_cidr_blocks # <---- Here
#------------------------------------------------------------------------------
}