已通过Terraform v0.12.9进行了测试
我通常将安全组和安全组规则作为单独的资源进行管理,如以下示例所示:
resource "aws_security_group" "this" {
count = var.create ? 1 : 0
name_prefix = "${var.security_group_name}_"
vpc_id = var.vpc_id
lifecycle {
create_before_destroy = true
}
}
resource "aws_security_group_rule" "ingress_rules" {
count = var.create ? length(var.inbound_security_group_ids) : 0
security_group_id = aws_security_group.this[0].id
type = "ingress"
from_port = var.from_port
to_port = var.to_port
protocol = "tcp"
source_security_group_id = var.inbound_security_group_ids[count.index]
}
此实现的外观如下所示:
module "test_module" {
source = "../path/to/module/"
create = true
vpc_id = "vpc-xxxxxx"
security_group_name = "${var.service_name}-db"
from_port = 1234
to_port = 1234
inbound_security_group_ids = [
module.service.security_group_id_one,
module.service.security_group_id_two
]
}
问题
如果没有创建module.service
的输出,我希望它能正常工作。在那种情况下,我的期望是length(var.inbound_security_group_ids)
应该评估为0
,从而导致未创建安全组规则
实际上发生的是,当未创建length(var.inbound_security_group_ids)
时,2
的值为module.service
。据推测这是因为它是两个空白字符串的数组["", ""]
根据Terraform documentation,我可以使用compact
函数处理此问题,该函数将从数组中删除空字符串。
resource "aws_security_group_rule" "ingress_rules" {
count = var.create ? length(compact(var.inbound_security_group_ids)) : 0
security_group_id = aws_security_group.this[0].id
type = "ingress"
from_port = var.from_port
to_port = var.to_port
protocol = "tcp"
source_security_group_id = var.inbound_security_group_ids[count.index]
}
然而,问题是Terraform无法确定plan
,因为直到var.inbound_security_group_ids
才知道apply-time
的计算结果。这是错误消息(针对上下文):
“ count”值取决于无法确定的资源属性在应用之前,Terraform无法预测将创建多少实例。要解决此问题,请使用-target参数首先仅应用计数所依赖的资源。
问题
是否有可能像这样解耦安全组,以便即使source_security_group_id
属性没有值也仍然可以创建该安全组?
presence。
在这种情况下,您可以通过更改从service
模块返回安全组ID的方式来解决该问题,以使每个输出都是安全组ID的list
,而不是一个可能是有效的安全组ID或空字符串:module "test_module" {
source = "../path/to/module/"
create = true
vpc_id = "vpc-xxxxxx"
security_group_name = "${var.service_name}-db"
from_port = 1234
to_port = 1234
inbound_security_group_ids = concat(
module.service.security_group_ids_one,
module.service.security_group_ids_two,
)
}
如果已知,则可以将它们安排为一个已知列表,其中一个元素的值未知,因此security_group_ids_one
或security_group_ids_two
是空列表,则concat
将完全忽略它。如果启用了[[are
length(var.inbound_security_group_ids)
在所有情况下仍将具有已知值。