1

The requirement is to create EC2s from the dynamically given list instance_names and distributed them evenly in the available subnets of the VPC. I have tried looping and conditional statements with little luck.

Use Case 01 - (In a VPC with two subnets) If we are creating 2 servers, One EC2 should be in subnet 'a' and other in subnet 'b'

Use Case 02 - (In a VPC with two subnets) If we are creating 3 servers, two EC2s need to be in subnet 'a' and the other EC2 in subnet 'b'

Control Code

module "servers" {
  source = "modules/aws-ec2"

  instance_type     = "t2.micro"
  instance_names    = ["server01", "server02", "server03"]
  subnet_ids        = module.prod.private_subnets
}

Module

resource "aws_instance" "instance" {
  count      = length(var.instance_names)
  subnet_id  = var.subnet_ids[count.index]
  tags = {
    Name     = var.instance_names[count.index]
  }
}
Udara Jayawardana
  • 1,073
  • 2
  • 14
  • 27
  • What's wrong with what you tried? Do you get an error? Does it not do what you want it to do? If so what does it do instead? – ydaetskcoR Dec 04 '19 at 09:21
  • conditional statements only work if we only have two subnets. Then depending whether the current index is odd or even we can assign the subnet. And yes, it's a horrible way to do any kind of task! Looping will basically need a length right? So if we provide subnets for each and every instance name from control code, it works – Udara Jayawardana Dec 04 '19 at 09:28
  • I can get the code work from the last method, but well it's not a proper code – Udara Jayawardana Dec 04 '19 at 09:29
  • It works! In a matter of minutes now we've got 2 solutions! – Udara Jayawardana Dec 04 '19 at 10:28

2 Answers2

1

You can use element to loop around the subnet_ids list and get the correct id for each aws_instance.

In the docs you can see that element will give you the desired effect because:

If the given index is greater than the length of the list then the index is "wrapped around" by taking the index modulo the length of the list

Use Case 1 
-> server01 - subnet 'a' <-> element(subnet_ids,0)
-> server02 - subnet 'b' <-> element(subnet_ids,1)
Use Case 2
-> server01 | subnet 'a' <-> element(subnet_ids,0)
-> server02 | subnet 'b' <-> element(subnet_ids,1)
   # loop around the subnet id list the first id again
-> server03 | subnet 'a' <-> element(subnet_ids,2)
-> server04 | subnet 'b' <-> element(subnet_ids,3)
-> etc.

So the following update to the code should work:

resource "aws_instance" "instance" {
  count      = length(var.instance_names)

  subnet_id  = element(var.subnet_ids, count.index)

  tags = {
    Name     = var.instance_names[count.index]
  }
}
Mihai Stancu
  • 424
  • 2
  • 6
0

I found an interesting answer from Tom Lime for a similar question. I derived an answer from it to this scenario. For the Module, we provide the below logic for the subnet_id

subnet_id = "${var.subnet_ids[ count.index % length(var.subnet_ids) ]}"
Udara Jayawardana
  • 1,073
  • 2
  • 14
  • 27