# Creating resources in a loop with dynamic values

**URL:** <https://discuss.hashicorp.com/t/creating-resources-in-a-loop-with-dynamic-values/26464>\
**Category:** Terraform\
**Created:** [July 7, 2021, 12:32pm UTC](https://discuss.hashicorp.com/t/creating-resources-in-a-loop-with-dynamic-values/26464 "2021-07-07T12:32:49Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![sazzopardi](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/sazzopardi/32/20601_2.png) [@sazzopardi](https://discuss.hashicorp.com/u/sazzopardi)\
**Post date:** [July 7, 2021, 12:32pm UTC](https://discuss.hashicorp.com/t/creating-resources-in-a-loop-with-dynamic-values/26464/1 "2021-07-07T12:32:49Z")

</div>

I need to set up a set of GCE instances for example 5 of them, and I need to do them in a blue/green deployment way. So have we have 5 nodes as “blue” that are active and also potential 5 nodes as “green”. Now I’d like to either have 1 of them deployed or both at the same time running in “dual” mode.

I’d also like this to be a module that can be reused for multiple set of deployments.

What I’ve done so far is the following:

`variables.tf`:

```auto
variable "runner_managers" {
  type = map(object({
    zone = string
    service_account = string // If empty use default_service_account_email
  }))
}

variable "deployment" {
  type = object({
    blue = bool
    green = bool
  })
  description = "The deployments that are active."

  default = {
    blue = true
    green = false
  }
}

```

`main.tf`:

```auto
resource "google_compute_instance_template" "runners_manager" {
....
}

######################
# Deployment - blue #
######################
resource "google_compute_instance_from_template" "runners_manager_blue" {
  for_each = var.deployment.blue ? var.runner_managers : {}

  name = "${var.runner_type}-runners-manager-${each.key}-blue"
  zone = each.value.zone

  labels = merge(google_compute_instance_template.runners_manager.labels, {
    runner_manager_name = "${var.runner_type}-runners-manager-${each.key}"
    deployment = "blue"
  })

  source_instance_template = google_compute_instance_template.runners_manager.id
}

######################
# Deployment - Green #
######################
resource "google_compute_instance_from_template" "runners_manager_green" {
  for_each = var.deployment.green ? var.runner_managers : {}

  name = "${var.runner_type}-runners-manager-${each.key}-green"
  zone = each.value.zone

  labels = merge(google_compute_instance_template.runners_manager.labels, {
    runner_manager_name = "${var.runner_type}-runners-manager-${each.key}"
    deployment = "green"
  })

  source_instance_template = google_compute_instance_template.runners_manager.id

  metadata = merge(google_compute_instance_template.runners_manager.metadata, {
    "CHEF_NODE_NAME" = "${var.runner_type}-runners-manager-${each.key}-blue"
  })
}

```

As you can see there is a lot of duplication here between `runners_manager_blue` and `runners_manager_green`, and I’m not sure how I can simplify this so that we end up creating X amount of instances depending on `var.runner_managers` but also have both `blue` and `green` at the same time.

Is duplicating the resources the only possible way here? I’ve tried looking into [dynamic blocks](https://www.terraform.io/docs/language/expressions/dynamic-blocks.html) but it doesn’t like it fit my needs since I don’t want blocks I want resources 🤔

---

<div class="post-metadata">

**Author:** ![stuart-c](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/stuart-c/32/10789_2.png) [@stuart-c](https://discuss.hashicorp.com/u/stuart-c)\
**Post date:** [July 7, 2021, 1:53pm UTC](https://discuss.hashicorp.com/t/creating-resources-in-a-loop-with-dynamic-values/26464/2 "2021-07-07T13:53:26Z")

</div>

You could do it with a single resource with the for\_each block by creating a new local variable containing entries for both the blue & green instances (depending on what is activated), with the blue/green type being included within that variable as needed.

---

<div class="post-metadata">

**Author:** ![sazzopardi](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/sazzopardi/32/20601_2.png) [@sazzopardi](https://discuss.hashicorp.com/u/sazzopardi)\
**Post date:** [July 7, 2021, 2:48pm UTC](https://discuss.hashicorp.com/t/creating-resources-in-a-loop-with-dynamic-values/26464/3 "2021-07-07T14:48:21Z")

</div>

@stuart-c interesting idea! I’ll give this a go and report back.

Thank you so much!

---

<div class="post-metadata">

**Author:** ![sazzopardi](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/sazzopardi/32/20601_2.png) [@sazzopardi](https://discuss.hashicorp.com/u/sazzopardi)\
**Post date:** [July 8, 2021, 10:03am UTC](https://discuss.hashicorp.com/t/creating-resources-in-a-loop-with-dynamic-values/26464/4 "2021-07-08T10:03:07Z")

</div>

I ended up with the following solution, which is exactly what I wanted, thank you so much @stuart-c !

```auto
locals {
  instances = merge(
    {
      for id, info in var.runner_managers : "${var.runner_type}-runners-manager-${id}-blue" => info
      if var.deployment.blue
    },
    {
      for id, info in var.runner_managers : "${var.runner_type}-runners-manager-${id}-green" => info
      if var.deployment.green
    }
  )
}

resource "google_compute_instance_from_template" "runners_manager" {
  for_each = local.runners_manager.instances

  name = each.key
  zone = each.value.zone
}

```

Other resources I used to help me figure this out:

- [azure - Terraform - conditionally creating a resource within a loop - Stack Overflow](https://stackoverflow.com/questions/48301709/terraform-conditionally-creating-a-resource-within-a-loop)
- [Create new map from a nested structure with for loops](https://discuss.hashicorp.com/t/create-new-map-from-a-nested-structure-with-for-loops/9441)
