我正在尝试创建一个用于创建aws_route_table的地形模块,下面是这个资源定义的示例:
resource "aws_route_table" "example" {
vpc_id = aws_vpc.example.id
route {
cidr_block = "10.0.1.0/24"
gateway_id = aws_internet_gateway.example.id
}
route {
ipv6_cidr_block = "::/0"
egress_only_gateway_id = aws_egress_only_internet_gateway.example.id
}
tags = {
Name = "example"
}
}
我正试图通过使用动态块来使它更加动态。问题是,我总是必须在内容块中定义密钥
resource "aws_route_table" "example" {
...
dynamic "route" {
for_each = var.route
content {
cidr_block = route.value.cidr_block
gateway_id = route.value.gateway_id
}
}
...
}
因此,在这种情况下,我需要编写两个动态块,一个用于具有cidr_block
和gateway_id
的内容,另一个用于带有ipv6_cidr_block
和egress_only_gateway_id
的内容。
有没有任何方法可以在不显式定义键的情况下做到这一点。类似这样的东西:
dynamic "route" {
for_each = var.route
content {
var.route.map
}
}
是的,您可以动态创建route
,因为块route
充当块的属性。所以你可以做
# define all your routes in a variable (example content)
variable "routes" {
default = [
{
cidr_block = "0.0.0.0/0"
gateway_id = "igw-0377483faa64bf010"
},
{
cidr_block = "172.31.0.0/20"
instance_id = "i-043fc97db72ad1b59"
}
]
}
# need to provide default values (null) for all possibilities
# in route
locals {
routes_helper = [
for route in var.routes: merge({
carrier_gateway_id = null
destination_prefix_list_id = null
egress_only_gateway_id = null
ipv6_cidr_block = null
local_gateway_id = null
nat_gateway_id = null
network_interface_id = null
transit_gateway_id = null
vpc_endpoint_id = null
instance_id = null
gateway_id = null
vpc_peering_connection_id = null
}, route)
]
}
resource "aws_route_table" "example" {
vpc_id = aws_vpc.example.id
# route can be attribute, instead of blocks
route = local.routes_helper
tags = {
Name = "example"
}
}
文档一般不建议使用它,但我认为route是一个可以接受的好例子。
对于不使用"作为块的属性";Marcin提到的向后兼容性垫片依赖于这样一个事实,即对于Terraform提供程序参数,省略参数或将其显式设置为null
在含义上没有区别。
这意味着您可以编写一个表达式来决定是否填充特定的参数,方法是在适当的情况下使其返回显式null
。例如:
dynamic "route" {
for_each = var.route
content {
cidr_block = try(route.value.cidr_block, null)
gateway_id = try(route.value.gateway_id, null)
ipv6_cidr_block = try(route.value.ipv6_cidr_block, null)
# ...
}
}
像这样的嵌套块更像是一个固定的数据结构,而不是一个集合,因此没有任何语法可以动态构建它。
话虽如此,正如Marcin所指出的,在这种特殊情况下,route
实际上只是对象类型的一个属性,Terraform Core允许将其与块语法一起使用,作为与旧Terraform版本向后兼容的让步。出于这个原因,这两种方法在实践中并没有任何显著的区别;作为块的属性";该机制仅适用于某些情况,即提供者被设计为假设Terraform v0.11验证错误,因此我上面描述的条件null
方法是更通用的答案,它也应该适用于正常的嵌套块。