将变量(地图)转换/组合为地形中的局部变量
transforming / combining variables (maps) into locals in terraform
为了简化变量定义,我将子网和属性(如安全组)分组到字典列表中......然后有一层字典等......(或maps/objects)
这是一个示例定义 JSON:
"subnets": [
{
"name": "inside",
"prefix": "10.248.0.0/28",
"route_table": true,
"nsg": true,
"security_group_rules": [
{
"name": "AllowAllInbound",
"properties": {
"priority": 100,
"access": "Allow",
"direction": "Inbound",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "*",
"sourceAddressPrefix": "*",
"destinationAddressPrefix": "*"
}
}
]
}
对于这个单一的块,我希望能够 运行 通过循环构建子网,然后使用不同的资源块构建安全组。我遇到了各种各样的问题,无法对此进行迭代。
我想我应该和当地人一起做点什么,这样我就可以为每次操作提取我需要的东西
在子网端:
resource "azurerm_subnet" "subnet" {
for_each = var.subnets
name = each.value.name
resource_group_name = azurerm_resource_group.hub_network_rg.name
virtual_network_name = azurerm_virtual_network.hub_vnet.name
address_prefixes = [each.value.prefix]
}
由于变量类型的问题而不起作用:我将 'subnets' 变量定义为:
variable "subnets" {
type = list(object({
name = string
prefix = string
route_table = bool
nsg = bool
security_group_rules = map(list(string))
}))
}
我知道 TF 是松散类型的,但它不想遍历对象,因为它遇到了其他事情。
选项:
1.break 将其分解为单独的元素 - 我将再次 运行 进行分解,只是规模较小。
2. 找到一种方法来创建一个 local.subnets 地图和一个 local.security_groups 地图,该地图引用了我拥有的 var.subnets。
正在寻求有关 #2 的帮助。
类似于:
locals {
subnets = for k,v in var.subnets: [
{
name = var.subnet.name
prefix = var.subnet.prefix
}
我离题太远了,但我认为这已经解决了问题。我的大脑开始 Python 和 list/dict 理解,但我可以弄清楚如何使用 TF 做到这一点。感觉就在眼前,就是拼不出来语法。
Terraform for_each
只接受字符串集或字符串映射。传递 var
之类的列表之类的东西根本行不通。我建议做的是:
# Create a JSON like variable for your subnets. Notice, this variable is a list, the type of it is inferred, we don't need to complicate ourselves here
variable "subnets" {
default = [{
"name" : "inside",
"prefix" : "10.248.0.0/28",
"route_table" : true,
"nsg" : true,
"security_group_rules" : [
{
"name" : "AllowAllInbound",
"properties" : {
"priority" : 100,
"access" : "Allow",
"direction" : "Inbound",
"protocol" : "*",
"sourcePortRange" : "*",
"destinationPortRange" : "*",
"sourceAddressPrefix" : "*",
"destinationAddressPrefix" : "*"
}
}
]
}]
}
# Create a local which maps the name of the the subnet to the subnet itself
locals {
subnet_map = { for s in var.subnets: s.name => s }
}
# Create the resources
resource "azurerm_subnet" "subnet" {
for_each = toset([
for s in var.subnets: s.name
]) # Note, we create a set from the subnet names. We can use these names to read out properties from the map created above
name = each.value.name
resource_group_name = azurerm_resource_group.hub_network_rg.name
virtual_network_name = azurerm_virtual_network.hub_vnet.name
address_prefixes = [local.subnet_map[each.value].prefix] # We use the subnet names here
}
更新:
我们需要subnet_map
的原因是必须要有以下映射:
subnet_map = {
"inside" = {
"name" = "inside"
"nsg" = true
"prefix" = "10.248.0.0/28"
...
},
# you have only one subnet as the input, but if you had more than one the map will contain it
"other_subnet" = {
...
}
}
本质上,我们要将每个子网的name
映射到子网本身。正如我上面所说,我们需要它的原因是 for_each
只接受字符串集。此 toset([for s in var.subnets: s.name])
的值是一组子网名称,因此 set("inside")
,这意味着 for_each
将遍历子网名称并为每个子网名称创建一个 azurerm_subnet
.显然,我们需要有关子网的更多信息,而不仅仅是其名称。我们可以从 subnet_map
中获取我们需要的所有信息。这是因为如果我们提供子网的名称,我们可以从中获取一个对象。这正是该语句的作用:local.subnet_map[each.value].prefix
为了简化变量定义,我将子网和属性(如安全组)分组到字典列表中......然后有一层字典等......(或maps/objects)
这是一个示例定义 JSON:
"subnets": [
{
"name": "inside",
"prefix": "10.248.0.0/28",
"route_table": true,
"nsg": true,
"security_group_rules": [
{
"name": "AllowAllInbound",
"properties": {
"priority": 100,
"access": "Allow",
"direction": "Inbound",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "*",
"sourceAddressPrefix": "*",
"destinationAddressPrefix": "*"
}
}
]
}
对于这个单一的块,我希望能够 运行 通过循环构建子网,然后使用不同的资源块构建安全组。我遇到了各种各样的问题,无法对此进行迭代。
我想我应该和当地人一起做点什么,这样我就可以为每次操作提取我需要的东西
在子网端:
resource "azurerm_subnet" "subnet" {
for_each = var.subnets
name = each.value.name
resource_group_name = azurerm_resource_group.hub_network_rg.name
virtual_network_name = azurerm_virtual_network.hub_vnet.name
address_prefixes = [each.value.prefix]
}
由于变量类型的问题而不起作用:我将 'subnets' 变量定义为:
variable "subnets" {
type = list(object({
name = string
prefix = string
route_table = bool
nsg = bool
security_group_rules = map(list(string))
}))
}
我知道 TF 是松散类型的,但它不想遍历对象,因为它遇到了其他事情。
选项: 1.break 将其分解为单独的元素 - 我将再次 运行 进行分解,只是规模较小。 2. 找到一种方法来创建一个 local.subnets 地图和一个 local.security_groups 地图,该地图引用了我拥有的 var.subnets。
正在寻求有关 #2 的帮助。
类似于:
locals {
subnets = for k,v in var.subnets: [
{
name = var.subnet.name
prefix = var.subnet.prefix
}
我离题太远了,但我认为这已经解决了问题。我的大脑开始 Python 和 list/dict 理解,但我可以弄清楚如何使用 TF 做到这一点。感觉就在眼前,就是拼不出来语法。
Terraform for_each
只接受字符串集或字符串映射。传递 var
之类的列表之类的东西根本行不通。我建议做的是:
# Create a JSON like variable for your subnets. Notice, this variable is a list, the type of it is inferred, we don't need to complicate ourselves here
variable "subnets" {
default = [{
"name" : "inside",
"prefix" : "10.248.0.0/28",
"route_table" : true,
"nsg" : true,
"security_group_rules" : [
{
"name" : "AllowAllInbound",
"properties" : {
"priority" : 100,
"access" : "Allow",
"direction" : "Inbound",
"protocol" : "*",
"sourcePortRange" : "*",
"destinationPortRange" : "*",
"sourceAddressPrefix" : "*",
"destinationAddressPrefix" : "*"
}
}
]
}]
}
# Create a local which maps the name of the the subnet to the subnet itself
locals {
subnet_map = { for s in var.subnets: s.name => s }
}
# Create the resources
resource "azurerm_subnet" "subnet" {
for_each = toset([
for s in var.subnets: s.name
]) # Note, we create a set from the subnet names. We can use these names to read out properties from the map created above
name = each.value.name
resource_group_name = azurerm_resource_group.hub_network_rg.name
virtual_network_name = azurerm_virtual_network.hub_vnet.name
address_prefixes = [local.subnet_map[each.value].prefix] # We use the subnet names here
}
更新:
我们需要subnet_map
的原因是必须要有以下映射:
subnet_map = {
"inside" = {
"name" = "inside"
"nsg" = true
"prefix" = "10.248.0.0/28"
...
},
# you have only one subnet as the input, but if you had more than one the map will contain it
"other_subnet" = {
...
}
}
本质上,我们要将每个子网的name
映射到子网本身。正如我上面所说,我们需要它的原因是 for_each
只接受字符串集。此 toset([for s in var.subnets: s.name])
的值是一组子网名称,因此 set("inside")
,这意味着 for_each
将遍历子网名称并为每个子网名称创建一个 azurerm_subnet
.显然,我们需要有关子网的更多信息,而不仅仅是其名称。我们可以从 subnet_map
中获取我们需要的所有信息。这是因为如果我们提供子网的名称,我们可以从中获取一个对象。这正是该语句的作用:local.subnet_map[each.value].prefix