具有动态内容的 Terraform 动态块
Terrafrom dynamic block with dynamic content
我正在尝试为 aws_route_table 创建一个 terraform 模块,这里是这个资源定义的一个例子:
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
和 [=16 的内容=].
有没有办法在不显式定义键的情况下做到这一点。像这样:
dynamic "route" {
for_each = var.route
content {
var.route.map
}
}
是的,您可以动态创建 route
,因为块 route
充当 Attributes as Blocks。所以你可以做(例子)
# 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"
}
}
文档通常不建议使用它,但我认为路线是一个很好的例子,它可以接受。
Marcin 提到的不使用“属性作为块”向后兼容垫片的块类型的一般答案是依赖于 Terraform 提供程序参数的事实省略参数或将其显式设置为 null
.
在含义上没有区别
这意味着您可以编写一个表达式来决定是否填充特定参数,方法是在适当的情况下将其 return 显式 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
我上面描述的方法是更一般的答案,它也应该适用于普通的嵌套块。
我正在尝试为 aws_route_table 创建一个 terraform 模块,这里是这个资源定义的一个例子:
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
和 [=16 的内容=].
有没有办法在不显式定义键的情况下做到这一点。像这样:
dynamic "route" {
for_each = var.route
content {
var.route.map
}
}
是的,您可以动态创建 route
,因为块 route
充当 Attributes as Blocks。所以你可以做(例子)
# 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"
}
}
文档通常不建议使用它,但我认为路线是一个很好的例子,它可以接受。
Marcin 提到的不使用“属性作为块”向后兼容垫片的块类型的一般答案是依赖于 Terraform 提供程序参数的事实省略参数或将其显式设置为 null
.
这意味着您可以编写一个表达式来决定是否填充特定参数,方法是在适当的情况下将其 return 显式 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
我上面描述的方法是更一般的答案,它也应该适用于普通的嵌套块。