【问题标题】:How to loop through locals and list at the same time to generate resources如何同时遍历locals和list来生成资源
【发布时间】:2020-11-09 17:44:18
【问题描述】:

我有以下 tf 文件:

locals {
  schemas = {
    "ODS" = {
      usage_roles = ["TRANSFORMER"]
    }
    "EXT" = {
      usage_roles = []
    }
    "INT" = {
      usage_roles = ["REPORTER"]
    }
    "DW" = {
      usage_roles = ["LOADER"]
    }
  }
}

resource "snowflake_schema" "schema" {
  for_each = local.schemas
  name = each.key
  database = ???????
  usage_roles = each.value.usage_roles
}

我想保持本地人的原样(每个模式的不同 usage_roles 并在此处硬编码),同时将多个值作为每个模式的数据库。在伪代码中是:

for database in ['db_1', 'db_2', 'db_3']:
    resource "snowflake_schema" "schema" {
      for_each = local.schemas
      name = each.key
      database = database
      usage_roles = each.value.usage_roles
    }

这样我们在三个不同的数据库中拥有相同的架构资源。我已经阅读了一些文章,这些文章使我相信可以进行此循环但预先分配所有值,这意味着我必须将 usage_roles 放在一个列表或其他东西中,而不是在本地硬编码,我认为这是可读性较差。例如: Terraform - how to use for_each loop on a list of objects to create resources

我所要求的甚至可能吗?如果是这样,怎么做?提前非常感谢您

【问题讨论】:

    标签: terraform


    【解决方案1】:

    for_each 的主要要求是您提供的地图必须为您要创建的资源的每个实例提供一个元素。在您的情况下,我认为这意味着您需要一个地图,其中每个数据库和架构组合都有一个元素。

    在两组中查找每个值组合的操作正式称为cartesian product,Terraform 有the setproduct function 来执行该操作。在您的情况下,应用它的两个集合是数据库名称集合和模式映射中的键集合,如下所示:

    locals {
      databases = toset(["db_1", "db_2", "db_3"])
    
      database_schemas = [
        for pair in setproduct(local.databases, keys(local.schemas)) : {
          database_name = pair[0]
          schema_name   = pair[1]
          usage_roles   = local.schemas[pair[1]].usage_roles
        }
      ]
    }
    

    local.database_schemas 值将包含每个组合的对象,如下所示:

    [
      {
        database_name = "db_1"
        schema_name   = "ODS"
        usage_roles   = ["TRANSFORMER"]
      },
      {
        database_name = "db_1"
        schema_name   = "EXT"
        usage_roles   = []
      },
      # ...
      {
        database_name = "db_2"
        schema_name   = "ODS"
        usage_roles   = ["TRANSFORMER"]
      },
      {
        database_name = "db_2"
        schema_name   = "EXT"
        usage_roles   = []
      },
      # ...
      {
        database_name = "db_3"
        schema_name   = "ODS"
        usage_roles   = ["TRANSFORMER"]
      },
      {
        database_name = "db_3"
        schema_name   = "EXT"
        usage_roles   = []
      },
      # ...
    ]
    

    这满足了您要创建的每个实例具有一个元素的要求,但是我们仍然需要将其转换为每个元素具有唯一键的地图,以便为 Terraform 提供每个实例的唯一跟踪键,因此我们可以做一个for_each 参数中的更多 for 投影:

    resource "snowflake_schema" "schema" {
      for_each = {
        for s in local.database_schemas :
        "${s.database_name}:${s.schema_name}" => s
      }
    
      name        = each.value.schema_name
      database    = each.value.database_name
      usage_roles = each.value.usage_roles
    }
    

    Terraform 将使用如下地址跟踪这些实例:

    • snowflake_schema.schema["db_1:ODS"]
    • snowflake_schema.schema["db_1:EXT"]
    • ...
    • snowflake_schema.schema["db_2:ODS"]
    • snowflake_schema.schema["db_2:EXT"]
    • ...
    • snowflake_schema.schema["db_3:ODS"]
    • snowflake_schema.schema["db_3:EXT"]
    • ...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-17
      • 1970-01-01
      • 2014-01-26
      • 2018-08-16
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      相关资源
      最近更新 更多