具有动态内容的Terrafrom动态块



我正在尝试创建一个用于创建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_blockgateway_id的内容,另一个用于带有ipv6_cidr_blockegress_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方法是更通用的答案,它也应该适用于正常的嵌套块。

相关内容

  • 没有找到相关文章

最新更新