В языке Terraform модуль создает отдельное пространство имен, но это , а не узел в графе зависимостей. Вместо этого каждая из входных переменных и выходных значений модуля является отдельными узлами в графе зависимостей.
По этой причине эта конфигурация содержит следующие зависимости:
- Ресурс
data.aws_security_group.default
зависит от module.vpc.vpc_id
, который является именно блоком output "vpc_id"
в этом модуле, а не модулем в целом. - Переменная
vpc
модуля *1013* зависит от ресурса data.aws_security_group.default
.
Мы не можем видеть внутреннюю часть модуля vpc
в вашем вопросе здесь, но с вышесказанным все в порядке, пока внутри модуля нет соединения зависимостей между output "vpc_id"
и variable "ssm_endpoint_security_group_ids"
.
Я предполагаю, что такого соединения не существует, и поэтому порядок оценки объектов здесь будет примерно таким:
aws_vpc.example
в module.vpc
создано (Я просто придумал название для этого, потому что оно не включено в ваш вопрос) - Оценивается
output "vpc_id"
в module.vpc
, ссылаясь на module.vpc.aws_vpc.example
и производя module.vpc.vpc_id
. data.aws_security_group.default
в режиме root Файл читается, используя значение module.vpc.vpc_id
. - .
variable "ssm_endpoint_security_group_ids"
для module.vpc
оценивается, ссылаясь на data.aws_security_group.default
. aws_vpc_endpoint.example
в module.vpc
создан включая ссылку на var.ssm_endpoint_security_group_ids
.
Обратите внимание, что во всем вышесказанном я говорю об объектах в модулях, а не о самих модулях. Модули служат только для создания отдельных пространств имен для объектов, а затем сами отдельные объекты (включая отдельные блоки variable
и output
) участвуют в графике зависимостей.
Обычно этот дизайн детали не видны: обычно Terraform просто использует их для потенциальной оптимизации параллелизма, начиная работу над частью модуля, прежде чем весь модуль будет готов к обработке. Однако в некоторых интересных случаях, подобных этому, вы также можете намеренно использовать эту схему, чтобы операция для вызывающего модуля могла быть явно помещена между двумя операциями для дочернего модуля.
Еще одна причина, по которой мы могли бы использовать это Это возможно, когда два модуля естественно зависят друг от друга, например, в экспериментальном модуле, который я построил , который скрывает некоторые хитрые детали настройки пиринговых соединений VP C:
locals {
vpc_nets = {
us-west-2 = module.vpc_usw2
us-east-1 = module.vpc_use1
}
}
module "peering_usw2" {
source = "../../modules/peering-mesh"
region_vpc_networks = local.vpc_nets
other_region_connections = {
us-east-1 = module.peering_use1.outgoing_connection_ids
}
providers = {
aws = aws.usw2
}
}
module "peering_use1" {
source = "../../modules/peering-mesh"
region_vpc_networks = local.vpc_nets
other_region_connections = {
us-west-2 = module.peering_usw2.outgoing_connection_ids
}
providers = {
aws = aws.use1
}
}
(выше приведен только соответствующий фрагмент из примера в репозитории модулей .)
В приведенном выше случае модуль peering-mesh
тщательно спроектирован, чтобы разрешить эту взаимную ссылку, внутренне решить для каждой пары региональных VPC, какой из них будет инициатором пиринга, а какой - пиринговым акцептором. Вывод outgoing_connection_ids
относится только к ресурсу aws_vpc_peering_connection
, а aws_vpc_peering_connection_accepter
относится только к var.other_region_connections
, поэтому в результате получается куча параллельных операций для создания ресурсов aws_vpc_peering_connection
, за которыми следует куча параллельных операций для создать aws_vpc_peering_connection_accepter
ресурсов.