[英]Terraform issues when using for_each local variable created based on another local
I am trying to create azure keyvault secrets using locals which reference data resources.我正在尝试使用引用数据资源的本地人创建 azure keyvault 秘密。 I am iterating over an array containing my environments and creating a list of maps where each item is the set of secrets for a given environment.
我正在遍历一个包含我的环境的数组并创建一个映射列表,其中每个项目都是给定环境的一组秘密。 Using another local, I then proceed to merge these maps into a single one by creating two lists, one with keys and another with values and then zipping them.
使用另一个本地,然后我通过创建两个列表(一个带有键,另一个带有值)然后压缩它们,继续将这些映射合并为一个。
I finally use for_each on the second local to create the resource.我最终在第二个本地使用 for_each 来创建资源。
If I run my root module without creating the actual secret resources ("azurerm_key_vault_secret) and a second time with it, it all works fine.如果我在没有创建实际秘密资源(“azurerm_key_vault_secret”)的情况下运行我的根模块,并且第二次使用它,一切正常。
If I try to do it all in one go, as I want to implement on my CI/CD I get the error message:如果我尝试在一个 go 中完成所有操作,因为我想在我的 CI/CD 上实现,我会收到错误消息:
|Error: Invalid for_each argument |错误:无效的 for_each 参数
|on variables.tf line 239, in resource “azurerm_key_vault_secret” “example”: |在 variables.tf 第 239 行,在资源“azurerm_key_vault_secret”“example”中:
│239: for_each = nonsensitive(local.example_map) │239: for_each = nonsensitive(local.example_map)
│ local.example_map will be known only after apply │ local.example_map apply后才知道
| | The “for_each” value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created.
“for_each”值取决于资源属性,直到应用时才能确定,因此 Terraform 无法预测将创建多少个实例。 To work around this, use the -target argument to first apply only the resources that the for_each depends on.
要解决此问题,请使用 -target 参数首先仅应用 for_each 所依赖的资源。
If anybody has any idea how i could make work.如果有人知道我该如何工作。 It seems to me that this data transformation within locals doesn't quite work.
在我看来,本地人内部的这种数据转换并不十分有效。 Maybe I am going about the whole thing wrong.
也许我做错了整件事。 Any pointers would be highly appreciated.
任何指针将不胜感激。
Here is the code I am trying to make work:这是我试图使工作的代码:
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",
}
]
}
Also what confuses me the most is that if I work with the following data structure, which is hard coding instead of doing the first transformation based on namespaces.同样让我最困惑的是,如果我使用以下数据结构,这是硬编码而不是基于名称空间进行第一次转换。 The entry getting information from another module doesn't cause any problems and it all works wonderfully.
从另一个模块获取信息的条目不会导致任何问题,而且一切都很好。
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"
}
if the resulting data structure is the same, why for_each works for one and not for the other?如果生成的数据结构相同,为什么 for_each 只适用于一个而不适用于另一个? [1]: https://i.stack.imgur.com/cTq5f.png
[1]: https://i.stack.imgur.com/cTq5f.png
from the doc从文档
Sensitive values, such as sensitive input variables, sensitive outputs, or sensitive resource attributes, cannot be used as arguments to for_each.
敏感值,例如敏感输入变量、敏感输出或敏感资源属性,不能用作 for_each 的 arguments。 The value used in for_each is used to identify the resource instance and will always be disclosed in UI output, which is why sensitive values are not allowed.
for_each 中使用的值用于标识资源实例,并且将始终在 UI output 中公开,这就是不允许使用敏感值的原因。 Attempts to use sensitive values as for_each arguments will result in an error.(visite https://www.terraform.io/language/meta-arguments/for_each#limitations-on-values-used-in-for_each )
尝试将敏感值用作 for_each arguments 将导致错误。(访问https://www.terraform.io/language/meta-arguments/for_each#limitations-on-values-used-in-for_each )
Keys ()
will always return a sensitive value if the input is sensitive, so instead try the following:如果输入敏感,
Keys ()
将始终返回敏感值,因此请尝试以下操作:
example_map = zipmap(
flatten(
[for item,value in local.example : item]
),
flatten(
[for item, value in local.example : value]
)
) )
This is probably because of module.some_module.connection_string
.这可能是因为
module.some_module.connection_string
。 You can't use dynamic values in for_each
.您不能在
for_each
中使用动态值。 As the error message says, you have to use target to first create those dynamic resources, and then your for_each
will work.正如错误消息所说,您必须先使用target创建那些动态资源,然后您的
for_each
才会起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.