Terraform 如何有条件地向动态标记添加属性?
在config.meta文件中,我存储了对google bigquery数据集的访问。Terraform 如何有条件地向动态标记添加属性?,terraform,Terraform,在config.meta文件中,我存储了对google bigquery数据集的访问。访问对象是一个字典列表,其中每个字典都包含作为第一个元素和第二个元素元素的角色(例如特殊组或通过电子邮件对组),这些元素在列表中变化 我的目标是动态地应用访问。当访问列表上的每个字典都有相同的第二个元素时(例如,仅特殊组),这种方法非常简单但如何动态应用它们取决于第二个元素名称/值? # config.meta file { "accesses": [ { "ro
访问
对象是一个字典列表,其中每个字典都包含作为第一个元素和第二个元素元素的角色(例如特殊组
或通过电子邮件对组
),这些元素在列表中变化
我的目标是动态地应用访问。当访问
列表上的每个字典都有相同的第二个元素时(例如,仅特殊组
),这种方法非常简单但如何动态应用它们取决于第二个元素名称/值?
# config.meta file
{
"accesses": [
{
"role": "OWNER",
"special_group": "projectOwners"
},
{
"role": "READER",
"group_by_email": "myemail@myemail.com"
},
...
]
...
}
地形文件:
resource "google_bigquery_dataset" "dataset" {
dataset_id = "${var.dataset}"
location = "${var.bq_region}"
friendly_name = "${var.dataset}"
dynamic "access" {
# get accesses (list of dictionaries) from a file
for_each = [for a in jsondecode(file("$config.meta"))["access"]: {
role = a.role
special_group = a.special_group
# how to get special_group/group_by name conditionally?
# like: if dictionary has the key 'special_group' create that variable
# othervise create 'group_by_name'
}]
content {
role = access.value.role
special_group = access.value.special_group
# how to get special_group/group_by name conditionally?
# like: if the 'special_group' had been declared add 'special_group' to the access block
# othervise add 'group_by_name'.
}
}
}
如何有条件地向动态标记添加属性
locals {
items = fileexists("$config.meta") ? jsondecode(file("$config.meta")).accesses : []
special_groups = [for v in local.items: v if lookup(v, "special_group", "") != ""]
group_by_emails = [for v in local.items: v if lookup(v, "group_by_email", "") != ""]
}
您可以使用动态块的多个定义
resource "google_bigquery_dataset" "dataset" {
...
dynamic "access" {
for_each = [for a in local.special_groups: {
role = lookup(a, "role", "")
special_group = lookup(a, "special_group", "")
}]
content {
role = access.value.role
special_group = access.value.special_group
}
}
dynamic "access" {
for_each = [for a in local.group_by_emails: {
role = lookup(a, "role", "")
group_by_email = lookup(a, "group_by_email", "")
}]
content {
role = access.value.role
group_by_email = access.value.group_by_email
}
}
}
您可以使用动态块的多个定义
resource "google_bigquery_dataset" "dataset" {
...
dynamic "access" {
for_each = [for a in local.special_groups: {
role = lookup(a, "role", "")
special_group = lookup(a, "special_group", "")
}]
content {
role = access.value.role
special_group = access.value.special_group
}
}
dynamic "access" {
for_each = [for a in local.group_by_emails: {
role = lookup(a, "role", "")
group_by_email = lookup(a, "group_by_email", "")
}]
content {
role = access.value.role
group_by_email = access.value.group_by_email
}
}
}
在Terraform的配置块中,省略可选参数并将该参数设置为null
是等效的。因为access
是一个嵌套块,我们可以利用它来编写有条件地设置参数的表达式
dynamic "access" {
# get accesses (list of dictionaries) from a file
for_each = [for a in jsondecode(file("$config.meta"))["access"]: {
role = a.role
special_group = try(a.special_group, null)
group_by_email = try(a.group_by_email, null)
}]
content {
role = access.value.role
special_group = access.value.special_group
group_by_email = access.value.group_by_email
}
}
这首先使用,以便丢失的属性将导致返回到null
值,而不是错误。这意味着生成的对象将如下所示:
[
{
"role": "OWNER",
"special_group": "projectOwners",
"group_by_name": null,
},
{
"role": "READER",
"special_group": null,
"group_by_email": "myemail@myemail.com",
},
]
在内容
块中,我们直接分配所有这些内容。由于我前面描述的行为,null
将被Terraform视为根本没有设置。(请注意,在构造对象值时,将null
视为unset的行为不适用:这是一种特殊行为,仅适用于块内的直接参数。)
这将产生与直接写出以下两个access
块相同的效果:
access {
role = "OWNER"
special_group = "projectOwners"
}
access {
role = "READER"
group_by_email = "myemail@myemail.com"
}
在Terraform的配置块中,省略可选参数并将该参数设置为null
是等效的。因为access
是一个嵌套块,我们可以利用它来编写有条件地设置参数的表达式
dynamic "access" {
# get accesses (list of dictionaries) from a file
for_each = [for a in jsondecode(file("$config.meta"))["access"]: {
role = a.role
special_group = try(a.special_group, null)
group_by_email = try(a.group_by_email, null)
}]
content {
role = access.value.role
special_group = access.value.special_group
group_by_email = access.value.group_by_email
}
}
这首先使用,以便丢失的属性将导致返回到null
值,而不是错误。这意味着生成的对象将如下所示:
[
{
"role": "OWNER",
"special_group": "projectOwners",
"group_by_name": null,
},
{
"role": "READER",
"special_group": null,
"group_by_email": "myemail@myemail.com",
},
]
在内容
块中,我们直接分配所有这些内容。由于我前面描述的行为,null
将被Terraform视为根本没有设置。(请注意,在构造对象值时,将null
视为unset的行为不适用:这是一种特殊行为,仅适用于块内的直接参数。)
这将产生与直接写出以下两个access
块相同的效果:
access {
role = "OWNER"
special_group = "projectOwners"
}
access {
role = "READER"
group_by_email = "myemail@myemail.com"
}
这会起作用,但会增加复杂性。请参阅Martin Atkins答案,以获得更简单的解决方案和对底层机制更完整的解释。这将起作用,但会增加复杂性。参见Martin Atkins答案,以获得更简单的解决方案和对基本力学的更完整解释。