1

Requirements: I have a bunch of EC2s. Which I am grouping according to the Tags. in this example total number of group =4 and each group has 7 EC2 : 1 parent-6 Child. here i am sharing code of child whose naming matters.

working code:Here I am sharing the child EC2 code which is working perfectly fine with the input variables of map type named :ws_to_Child_Node_name_map_count. Now i want it to be scalable(number of parent-child) for which I am looking to use 'dynamically created map in locals' instead of using input variable. 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
}

the map shown above I want to create dynamically using two variables, which in future i will not be constant.

variable "child_count" {
  default     = 6
}

variable "group_count" {
  default     =  4
}

2 Answers 2

5

The mapping table you wrote here seems to be describing a variant of the modulo operation that starts counting at one rather than zero.

If that's your intent, you could potentially calculate this dynamically using an expression rather than producing a separate mapping 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
  }
}

The - 1 and + 1 in the expression above are allowing for the fact that you are using one-based counting rather than zero-based counting. For zero-based, this would reduce to count.index % var.child_count.


If you still want to make the mapping table in a local value for some reason, you can perform the above calculation inside a for expression instead:

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

This uses the range function to count from 1 up to your total count, and then produces a map with one element per element of that result where the value is the result of the same modulo calculation I showed in the resource block above.

From Terraform 0.12 onwards it is never necessary to use null_resource or null_data_source as a hack to transform lists, because the for expression syntax can now meet the same use-cases.

Sign up to request clarification or add additional context in comments.

Comments

2

i can help you create a dynamic list of maps with terraform using a hack here's an example :

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}"
}

you can try it create a main.tf and run terraform init terraform apply

the result should be like this :

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"
  },
]

If you want to check every parent and every child (you can use locals) you can create a 2 loops like this :

   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
      }
      ]
    
      }
    }

your output will be grouped by parents like this :

  "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
    },
  ]

3 Comments

Thanks, it worked for me, in case of child. HOwever, parent will be same for all 6 children. Child1-parent1, Child2-parent1,child3-parent1,child4-parent1,child5-parent1,child6-parent1 and then child1-parent2. Can I please have the element syntax for the same? Great help!!
Thanks Montassar, Sorry, my example list might have created the confusion. Actually i am using two separate to parent and child. apologies again. The parent will be same for all 6 children.
hello @kamlendra thank you , i will add the format to the answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.