# Conditionally create resources when a for\_each loop is involved

**URL:** <https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841>\
**Category:** Terraform\
**Created:** [February 11, 2021, 2:55pm UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841 "2021-02-11T14:55:42Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![chrisadkin](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/chrisadkin/32/16785_2.png) [@chrisadkin](https://discuss.hashicorp.com/u/chrisadkin)\
**Post date:** [February 11, 2021, 2:55pm UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/1 "2021-02-11T14:55:42Z")

</div>

A technique for the conditional creation of resources is to have a line immediately after the one with name of the resource like:

count = var.create\_resource ? 1 : 0

However, for a resource that contains a for\_each loop this does not work.

Is there a way of coding a resource that includes a for\_each loop in such away that the resources only get created if a boolean variable is set to true ?.

---

<div class="post-metadata">

**Author:** ![apparentlymart](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/apparentlymart/32/702_2.png) [@apparentlymart](https://discuss.hashicorp.com/u/apparentlymart)\
**Post date:** [February 11, 2021, 5:09pm UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/2 "2021-02-11T17:09:24Z")

</div>

Hi @chrisadkin,

The key thing about `for_each` is that it declares one resource instance for each element in the map (or set) assigned to it.

Building on that, the key to your question is to make sure that the `for_each` map has zero elements in the cases where you want to create nothing. If you have a sort of “all or nothing” situation – where you’ll disable all of the elements together in the “off” case – then a relatively concise way to write it is to write a `for` expression with an `if` clause that always evaluates to true only if your condition is enabled:

```auto
  for_each = { for k, v in var.some_map : k => v if var.enabled }

```

Typically when writing an expression like this the `if` clause would contain a reference to `k` and/or `v`, but since this is an “all or nothing” situation the result depends only on some external flag and doesn’t vary for each element.

If you _do_ want to vary the behavior by element then you can certainly do that too. For example:

```auto
  for_each = {
    for k, v in var.some_map : k => v
    if contains(var.enabled_keys, k)
  }

```

(the above is assuming that `var.enabled_keys` is a `set(string)` value containing the keys of the `var.some_map` elements that ought to be enabled, just as a contrived example of an item-specific condition.)

---

<div class="post-metadata">

**Author:** ![ohmer](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/ohmer/32/17491_2.png) [@ohmer](https://discuss.hashicorp.com/u/ohmer)\
**Post date:** [March 1, 2021, 1:18pm UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/3 "2021-03-01T13:18:14Z")

</div>

You can’t have `count` and `for_each` on a data source, resource or module.  
A trick to filter a map to remove items based on your condition.

```auto
variable "mymap" {
    type = map(object({
        attribute = string
        condition = bool
    }))

    default = {
        key1 = {
            attribute = "value"
            condition = true
        }
        key2 = {
            attribute = "value"
            condition = false
        }
        key3 = {
            attribute = "value"
            condition = true
        }
    }
}

resource "null_resource" "test" {
  for_each = { for k in compact([for k, v in var.mymap: v.condition ? k : ""]): k => var.mymap[k] }
}

```

---

<div class="post-metadata">

**Author:** ![Roxyrob](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/roxyrob/32/11129_2.png) [@Roxyrob](https://discuss.hashicorp.com/u/Roxyrob)\
**Post date:** [July 5, 2021, 12:26pm UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/4 "2021-07-05T12:26:59Z")

</div>

Hi @apparentlymart,  
It is possible to conditionally create a resource **with resource just in place and leaving resource address unchanged**?

e.g.

(starting code)

```auto
module "ec2one" {
  source = "..."
  ...
}

```

will produce resource address:

```auto
module.ec2one.<attributes>

```

(refactoring with count)

```auto
module "ec2one" {
  source = "..."
  count = var.ec2one_created ? 1 : 0  
  ...
}

```

will produce resource address:

```auto
module.ec2one[0].<attributes>

```

(refactoring with for\_each)

```auto
module "ec2one" {
  source = "..."
  for_each = { for k in ["created"] : k => k if var.ec2one_created }
  ...
}

```

will produce resource address:

```auto
module.ec2one[0].created.<attributes>

```

(refactoring **without address changes** )

```auto
module "ec2one" {
  source = "..."
  <some conditional method not changing resource address>
  ...
}

```

will produce **resource address as original** :

```auto
module.ec2one.<attributes>

```

---

<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 5, 2021, 4:42pm UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/5 "2021-07-05T16:42:23Z")

</div>

In reality there is no such thing as “conditional create”, just the ability to choose the number of resources to create (we just happen to only choose zero or one). Therefore there has to be a way to handle the count/for\_each creating more than 1 resource - hence the change to either [1] or [“something”].

So in short, no adding count of for\_each would adjust the resource name, but you could easily update any existing resource using `terraform state mv`

---

<div class="post-metadata">

**Author:** ![Roxyrob](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/roxyrob/32/11129_2.png) [@Roxyrob](https://discuss.hashicorp.com/u/Roxyrob)\
**Post date:** [July 23, 2021, 12:05am UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/6 "2021-07-23T00:05:38Z")

</div>

I tried terrform import with some trouble.

[Terraform import aws\_instance force replacement for network\_interface](https://discuss.hashicorp.com/t/terraform-import-aws-instance-force-replacement-for-network-interface/27195)

I added count to an aws\_instance (e.g. bastionaws1) to allow conditional creation, so I need to terraform import new bastionaws1[0] linked resources and remove old ones (basrionaws1). I correctly imported aws\_instance, the instance has attached ENI so I also imported resource network\_interface. On terraform plan I get that instance will be replaced becouse network\_interface force replacement:

```auto
 # module.bastionaws1[0].aws_instance.this must be replaced
-/+ resource "aws_instance" "this" {
   ...
     + network_interface { # forces replacement
         + delete_on_termination = false
         + device_index = 0
         + network_interface_id = "eni-..."
       }

```

Not tried terraform state mv yet but probably I’ll get same result.

---

<div class="post-metadata">

**Author:** ![Roxyrob](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/roxyrob/32/11129_2.png) [@Roxyrob](https://discuss.hashicorp.com/u/Roxyrob)\
**Post date:** [July 23, 2021, 12:47am UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/7 "2021-07-23T00:47:52Z")

</div>

Using `terraform state mv` worked

thanks @stuart-c

---

<div class="post-metadata">

**Author:** ![Roxyrob](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/roxyrob/32/11129_2.png) [@Roxyrob](https://discuss.hashicorp.com/u/Roxyrob)\
**Post date:** [July 23, 2021, 7:32am UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/8 "2021-07-23T07:32:51Z")

</div>

It would be very useful if terraform could handle single element list as a single normal resource. This could simplify later adoption of conditional resources creation avoiding complex, risky and boring refactoring.

---

<div class="post-metadata">

**Author:** ![parsley42](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/parsley42/32/22071_2.png) [@parsley42](https://discuss.hashicorp.com/u/parsley42)\
**Post date:** [September 2, 2021, 2:37pm UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/9 "2021-09-02T14:37:45Z")

</div>

FYI, before finding this discussion I solved the problem this way:

```auto
for_each = var.create-bastions ? toset(local.users) : []

```

Worked For Me ™

---

<div class="post-metadata">

**Author:** ![Jimcumming](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/jimcumming/32/22938_2.png) [@Jimcumming](https://discuss.hashicorp.com/u/Jimcumming)\
**Post date:** [October 11, 2021, 11:03am UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/10 "2021-10-11T11:03:20Z")

</div>

I’m trying to do something similar, but I’m not sure I can apply these examples to my code. I have a terraform script that will create multiples website based upon the contents of a json file which I’m loading as a local variable. I want to add a value to the json file to control if a site is created in the production environment.

So the json file looks something like this

```auto
[
    {
        "site_name": "demosite1",
        "site_url": "some.url.com",
        "create_prod_site" : true
    },
    {
        "site_name": "demosite2",
        "site_url": "another.url.com",
        "create_prod_site" : false
    }
]

```

I then loop over the json using a for\_each loop like this.

```auto
module "site" {

    for_each = { for site in local.site_data : site.site_name => site }

    source = "./site"
    site_name = each.value.site_name
    site_url = each.value.site_url

}

```

I would like to only create the resource if var.environment != “prod” or each.value.site.create\_prod\_site == true.

I’m not quite sure how to handle that, any help would be appreciated.

---

<div class="post-metadata">

**Author:** ![djsmiley2k](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/djsmiley2k/32/19665_2.png) [@djsmiley2k](https://discuss.hashicorp.com/u/djsmiley2k)\
**Post date:** [December 6, 2021, 1:11pm UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/11 "2021-12-06T13:11:16Z")

</div>

Hi,

I had this exact issue a week or two ago.

You can add a ‘if’ condition to the for\_each.

` for_each = { for site in local.site_data : site.site_name => site if var.environment != "prod"}`

I’m not quite sure how to add both conditionals to the if, but I’m sure someone will add that too 🙂

---

<div class="post-metadata">

**Author:** ![apparentlymart](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/apparentlymart/32/702_2.png) [@apparentlymart](https://discuss.hashicorp.com/u/apparentlymart)\
**Post date:** [February 10, 2022, 3:36pm UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/12 "2022-02-10T15:36:08Z")

</div>

Split this topic on February 10, 2022, 3:36pm UTC

2 posts were split to a new topic: [For\_each with an extra condition](https://discuss.hashicorp.com/t/for-each-with-an-extra-condition/35536)

---

<div class="post-metadata">

**Author:** ![apparentlymart](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/apparentlymart/32/702_2.png) [@apparentlymart](https://discuss.hashicorp.com/u/apparentlymart)\
**Post date:** [February 10, 2022, 3:36pm UTC](https://discuss.hashicorp.com/t/conditionally-create-resources-when-a-for-each-loop-is-involved/20841/13 "2022-02-10T15:36:23Z")

</div>

Closed on February 10, 2022, 3:36pm UTC


