Terraform 变量循环生成属性
Terraform Variable looping to generate properties
我不得不承认,这是我第一次不得不问一些我自己都不知道如何提出或解释的问题,所以这是我的代码。
值得解释的是,由于特定原因我不能更改输出资源,发送到资源的元数据必须保持原样,否则会导致重新创建,我不希望那样。
目前我有一个 terraform 代码使用 static/fixed 像这样的变量
user1_name="Ed"
user1_Age ="10"
user2_name="Mat"
user2_Age ="20"
然后这些硬类型变量在多个地方使用,但最重要的是它们作为元数据传递给实例,就像这样
resource "google_compute_instance_template" "mytemplate" {
...
metadata = {
othervalues = var.other
user1_name = var.user1_name
user1_Age = var.user1_Age
user2_name = var.user2_name
user2_Age = var.user2_Age
}
...
}
我不是 terraform 方面的专家,所以我问,但我知道事实上这是 100% 丑陋和错误的,我需要使用列表或数组或其他任何东西,所以我将我的声明更改为:
users = [
{ "name" : "yo", "age" : "10", "last" : "other" },
{ "name" : "El", "age" : "20", "last" : "other" }
]
但是,我该如何为该资源生成相同的结果?生成的资源必须仍然具有与所示相同的元数据。
当然假设用户的顺序将用作值的“索引”,第一个得到 user1_name 等等......
我假设我需要在其中使用 for_each 循环,但无法弄清楚如何绕过资源属性中的循环
不确定我是否清楚这一点,可能没有,但没有找到更好的解释方式。
metadata
不是块,而是 map
类型的常规属性。所以你可以这样做:
# it would be better to use map, not list for users:
variable "users"
default {
user1 = { "name" : "yo", "age" : "10", "last" : "other" },
user2 = { "name" : "El", "age" : "20", "last" : "other" }
}
}
resource "google_compute_instance_template" "mytemplate" {
for_each = var.users
metadata = each.value
#...
}
从你的例子来看,你的意图似乎是让这些最终都显示为一个单一的地图,其中的键由两部分组成。
你的例子没有说明 user1
和 Ed
之间的关系,但是:你的第一个例子显示“user1's”的名字是 Ed,但是在你的数据例子中您要创建的结构只有一个“名称”,我不清楚该名称是否会替换第一个示例中的“user1”或“Ed”。
相反,我将采用一个略有不同的变量结构,该结构仍然保持像“user1”这样的键 和 name 属性,如下所示:
variable "users" {
type = map(object({
name = string
age = number
})
}
locals {
# First we'll transform the map of objects into a
# flat set of key/attribute/value objects, because
# that's easier to work with when we generate the
# flattened map below.
users_flat = flatten([
for key, user in var.users : [
for attr, value in user : {
key = key
attr = attr
value = value
}
]
])
}
resource "google_compute_instance_template" "mytemplate" {
metadata = merge(
{
othervalues = var.other
},
{
for vo in local.users_flat : "${vo.key}_${vo.attr}" => vo.value
}
)
}
local.users_flat
这里是一个中间数据结构,它将输入中的键和对象属性的 two-level 层次结构展平。它的形状应该是这样的:
[
{ key = "user1", attr = "name", value = "Ed" },
{ key = "user1", attr = "age", value = 10 },
{ key = "user2", attr = "name", value = "Mat" },
{ key = "user2", attr = "age", value = 20 },
]
metadata
参数中的 merge
调用然后将“其他值”的 directly-configured 映射与从 local.users_flat
派生的生成映射合并,形状如下:
{
"user1_name" = "Ed"
"user1_age" = 10
"user2_name" = "Mat"
"user2_age" = 20
}
从模块调用者的角度来看,users
变量应该定义如下值才能得到上面的结果:
users = {
user1 = {
name = "Ed"
age = 10
}
user2 = {
name = "Mat"
age = 20
}
}
我不得不承认,这是我第一次不得不问一些我自己都不知道如何提出或解释的问题,所以这是我的代码。 值得解释的是,由于特定原因我不能更改输出资源,发送到资源的元数据必须保持原样,否则会导致重新创建,我不希望那样。
目前我有一个 terraform 代码使用 static/fixed 像这样的变量
user1_name="Ed"
user1_Age ="10"
user2_name="Mat"
user2_Age ="20"
然后这些硬类型变量在多个地方使用,但最重要的是它们作为元数据传递给实例,就像这样
resource "google_compute_instance_template" "mytemplate" {
...
metadata = {
othervalues = var.other
user1_name = var.user1_name
user1_Age = var.user1_Age
user2_name = var.user2_name
user2_Age = var.user2_Age
}
...
}
我不是 terraform 方面的专家,所以我问,但我知道事实上这是 100% 丑陋和错误的,我需要使用列表或数组或其他任何东西,所以我将我的声明更改为:
users = [
{ "name" : "yo", "age" : "10", "last" : "other" },
{ "name" : "El", "age" : "20", "last" : "other" }
]
但是,我该如何为该资源生成相同的结果?生成的资源必须仍然具有与所示相同的元数据。 当然假设用户的顺序将用作值的“索引”,第一个得到 user1_name 等等......
我假设我需要在其中使用 for_each 循环,但无法弄清楚如何绕过资源属性中的循环
不确定我是否清楚这一点,可能没有,但没有找到更好的解释方式。
metadata
不是块,而是 map
类型的常规属性。所以你可以这样做:
# it would be better to use map, not list for users:
variable "users"
default {
user1 = { "name" : "yo", "age" : "10", "last" : "other" },
user2 = { "name" : "El", "age" : "20", "last" : "other" }
}
}
resource "google_compute_instance_template" "mytemplate" {
for_each = var.users
metadata = each.value
#...
}
从你的例子来看,你的意图似乎是让这些最终都显示为一个单一的地图,其中的键由两部分组成。
你的例子没有说明 user1
和 Ed
之间的关系,但是:你的第一个例子显示“user1's”的名字是 Ed,但是在你的数据例子中您要创建的结构只有一个“名称”,我不清楚该名称是否会替换第一个示例中的“user1”或“Ed”。
相反,我将采用一个略有不同的变量结构,该结构仍然保持像“user1”这样的键 和 name 属性,如下所示:
variable "users" {
type = map(object({
name = string
age = number
})
}
locals {
# First we'll transform the map of objects into a
# flat set of key/attribute/value objects, because
# that's easier to work with when we generate the
# flattened map below.
users_flat = flatten([
for key, user in var.users : [
for attr, value in user : {
key = key
attr = attr
value = value
}
]
])
}
resource "google_compute_instance_template" "mytemplate" {
metadata = merge(
{
othervalues = var.other
},
{
for vo in local.users_flat : "${vo.key}_${vo.attr}" => vo.value
}
)
}
local.users_flat
这里是一个中间数据结构,它将输入中的键和对象属性的 two-level 层次结构展平。它的形状应该是这样的:
[
{ key = "user1", attr = "name", value = "Ed" },
{ key = "user1", attr = "age", value = 10 },
{ key = "user2", attr = "name", value = "Mat" },
{ key = "user2", attr = "age", value = 20 },
]
metadata
参数中的 merge
调用然后将“其他值”的 directly-configured 映射与从 local.users_flat
派生的生成映射合并,形状如下:
{
"user1_name" = "Ed"
"user1_age" = 10
"user2_name" = "Mat"
"user2_age" = 20
}
从模块调用者的角度来看,users
变量应该定义如下值才能得到上面的结果:
users = {
user1 = {
name = "Ed"
age = 10
}
user2 = {
name = "Mat"
age = 20
}
}