Terraform根据字典创建列表

时间:2020-08-28 06:57:58

标签: terraform terraform-provider-aws

我遇到以下问题。我创建一个本地变量,如:

variable vpcs {
  type = map
  default = {
    "tftest" = {
      "cidr" = "10.1.0.0/16",
      "tags" = {
        "cost"    = "shared",
        "service" = "TEST"
      }
    }
  }
}

data "aws_availability_zones" "azs" {
  state = "available"
}

variable subnets {
  type = map
  default = {
    "pub1"  = { "subnet" = 0, "rttable" = "public" },
    "pub2"  = { "subnet" = 1, "rttable" = "public" },
    "priv1" = { "subnet" = 2, "rttable" = "default" },
    "priv2" = { "subnet" = 3, "rttable" = "default" }
  }
}

locals {
  vpc_subnet_var = flatten([
    for v in keys(var.vpcs) : [
      for s in keys(var.subnets) : {
        network_name   = v
        tags           = var.vpcs[v]["tags"]
        subnet_name    = format("%v_%s", v, s)
        subnet_cidr    = cidrsubnet(var.vpcs[v]["cidr"], 8, var.subnets[s]["subnet"])
        subnet_az      = element(local.my_azs, var.subnets[s]["subnet"] % 2)
        subnet_rttable = var.subnets[s]["rttable"]
      }
    ]
  ])
  prefix = "${var.prefix}-${terraform.workspace}-tf"
  common_tags = {
    Environment = terraform.workspace
    Project     = var.project
    ManagedBy   = "Terraform"
  }
  my_azs = slice(data.aws_availability_zones.azs.names, 0, 2)
}

resource "aws_vpc" "test" {
  for_each   = var.vpcs
  cidr_block = each.value["cidr"]
  tags = merge(each.value["tags"],
    {
      Name = each.key
  })
}

resource "aws_subnet" "test" {
  for_each = {
    for s in local.vpc_subnet_var : s.subnet_name => s
  }
  vpc_id            = aws_vpc.test[each.value.network_name].id
  availability_zone = each.value.subnet_az
  cidr_block        = each.value.subnet_cidr
  tags = merge(each.value.tags,
    {
      Name = each.value.subnet_name
  })
}

示例测试输出为:

test                = [
      + {
          + tftest_priv1 = {
              + arn                             = (known after apply)
              + assign_ipv6_address_on_creation = false
              + availability_zone               = "eu-west-1a"
              + availability_zone_id            = (known after apply)
              + cidr_block                      = "10.1.2.0/24"
              + id                              = (known after apply)
              + ipv6_cidr_block                 = (known after apply)
              + ipv6_cidr_block_association_id  = (known after apply)
              + map_public_ip_on_launch         = false
              + owner_id                        = (known after apply)
              + tags                            = {
                  + "Name"    = "tftest_priv1"
                  + "cost"    = "shared"
                  + "service" = "TEST"
                }
              + timeouts                        = null
              + vpc_id                          = (known after apply)
            }
          + tftest_priv2 = {
              + arn                             = (known after apply)
              + assign_ipv6_address_on_creation = false
              + availability_zone               = "eu-west-1b"
              + availability_zone_id            = (known after apply)
              + cidr_block                      = "10.1.3.0/24"
              + id                              = (known after apply)
              + ipv6_cidr_block                 = (known after apply)
              + ipv6_cidr_block_association_id  = (known after apply)
              + map_public_ip_on_launch         = false
              + owner_id                        = (known after apply)
              + tags                            = {
                  + "Name"    = "tftest_priv2"
                  + "cost"    = "shared"
                  + "service" = "TEST"
                }
              + timeouts                        = null
              + vpc_id                          = (known after apply)
            }
          + tftest_pub1  = {
              + arn                             = (known after apply)
              + assign_ipv6_address_on_creation = false
              + availability_zone               = "eu-west-1a"
              + availability_zone_id            = (known after apply)
              + cidr_block                      = "10.1.0.0/24"
              + id                              = (known after apply)
              + ipv6_cidr_block                 = (known after apply)
              + ipv6_cidr_block_association_id  = (known after apply)
              + map_public_ip_on_launch         = false
              + owner_id                        = (known after apply)
              + tags                            = {
                  + "Name"    = "tftest_pub1"
                  + "cost"    = "shared"
                  + "service" = "TEST"
                }
              + timeouts                        = null
              + vpc_id                          = (known after apply)
            }
          + tftest_pub2  = {
              + arn                             = (known after apply)
              + assign_ipv6_address_on_creation = false
              + availability_zone               = "eu-west-1b"
              + availability_zone_id            = (known after apply)
              + cidr_block                      = "10.1.1.0/24"
              + id                              = (known after apply)
              + ipv6_cidr_block                 = (known after apply)
              + ipv6_cidr_block_association_id  = (known after apply)
              + map_public_ip_on_launch         = false
              + owner_id                        = (known after apply)
              + tags                            = {
                  + "Name"    = "tftest_pub2"
                  + "cost"    = "shared"
                  + "service" = "TEST"
                }
              + timeouts                        = null
              + vpc_id                          = (known after apply)
            }
        },
    ]

现在,我要使用创建的子网在专用子网中创建db_subnet_group,例如:

resource "aws_db_subnet_group" "main" {
  name = "${local.prefix}-main"
 subnet_ids = [ 
    aws_subnet.test["tftest_priv1"].id,
    aws_subnet.test["tftest_priv2"].id
  ]
}

但是当然不能使用固定值:)我想到了使用动态块,但这不起作用:/

resource "aws_db_subnet_group" "main" {
  name = "${local.prefix}-main"
  dynamic "subnet_ids" {
      for_each = {
            for s in local.vpc_subnet_var : s.subnet_az => s... if s.subnet_rttable == "public"
        }
  content {
      subnet_ids = aws_subnet.test[s.subnet_name].id
  }
  }

我能够获得所需的ID,例如在我的输出示例中:

output "test" {
    value = [for s in local.vpc_subnet_var : {
        subnet_ids = aws_subnet.test[s.subnet_name].id
    } if s.subnet_rttable == "default"
    ]
}
------------------------ OUTPUT ------------------------
  + test                = [
      + {
          + subnet_ids = (known after apply)
        },
      + {
          + subnet_ids = (known after apply)
        },
    ]

但是我如何仅获取ID并将其放入[[“ priv_subnet_id1”,“ priv_subnet_id2”]等列表中...要使用它,例如在aws_db_subnet_group资源中?大概创建另一个本地吗?

希望您能理解问题:D我现在尝试了很多事情,但没有成功。如果您需要更多输入,请告诉我(这是我关于stackoverflow的第一个问题)

Thx, 丹尼尔

1 个答案:

答案 0 :(得分:0)

根据现有数据,我认为(假设我没有误解这个问题),您非常接近。

我没有aws_subnet.test,因此无法完全复制或验证结果,但是我认为以下内容应导致产生一个子网ID列表。我设置了一个private_subnets_list局部变量:

locals {

  private_subnets_list = [
      for s in local.vpc_subnet_var:
        aws_subnet.test[s.subnet_name].id if s.subnet_rttable == "default"]

}

以上假设aws_subnet.test[s.subnet_name].id是正确的,并且aws_subnet.tests.subnet_name索引了。

然后创建子网组,可以尝试以下操作:

resource "aws_db_subnet_group" "main" {
  name = "${local.prefix}-main"
  subnet_ids = local.private_subnets_list
}