![](/img/trans.png)
[英]Terraform: Local list of maps iteration with for_each and conditionals
[英]Terraform issues when using for_each local variable created based on another local
我正在嘗試使用引用數據資源的本地人創建 azure keyvault 秘密。 我正在遍歷一個包含我的環境的數組並創建一個映射列表,其中每個項目都是給定環境的一組秘密。 使用另一個本地,然后我通過創建兩個列表(一個帶有鍵,另一個帶有值)然后壓縮它們,繼續將這些映射合並為一個。
我最終在第二個本地使用 for_each 來創建資源。
如果我在沒有創建實際秘密資源(“azurerm_key_vault_secret”)的情況下運行我的根模塊,並且第二次使用它,一切正常。
如果我嘗試在一個 go 中完成所有操作,因為我想在我的 CI/CD 上實現,我會收到錯誤消息:
|錯誤:無效的 for_each 參數
|在 variables.tf 第 239 行,在資源“azurerm_key_vault_secret”“example”中:
│239: for_each = nonsensitive(local.example_map)
│ local.example_map apply后才知道
| “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 的 arguments。 for_each 中使用的值用於標識資源實例,並且將始終在 UI output 中公開,這就是不允許使用敏感值的原因。 嘗試將敏感值用作 for_each arguments 將導致錯誤。(訪問https://www.terraform.io/language/meta-arguments/for_each#limitations-on-values-used-in-for_each )
如果輸入敏感, 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
才會起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.