Terraform 元组到 map 转换

标签 terraform terraform-provider-aws

我是 Terraform 的新手,我正在使用此功能重新使用相同的子网列表来启动比我拥有的子网更多的实例。 (它只会循环)如果我提供我自己的子网映射,这很好用,但远程状态中的数据是一个元组,我收到此错误:
Invalid value for "inputMap" parameter: lookup() requires a map as the first argument. data.terraform_remote_state.vpc.outputs.private_subnets is tuple with 4 elements
我也试过 tomap( 函数,但这失败了:
Invalid value for "v" parameter: cannot convert tuple to map of any single type.
这是我的代码:

  count                  = var.instance_count
  ami                    = var.ami
  instance_type          = "t2.medium"
  subnet_id              = lookup(data.terraform_remote_state.vpc.outputs.private_subnets, count.index%length(data.terraform_remote_state.vpc.outputs.private_subnets))
  vpc_security_group_ids = ["${data.terraform_remote_state.foo_sg.outputs.foo_sg_id}"]
  key_name               = var.key_name
  iam_instance_profile   = var.iam_instance_profile

  user_data = <<-EOF
              #!/bin/bash
              hostnamectl set-hostname --static "${var.app_name}-${count.index + 1}.${data.terraform_remote_state.vpc.outputs.private_zone_domain_name}"
              echo "127.0.0.1 localhost.localdomain localhost4 localhost4.localdomain4 ${var.app_name}-${count.index + 1}.${data.terraform_remote_state.vpc.outputs.private_zone_domain_name} localhost" > hosts
              echo "::1 localhost localhost.localdomain localhost6 localhost6.localdomain6" >> hosts
              EOF

  tags = {
    Name                 = "${var.app_name}-${count.index +1}.${data.terraform_remote_state.vpc.outputs.private_zone_domain_name}"
}


就像我说的,我的目标是在我拥有的远程状态下重用 4 个子网,所以如果我想要 6 个实例,它将循环遍历我拥有的 4 个,第 5 个和第 6 个实例将位于元组中的子网 1 和 2 .任何建议,将不胜感激!

最佳答案

您有 3 种形式来制作循环。

1º 使用 dynamic block ... 例子:

resource "aws_security_group" "ecc_default" {
  count       = length(var.clusters)
  vpc_id      = var.vpc_id
  name        = "${terraform.workspace}.ecc-${var.clusters[count.index].engine}.sg"
  description = "${terraform.workspace}.ecc-${var.clusters[count.index].engine}.sg"

  ingress {
    from_port   = var.clusters[count.index].port
    to_port     = var.clusters[count.index].port
    protocol    = "tcp"
    cidr_blocks = [var.vpc_cidr]
  }

  dynamic "ingress" {
    iterator = item
    for_each = var.enable_vpn ? var.vpn_cidr : []

    content {
      from_port   = var.clusters[count.index].port
      to_port     = var.clusters[count.index].port
      protocol    = "tcp"
      cidr_blocks = [item.value["cidr"]]
      description = item.value["description"]
    }
  }
...
...
}

2º 使用 for_each ... ( click here for answer )

3º 使用算术迭代... ( click here for answer ) 示例:
resource "aws_security_group_rule" "ecc_internal" {
    count = length(var.ingress_security_groups) > 0 ? length(var.ingress_security_groups) * length(var.clusters) : 0
    security_group_id = aws_security_group.ecc_default[count.index % length(var.clusters)].id
    type = "ingress"
    from_port = var.clusters[count.index % length(var.clusters)].port
    to_port = var.clusters[count.index % length(var.clusters)].port
    protocol = "tcp"
    source_security_group_id = var.ingress_security_groups[floor(count.index / length(var.clusters))]
}

而且,对于转换错误:尝试使用 coalescelist 用假替换。像这样:
resource "aws_lb_listener_certificate" "default" {
  count           = (coalescelist(data.aws_alb_listener.https, [{ certificate_arn = "" }])[0].certificate_arn != var.certificate_arn) ? local.enabled : 0
  listener_arn    = coalescelist(data.aws_alb_listener.https, [{ arn = "" }])[count.index].arn
  certificate_arn = var.certificate_arn
}

元组 ( [N1, N2, N3] ) 到映射 ( {N1 = "", N2 = ""} ) 的转换实际上是不允许的。但是,您可以使用假替换来完成这项工作。 tomap 需要一个对象来论证。和 map , 需要多个参数才能得出结果。尝试操作您的列表,在 map 中转换,使用另一种形式(如果您只想转换,而不是解决问题):
environment_vars = jsonencode([
      for key in sort(keys(data.external.environment_vars.result)) : {
        name  = key
        value = lookup(data.external.environment_vars.result, key)
    }])

我为您推荐:Terraform tips & tricks: loops, if-statements, and gotchas

关于Terraform 元组到 map 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60010591/

相关文章:

postgresql - 使用 Terraform 在 AWS RDS PostgreSQL 上启用 PostGIS

amazon-web-services - Terraform - 确保根据是否还设置了另一个值来设置值

amazon-web-services - Terraform 无法将创建的集成附加到 API 网关的路由中

Terraform:如何从以前的 EC2 实例附加卷?

Terraform depend_on 另一个路径中的另一个模块

postgresql - 无法删除 Terraform 中包含提供程序的模块实例

amazon-sqs - 当 DLQ 尚不存在时,如何通过 Terraform 配置 SQS?

terraform - 如何对多个实例使用 Terraform provisioner

google-cloud-platform - 在计数条件中使用多个列表在 Terraform 中创建资源

amazon-web-services - Terraform 和 AWS Storage Gateway 磁盘出现问题