Terraform 使用局部变量而不是输入变量动态创建地图

Terraform Creating map dynamically using local variable instead of input variable

要求:我有一堆EC2。我根据标签对其进行分组。在此示例中,组总数 =4,每个组有 7 个 EC2:1 parent-6 Child。我在这里分享 child 的代码,其命名很重要。

工作 code:Here 我正在分享 child EC2 代码,它与名为 :ws_to_Child_Node_name_map_count 的地图类型的输入变量一起工作得很好。现在我希望它是可扩展的(parent-child 的数量),我希望使用 'dynamically created map in locals' 而不是使用输入变量。 main.tf

resource "aws_instance" "ec2_instance_child" {
  count                   = var.ec2_instance_child_count
  tags = {
    NodeName       = "${lookup(var.ws_to_Child_Node_name_map_count, count.index+1, 99)}"
  }
}

variable.tf

variable "ws_to_Child_Node_name_map_count"  {
  type = map
  default = {
      "1"="1"
      "2"="2"
      "3"="3"
      "4"="4"
      "5"="5"
      "6"="6"
      "7"="1"
      "8"="2"
      "9"="3"
      "10"="4"
      "11"="5"
      "12"="6"
      "13"="1"
      "14"="2"
      "15"="3"
      "16"="4"
      "17"="5"
      "18"="6"
      "19"="1"
      "20"="2"
      "21"="3"
      "22"="4"
      "23"="5"
      "24"="6"
    }
  }
variable "ec2_instance_child_count" {
  description = "Number of instances to run"
  default     = "24"   #number of group *6
}

上面显示的地图我想使用两个变量动态创建,以后我不会是常量。

variable "child_count" {
  default     = 6
}

variable "group_count" {
  default     =  4
}

我可以帮助您使用 terraform 创建动态地图列表,这里是一个示例:

locals {
  childs = 24
  group  = [1,2,3,4,5,6]
}

# Here's the hack! The null_resource has a map called triggers that we can set to arbitrary values.
# We can also use count to create a list of null_resources. By accessing the triggers map inside of
# that list, we get our list of maps! See the output variable below.
resource "null_resource" "res" {
  count = local.childs+1

  triggers = {
    parent    = "${count.index}"
    child     = "${element(local.group, count.index)}"
  }
}

# And here's the result! We have a dynamic list of maps. I'm just outputting it here

output "map" {
  value = "${null_resource.res.*.triggers}"
}

你可以尝试创建一个 main.tf 和 运行 terraform init terraform apply

结果应该是这样的:

map = [
  {
    "child" = "1"
    "parent" = "0"
  },
  {
    "child" = "2"
    "parent" = "1"
  },
  {
    "child" = "3"
    "parent" = "2"
  },
  {
    "child" = "4"
    "parent" = "3"
  },
  {
    "child" = "5"
    "parent" = "4"
  },
  {
    "child" = "6"
    "parent" = "5"
  },
  {
    "child" = "1"
    "parent" = "6"
  },
  {
    "child" = "2"
    "parent" = "7"
  },
  {
    "child" = "3"
    "parent" = "8"
  },
  {
    "child" = "4"
    "parent" = "9"
  },
  {
    "child" = "5"
    "parent" = "10"
  },
  {
    "child" = "6"
    "parent" = "11"
  },
  {
    "child" = "1"
    "parent" = "12"
  },
  {
    "child" = "2"
    "parent" = "13"
  },
  {
    "child" = "3"
    "parent" = "14"
  },
  {
    "child" = "4"
    "parent" = "15"
  },
  {
    "child" = "5"
    "parent" = "16"
  },
  {
    "child" = "6"
    "parent" = "17"
  },
  {
    "child" = "1"
    "parent" = "18"
  },
  {
    "child" = "2"
    "parent" = "19"
  },
  {
    "child" = "3"
    "parent" = "20"
  },
  {
    "child" = "4"
    "parent" = "21"
  },
  {
    "child" = "5"
    "parent" = "22"
  },
  {
    "child" = "6"
    "parent" = "23"
  },
  {
    "child" = "1"
    "parent" = "24"
  },
]

如果你想检查每个 parent 和每个 child (你可以使用 locals) 你可以像这样创建 2 个循环:

   locals {
      childs = 24
      group = 6
    
      result = {
      for j in range(1, local.childs + 1) : j => [
      for i in range(1, local.group + 1) : {
        child = i,
        parent = j
      }
      ]
    
      }
    }

您的输出将按 parent 分组,如下所示:

  "1" = [
    {
      "child" = 1
      "parent" = 1
    },
    {
      "child" = 2
      "parent" = 1
    },
    {
      "child" = 3
      "parent" = 1
    },
    {
      "child" = 4
      "parent" = 1
    },
    {
      "child" = 5
      "parent" = 1
    },
    {
      "child" = 6
      "parent" = 1
    },
  ]
  "2" = [
    {
      "child" = 1
      "parent" = 2
    },
    {
      "child" = 2
      "parent" = 2
    },
    {
      "child" = 3
      "parent" = 2
    },
    {
      "child" = 4
      "parent" = 2
    },
    {
      "child" = 5
      "parent" = 2
    },
    {
      "child" = 6
      "parent" = 2
    },
  ]

您在此处编写的映射 table 似乎描述了 modulo operation 的变体,它从 1 而不是 0 开始计数。

如果这是您的意图,您可以使用表达式动态计算,而不是生成单独的映射 table。

variable "child_count" {
  default     = 6
}

variable "group_count" {
  default     =  4
}

resource "aws_instance" "example" {
  count = var.child_count * var.group_count

  tags = {
    # The % symbol is Terraform's modulo operator
    NodeName = ((count.index - 1) % var.child_count) + 1
  }
}

上面表达式中的 - 1+ 1 允许您使用基于 1 的计数而不是基于 0 的计数。对于从零开始,这将减少到 count.index % var.child_count.


如果您出于某种原因仍想在本地值中进行映射 table,您可以在 for expression 中执行上述计算:

locals {
  lookup_table = {
    for n in range(1, (var.child_count * var.group_count) + 1) :
    n => ((n - 1) % var.child_count) + 1
  }
}

这使用 the range function 从 1 计数到您的总计数,然后生成一个映射,该结果的每个元素一个元素,其中值是我在resource 块以上。

从 Terraform 0.12 开始,不再需要使用 null_resourcenull_data_source 作为转换列表的 hack,因为 for 表达式语法现在可以满足相同的用例.