我一直在尝试提高我在 Terraform 中使用循环的能力。
我有一个用于创建路由表的模块,该路由表采用内联路由列表。
子模块如下所示:
main.tf
resource "azurerm_route_table" "this" {
name = var.name
location = var.location
resource_group_name = var.resource_group_name
bgp_route_propagation_enabled = false
}
resource "azurerm_route" "routes" {
for_each = { for route in var.routes : route.name => route }
name = each.value.name
resource_group_name = azurerm_route_table.this.resource_group_name
route_table_name = azurerm_route_table.this.name
address_prefix = each.value.address_prefix
next_hop_type = each.value.next_hop_type
next_hop_in_ip_address = each.value.next_hop_in_ip_address
}
子变量如下所示:
variables.tf
variable "name" {
type = string
description = "(Required) The name of the Route Table."
}
variable "resource_group_name" {
description = "(Required) Resource Group name of the Route Table to be created"
type = string
nullable = false
}
variable "location" {
description = "(Required) Location of the Route Table to be created"
type = string
nullable = false
}
variable "bgp_route_propagation_enabled" {
description = "(Optional) Boolean flag that controls propagation of routes learned by BGP on the Route Table."
type = bool
default = true
}
variable "routes" {
description = "List of objects that represent the configuration of each added Route."
type = list(object({
name = string
address_prefix = string
next_hop_type = string
next_hop_in_ip_address = optional(string)
}))
default = []
validation {
condition = can(regex("^[VirtualNetworkGateway]|[VnetLocal]|[Internet]|[VirtualAppliance]|[None]$", var.routes[0].next_hop_type))
error_message = "Next Hop Type error: Must be one of the following. \"VirtualNetworkGateway\", \"VnetLocal\", \"Internet\", \"VirtualAppliance\" \"None\". Defaults to None."
}
}
variable "tags" {
description = "(Required) Tags for the resource"
type = map(string)
}
我还包含了路由表 ID、名称和路由名称的输出(我认为?)。
子输出
outputs.tf
output "id" {
value = azurerm_route_table.this.id
description = "The Route Table configuration ID."
}
output "name" {
value = azurerm_route_table.this.name
description = "The name of the Route Table."
}
output "routes" {
value = azurerm_route_table.this.route
description = "Blocks containing configuration of each route."
}
我试图让调用父模块也将这些输出输出到控制台。但路线名称返回一些奇怪的东西?
父模块:
main.tf
module "route_table" {
source = "../"
name = "route-table-001" # NOTE: Route table name is free text, best to create something meaningful.
resource_group_name = "rg-rtb-uks-001"
location = "uksouth"
routes = [
{
name = "internet",
address_prefix = "0.0.0.0/0",
next_hop_type = "Internet",
},
{
name = "firewall",
address_prefix = "10.0.0.0/16",
next_hop_type = "VirtualAppliance",
next_hop_in_ip_address = "10.0.0.4"
},
{
name = "route2", # NOTE: Route name is free text, best to create something meaningful.
address_prefix = "10.10.0.0/16",
next_hop_type = "VirtualAppliance",
next_hop_in_ip_address = "10.10.0.4"
}
]
bgp_route_propagation_enabled = false
tags = {}
}
父输出.tf
outputs.tf
output "id" {
value = module.route_table.id
description = "The Route Table configuration ID."
}
output "name" {
value = module.route_table.name
description = "The name of the Route Table."
}
output "routes" {
value = [module.route_table[*].routes[*].name]
description = "Blocks containing configuration of each route."
}
当我运行此命令时,我会创建其中包含路由的路由表,但路由名称的输出看起来像 Terraform 命令语法 -
toList([])
?
module.route_table.azurerm_route_table.this: Creation complete after 3s [id=/subscriptions/e286703f-8ba4-4a0d-bd44-8fb115bdebcd/resourceGroups/rg-rtb-uks-001/providers/Microsoft.Network/routeTables/route-table-001]
module.route_table.azurerm_route.routes["route2"]: Creating...
module.route_table.azurerm_route.routes["firewall"]: Creating...
module.route_table.azurerm_route.routes["internet"]: Creating...
module.route_table.azurerm_route.routes["internet"]: Creation complete after 3s [id=/subscriptions/e286703f-8ba4-4a0d-bd44-8fb115bdebcd/resourceGroups/rg-rtb-uks-001/providers/Microsoft.Network/routeTables/route-table-001/routes/internet]
module.route_table.azurerm_route.routes["route2"]: Creation complete after 6s [id=/subscriptions/e286703f-8ba4-4a0d-bd44-8fb115bdebcd/resourceGroups/rg-rtb-uks-001/providers/Microsoft.Network/routeTables/route-table-001/routes/route2]
module.route_table.azurerm_route.routes["firewall"]: Creation complete after 9s [id=/subscriptions/e286703f-8ba4-4a0d-bd44-8fb115bdebcd/resourceGroups/rg-rtb-uks-001/providers/Microsoft.Network/routeTables/route-table-001/routes/firewall]
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Outputs:
id = "/subscriptions/e286703f-8ba4-4a0d-bd44-8fb115bdebcd/resourceGroups/rg-rtb-uks-001/providers/Microsoft.Network/routeTables/route-table-001"
name = "route-table-001"
routes = [
tolist([]),
]
当我运行 destroy 时,表中的路由结构看起来不错,每个路由都清楚地有一个名称。
Terraform will perform the following actions:
# module.route_table.azurerm_route.routes["firewall"] will be destroyed
- resource "azurerm_route" "routes" {
- address_prefix = "10.0.0.0/16" -> null
- id = "/subscriptions/e286703f-8ba4-4a0d-bd44-8fb115bdebcd/resourceGroups/rg-rtb-uks-001/providers/Microsoft.Network/routeTables/route-table-001/routes/firewall" -> null
- name = "firewall" -> null
- next_hop_in_ip_address = "10.0.0.4" -> null
- next_hop_type = "VirtualAppliance" -> null
- resource_group_name = "rg-rtb-uks-001" -> null
- route_table_name = "route-table-001" -> null
}
# module.route_table.azurerm_route.routes["internet"] will be destroyed
- resource "azurerm_route" "routes" {
- address_prefix = "0.0.0.0/0" -> null
- id = "/subscriptions/e286703f-8ba4-4a0d-bd44-8fb115bdebcd/resourceGroups/rg-rtb-uks-001/providers/Microsoft.Network/routeTables/route-table-001/routes/internet" -> null
- name = "internet" -> null
- next_hop_type = "Internet" -> null
- resource_group_name = "rg-rtb-uks-001" -> null
- route_table_name = "route-table-001" -> null
# (1 unchanged attribute hidden)
}
# module.route_table.azurerm_route.routes["route2"] will be destroyed
- resource "azurerm_route" "routes" {
- address_prefix = "10.10.0.0/16" -> null
- id = "/subscriptions/e286703f-8ba4-4a0d-bd44-8fb115bdebcd/resourceGroups/rg-rtb-uks-001/providers/Microsoft.Network/routeTables/route-table-001/routes/route2" -> null
- name = "route2" -> null
- next_hop_in_ip_address = "10.10.0.4" -> null
- next_hop_type = "VirtualAppliance" -> null
- resource_group_name = "rg-rtb-uks-001" -> null
- route_table_name = "route-table-001" -> null
}
# module.route_table.azurerm_route_table.this will be destroyed
- resource "azurerm_route_table" "this" {
- bgp_route_propagation_enabled = true -> null
- disable_bgp_route_propagation = false -> null
- id = "/subscriptions/e286703f-8ba4-4a0d-bd44-8fb115bdebcd/resourceGroups/rg-rtb-uks-001/providers/Microsoft.Network/routeTables/route-table-001" -> null
- location = "uksouth" -> null
- name = "route-table-001" -> null
- resource_group_name = "rg-rtb-uks-001" -> null
- route = [
- {
- address_prefix = "0.0.0.0/0"
- name = "internet"
- next_hop_type = "Internet"
# (1 unchanged attribute hidden)
},
- {
- address_prefix = "10.0.0.0/16"
- name = "firewall"
- next_hop_in_ip_address = "10.0.0.4"
- next_hop_type = "VirtualAppliance"
},
- {
- address_prefix = "10.10.0.0/16"
- name = "route2"
- next_hop_in_ip_address = "10.10.0.4"
- next_hop_type = "VirtualAppliance"
},
] -> null
- subnets = [] -> null
- tags = {
- "classification" = null
- "costcentre" = null
- "createdon" = null
- "data_classification" = null
- "deployedby" = null
- "environment" = null
- "owner_contact" = null
- "region" = null
} -> null
}
Plan: 0 to add, 0 to change, 4 to destroy.
Changes to Outputs:
- id = "/subscriptions/e286703f-8ba4-4a0d-bd44-8fb115bdebcd/resourceGroups/rg-rtb-uks-001/providers/Microsoft.Network/routeTables/route-table-001" -> null
- name = "route-table-001" -> null
- routes = [
- [
- "internet",
- "firewall",
- "route2",
],
] -> null
有人可以告诉我我错过的细微差别吗?
是
routes = [
tolist([]),
]
试图告诉我做某事?
谢谢。
您正在使用
for_each
创建路由,这意味着输出将是键值对。有一个内置的 values
函数可以在这种情况下使用。例如:
output "routes" {
value = values(azurerm_route_table.this)[*].route
description = "Blocks containing configuration of each route."
}
应返回所有键值的
route
属性的值,用 [*]
表示。