簡體   English   中英

使用基於另一個本地創建的 for_each 本地變量時出現 Terraform 問題

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM