【问题标题】:How to sort / merge two maps in terraform如何在terraform中对两张地图进行排序/合并
【发布时间】:2020-09-04 06:20:45
【问题描述】:

有人可以帮我解决这个问题吗?我正在使用 terraform 12.28。

我有两张这样的地图:

instances = { 
  "instance1" = "us-east-1a"
  "instance2" = "us-east-1a"
  "instance3" = "us-east-1c"
  "instance4" = "us-east-1b"
  "instance5" = "us-east-1b"
  "instance6" = "us-east-1c"
}

snapshots = {
  "snap1" = "us-east-1c"
  "snap2" = "us-east-1b"
  "snap3" = "us-east-1b"
  "snap4" = "us-east-1c"
  "snap5" = "us-east-1a"
  "snap6" = "us-east-1a"
}

我想摆脱的是:

desired_result = {
  "instance1" = "snap5"
  "instance2" = "snap6"
  "instnace3" = "snap1"
  "instance4" = "snap2"
  "instance5" = "snap3" 
  "instance6" = "snap4"
}

我只需要确保实例具有来自同一个 az 的快照。任何想法将不胜感激!

【问题讨论】:

  • 它应该如何工作? instance6 具有 useast-1c 的 az。由于拼写错误,snapshots 中没有这样的 az。拼写错误是你任务的实际部分吗?
  • 还有instance2us-east-1a 的az。这样的 az 有两个快照?两个都要算,还是只算第一个,最后一个?
  • 我的错,这是一个错字。两张地图上的所有 az 都应该匹配。我已经更正了这个例子。

标签: sorting merge maps terraform


【解决方案1】:

您描述的结果是不可能的,因为您的查找值重叠。 Instance1instance2 都可能导致snap5snap6,因为它们都位于us-east-1a。其他可用区也是如此。获得实际结果的一种方法是反转列表之一并对值进行分组。在此之后,您可以使用该列表在另一个列表中查找相应的值。这是我的例子:

locals {
  instances = {
    "instance1" = "us-east-1a"
    "instance2" = "us-east-1a"
    "instance3" = "us-east-1c"
    "instance4" = "us-east-1b"
    "instance5" = "us-east-1b"
    "instance6" = "us-east-1c"
  }
  snapshots = {
    "snap1" = "us-east-1c"
    "snap2" = "us-east-1b"
    "snap3" = "us-east-1b"
    "snap4" = "us-east-1c"
    "snap5" = "us-east-1a"
    "snap6" = "us-east-1a"
  }
  # Reverse and group (...)
  reversed_snapshots = {
    for key, value in local.snapshots:
    value => key...
  }
}

output "result" {
  value = {
    for key, value in local.instances:
    # Match instance to snapshots by looking up az
    key => lookup(local.reversed_snapshots, value, null)
  }
}

结果与原始问题中的结果有些不同,因为每个实例基本上都可能具有位于同一 AZ 中的两个快照之一。公共标识符 AZ 具有重复值,因此也许您可以找到另一个唯一标识符,例如 snapshotID 或类似的东西。或者,两个快照可能与一个实例相关并不是问题。

result = {
  "instance1" = [
    "snap5",
    "snap6",
  ]
  "instance2" = [
    "snap5",
    "snap6",
  ]
  "instance3" = [
    "snap1",
    "snap4",
  ]
  "instance4" = [
    "snap2",
    "snap3",
  ]
  "instance5" = [
    "snap2",
    "snap3",
  ]
  "instance6" = [
    "snap1",
    "snap4",
  ]
}

【讨论】:

    【解决方案2】:

    正如您可能知道的那样,我试图将卷映射到同一可用区中的实例,以用于灾难恢复 terraform 脚本。原始(灾难前)集群有相同数量的实例分布在 3 个可用区之间。在发生灾难的情况下,我需要跨相同数量的可用区恢复集群,将节点保留到可用区组组合中。

    我不确定这是否是解决这个问题的最干净的方法,但这就是我最终要做的。如果有人有更好/更清洁的方式来做这件事,我仍然愿意接受建议,但我很高兴至少现在能做到这一点。

    首先,我最终创建了一个字符串映射的元组,基于这样的可用区域:

    instance_az = [
      flatten([for instance in aws_instance.cassandra: 
        map(
          instance.availability_zone,
          zipmap(
            matchkeys(
              tolist(aws_instance.cassandra.*.id),
              tolist(aws_instance.cassandra.*.availability_zone),  
              [instance.availability_zone]
            ),
            matchkeys(
              tolist(aws_ebs_volume.data.*.id),
              tolist(aws_ebs_volume.data.*.availability_zone),        
              [instance.availability_zone]
            )
          )
        )
      ])
    ]
    

    示例输出:

    instance_az = [
      [
        {
          "us-east-1c" = {
            "i-0a18b339d3f1ddd80" = "vol-0ace4794f40c256ed"
            "i-0bd9681b1b856c3db" = "vol-00f694635ef7b0904"
          }
        },
        {
          "us-east-1a" = {
            "i-033c004ed25dbd907" = "vol-0a31e52f2e11dfdef"
            "i-0ed01a562756800e9" = "vol-0a20cabb0ae568084"
          }
        },
        {
          "us-east-1b" = {
            "i-0400baef538ea327a" = "vol-060aff04e902f7005"
            "i-08ed6b26743a2bd95" = "vol-06917d88b07bd5d5c"
          }
        },
        {
          "us-east-1c" = {
            "i-0a18b339d3f1ddd80" = "vol-0ace4794f40c256ed"
            "i-0bd9681b1b856c3db" = "vol-00f694635ef7b0904"
          }
        },
        {
          "us-east-1a" = {
            "i-033c004ed25dbd907" = "vol-0a31e52f2e11dfdef"
            "i-0ed01a562756800e9" = "vol-0a20cabb0ae568084"
          }
        },
        {
          "us-east-1b" = {
            "i-0400baef538ea327a" = "vol-060aff04e902f7005"
            "i-08ed6b26743a2bd95" = "vol-06917d88b07bd5d5c"
          }
        },
      ],
    ]
    

    该输出的问题在于,每个可用区都使用完全相同的 instanceId->volumeId 映射列出了两次。接下来,我想删除重复项,所以我将其转换为这样的集合:

      inst_vol_to_set = {
        s = toset(local.instance_az[0])
      }
    

    现在我的输出如下所示:

    inst_vol_to_set = {
      "s" = [
        {
          "us-east-1a" = {
            "i-033c004ed25dbd907" = "vol-0a31e52f2e11dfdef"
            "i-0ed01a562756800e9" = "vol-0a20cabb0ae568084"
          }
        },
        {
          "us-east-1b" = {
            "i-0400baef538ea327a" = "vol-060aff04e902f7005"
            "i-08ed6b26743a2bd95" = "vol-06917d88b07bd5d5c"
          }
        },
        {
          "us-east-1c" = {
            "i-0a18b339d3f1ddd80" = "vol-0ace4794f40c256ed"
            "i-0bd9681b1b856c3db" = "vol-00f694635ef7b0904"
          }
        },
      ]
    }
    

    好吧,这看起来更像是我想要完成的。现在,我只需要将其转换为 instanceId->VolumeId 的映射:

      inst_vol = [
        flatten([for s in lookup(local.inst_vol_to_set, "s"): [
          for key in keys(s): [
            for idx, v in keys(s[key]): {
              "${v}" = lookup(s[key], v)
            }
    
          ]
        ]])
      ]
    

    现在看起来更好了,但它仍然是一个映射元组:

    inst_vol = [
      [
        {
          "i-033c004ed25dbd907" = "vol-0a31e52f2e11dfdef"
        },
        {
          "i-0ed01a562756800e9" = "vol-0a20cabb0ae568084"
        },
        {
          "i-0400baef538ea327a" = "vol-060aff04e902f7005"
        },
        {
          "i-08ed6b26743a2bd95" = "vol-06917d88b07bd5d5c"
        },
        {
          "i-0a18b339d3f1ddd80" = "vol-0ace4794f40c256ed"
        },
        {
          "i-0bd9681b1b856c3db" = "vol-00f694635ef7b0904"
        },
      ],
    ]
    

    最后要做的是将结果展平,以便我可以查找 instance_id 并让它返回 volume_id:

    instance_to_volume_map = merge(flatten(local.inst_vol)...)
    

    这正是我想要的:

    instance_to_volume_map = {
      "i-033c004ed25dbd907" = "vol-0a31e52f2e11dfdef"
      "i-0400baef538ea327a" = "vol-060aff04e902f7005"
      "i-08ed6b26743a2bd95" = "vol-06917d88b07bd5d5c"
      "i-0a18b339d3f1ddd80" = "vol-0ace4794f40c256ed"
      "i-0bd9681b1b856c3db" = "vol-00f694635ef7b0904"
      "i-0ed01a562756800e9" = "vol-0a20cabb0ae568084"
    }
    

    【讨论】:

      猜你喜欢
      • 2019-11-09
      • 2019-01-30
      • 2022-11-09
      • 2012-04-13
      • 1970-01-01
      • 2013-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多