使用基于另一个局部创建的for_each局部变量时,Terraform会出现问题



我正在尝试使用引用数据资源的本地创建azure密钥库机密。我正在迭代一个包含我的环境的数组,并创建一个映射列表,其中每个项目都是给定环境的一组秘密。然后,我使用另一个本地映射,通过创建两个列表,一个带有键,另一个带有值,然后压缩它们,将这些映射合并为一个列表。

最后,我在第二个本地上使用for_each来创建资源。

如果我在不创建实际秘密资源("azurerm_key_vault_secret"(的情况下运行根模块,并再次使用它,那么一切都很好。

如果我试图一次完成所有操作,因为我想在CI/CD上实现,我会收到错误消息:

|错误:for_each参数无效

|在variables.tf第239行,在资源"azurerm_key_vault_secret"example"中:

│239:for_each=非敏感(local.example_map(

│local.example_map只有在应用后才能知道

|"for_each"值取决于在应用之前无法确定的资源属性,因此Terraform无法预测将创建多少实例。要解决此问题,请使用-target参数首先仅应用for_each所依赖的资源。

如果有人知道我该怎么做的话。在我看来,本地人内部的这种数据转换似乎不太奏效。也许我把整件事都做错了。任何建议都将不胜感激。

这是我试图使工作的代码:

variable "environment" {
default = [ "dev", "prod"]
}
locals {
example = distinct(flatten([
for namespace in var.environment : {
"${environment}-password1" = "${environment}-password",
"${environment}-password2" = "{"connection_string" : "${data.azurerm_storage_account.storage_account_example["${environment}"].primary_connection_string}"}",
"${environment}-password3" = "{"client_id" : "${jsondecode("${data.azurerm_key_vault_secret.other_credentials["${environment}"].value}").clients["example"].client_id}"}",
"${environment}-password4" = "{"password" : "${data.azurerm_key_vault_secret.k_password.value}"}",
"${environment}-password5" = "{"azurestorageaccountname" : "${data.azurerm_storage_account.example.name}", "azurestorageaccountkey" : "${data.azurerm_storage_account.example.primary_access_key}"}",
"${environment}-password6" = "{"connection_string" : "${module.some_module.connection_string}"}",
}]))
example_map = zipmap(
flatten(
[for item in local.example : keys(item)]
),
flatten(
[for item in local.example : values(item)]
)
)
}
resource "azurerm_key_vault_secret" "example" {
for_each     = nonsensitive(local.example_map)
name         = each.key
value        = each.value
key_vault_id = module.keyvault.id
content_type = "password"
}
Here is the data structures created by local.example and local.example_map

"example": {
"value": [
{
"dev-password1" = "dev-password",
"dev-password2" = "{"connection_string" : "DefaultEndpointsProtocol=https;AccountName=mystorage;AccountKey=blablablablblabalbalbalbalblablablablablalbalbalbl==;EndpointSuffix=foo.bar.net"}",
"dev-password3" = "{"client_id" : "myclientID"}",
"dev-password4" = "{"password" : "password123"}",
"dev-password5" = "{"azurestorageaccountname" : "somestorageaccount", "azurestorageaccountkey" : "XXXxxxxXXXXxxxxXXXxxxxxxe++++++NNNNNNNNNCCCccccccccccccccccc==}"}",
"dev-password6" = "{"connection_string" : "${module.some_module.connection_string}"}"
},
{
"prod-password1" = "prod-password",
"prod-password2" = "{"connection_string" : "DefaultEndpointsProtocol=https;AccountName=mystorage;AccountKey=blablablablblabalbalbalbalblablablablablalbalbalbl==;EndpointSuffix=foo.bar.net"}",
"prod-password3" = "{"client_id" : "myclientID"}",
"prod-password4" = "{"password" : "password123"}",
"prod-password5" = "{"azurestorageaccountname" : "somestorageaccount", "azurestorageaccountkey" : "XXXxxxxXXXXxxxxXXXxxxxxxe++++++NNNNNNNNNCCCccccccccccccccccc==}"}",
"prod-password6" = "{"connection_string" : "DefaultEndpointsProtocol=https;AccountName=yetanotherone;AccountKey=blablablablblabalbalbalbalblablablablablalbalbalbl==;EndpointSuffix=foo.bar.net"}"
}
]
}
"example_map": {
"value": {
"dev-password1" = "dev-password",
"dev-password2" = "{"connection_string" : "DefaultEndpointsProtocol=https;AccountName=mystorage;AccountKey=blablablablblabalbalbalbalblablablablablalbalbalbl==;EndpointSuffix=foo.bar.net"}",
"dev-password3" = "{"client_id" : "myclientID"}",
"dev-password4" = "{"password" : "password123"}",
"dev-password5" = "{"azurestorageaccountname" : "somestorageaccount", "azurestorageaccountkey" : "XXXxxxxXXXXxxxxXXXxxxxxxe++++++NNNNNNNNNCCCccccccccccccccccc==}"}",
"dev-password6" = "{"connection_string" : "DefaultEndpointsProtocol=https;AccountName=yetanotherone;AccountKey=blablablablblabalbalbalbalblablablablablalbalbalbl==;EndpointSuffix=foo.bar.net"}"
"prod-password1" = "prod-password",
"prod-password2" = "{"connection_string" : "DefaultEndpointsProtocol=https;AccountName=mystorage;AccountKey=blablablablblabalbalbalbalblablablablablalbalbalbl==;EndpointSuffix=foo.bar.net"}",
"prod-password3" = "{"client_id" : "myclientID"}",
"prod-password4" = "{"password" : "password123"}",
"prod-password5" = "{"azurestorageaccountname" : "somestorageaccount", "azurestorageaccountkey" : "XXXxxxxXXXXxxxxXXXxxxxxxe++++++NNNNNNNNNCCCccccccccccccccccc==}"}",
"prod-password6" = "{"connection_string" : "DefaultEndpointsProtocol=https;AccountName=yetanotherone;AccountKey=blablablablblabalbalbalbalblablablablablalbalbalbl==;EndpointSuffix=foo.bar.net"}"
},
"type": [
"object",
{
"dev-password1": "string",
"dev-password2": "string",
"dev-password3": "string",
"dev-password4": "string",
"dev-password5": "string",
"dev-password6": "string",
"prod-password1": "string",
"prod-password2": "string",
"prod-password3": "string",
"prod-password4": "string",
"prod-password5": "string",
"prod-password6": "string",
}
]
}

最让我困惑的是,如果我使用以下数据结构,这是硬编码,而不是基于名称空间进行第一次转换。从另一个模块获取信息的条目不会引起任何问题,而且一切都很好。

locals {
hardcoding_namespaces = {
"dev-password1" = "dev-password"
"dev-password2" = "{"connection_string" : "${data.azurerm_storage_account.storage_account_example["dev"].primary_connection_string}"}"
"dev-password3" = "{"connection_string" : "${module.some_module.connection_string}"}"
"prod-password1" = "prod-password"
"prod-password2" = "{"connection_string" : "${data.azurerm_storage_account.storage_account_example["prod"].primary_connection_string}"}"
"prod-password3" = "{"connection_string" : "${module.some_module.connection_string}"}"
}
}
resource "azurerm_key_vault_secret" "another_example" {
for_each     = local.hardcoding_namespaces
name         = each.key
value        = each.value
key_vault_id = module.keyvault.id
content_type = "password"
} 

如果得到的数据结构是相同的,为什么for_each适用于其中一个而不适用于另一个?[1] :https://i.stack.imgur.com/cTq5f.png

来自文档

敏感值,如敏感输入变量、敏感输出或敏感资源属性,不能用作for_each的参数。for_each中使用的值用于标识资源实例,并且将始终在UI输出中公开,这就是为什么不允许使用敏感值的原因。尝试将敏感值用作for_each参数将导致错误。(请访问https://www.terraform.io/language/meta-arguments/for_each#limitations-对值-用于每个(

Keys ()将始终返回敏感值,如果输入是敏感的,请尝试以下操作:

example_map = zipmap(
flatten(
[for item,value in local.example : item]
),
flatten(
[for item, value in local.example : value]
)

)

这可能是因为module.some_module.connection_string。不能在for_each中使用动态值。正如错误消息所说,您必须使用target首先创建这些动态资源,然后您的for_each才能工作。

最新更新