Using count and for_each together
When using both together:
The "count" and "for_each" meta-arguments are mutually-exclusive, only one should be used to be explicit about the number of resources to be created.
What's the reason for this limitation? This seems like such a weird thing.
My use case is identical to this one https://github.com/hashicorp/terraform/issues/30030
Hi @paololazzari,
Objects in terraform can be expanded into a number of instances, keyed by either a numeric index, or a string key; there is no way to use both as an index into the same structure. If there are multiple sources of key values for a resource, they can be combined into a single for_each expression using a single level of expansion.
We use GitHub issues for tracking bugs and enhancements, rather than for questions. While we can sometimes help with certain simple problems here, it's better to use the community forum where there are more people ready to help.
Thanks!
Mine wasn't a question, it was an enhancement request which is why I opened it with with the "enhancement" tag. Can you reopen it please?
Hi @paololazzari,
Could you elaborate a bit on the points from the issue template, like what the intended use case is, and what the proposal would look like? The literal interpretation of using count+for_each is not possible in terraform as it exists now, which would be to structure all resources as nested maps in a list (or vise versa). While that could allow for using both expansion modes, it would also require rewriting how terraform evaluates all resources and configuration, and make configuration generally more complex. This means it's not likely something that will be implemented given other possible solutions.
If multiple nested levels of configuration are needed, forcing that to be only 2 levels deep and consisting of an ordered level and a map level is somewhat arbitrary and limiting. More flexibility can be gained by generating a flat data structure containing all of the desired instances without such limitations.
Hey @paololazzari, I think I know what you are trying to achieve, correct me if I'm wrong. You want to create a resource with the for_each meta-argument, but on a condition. That can be achieved by adding the conditional to for_each and without count. See:
locals {
workspace = terraform.workspace
for_each_set = toset(["1", "2", "3"])
}
resource "random_string" "conditional_for_each_resource" {
for_each = local.workspace == "staging" ? local.for_each_set : []
length = 10
}
workspace default
$ terraform workspace list
* default
staging
$ terraform apply
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
workspace staging
$ terraform workspace select staging
Switched to workspace "staging".
$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
[…]
random_string.conditional_for_each_resource["3"]: Creating...
random_string.conditional_for_each_resource["1"]: Creating...
random_string.conditional_for_each_resource["2"]: Creating...
random_string.conditional_for_each_resource["1"]: Creation complete after 0s [id=TYl*-%z5#*]
random_string.conditional_for_each_resource["3"]: Creation complete after 0s [id=BU3jTP6RQ]]
random_string.conditional_for_each_resource["2"]: Creation complete after 0s [id=83RzgTf[t5]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
In addition to @bastiandg's suggestion, there's a more general form of this which allows more detailed conditions that conditionally exclude only a subset of the elements in input map or set:
resource "example" "example" {
for_each = {
for k, v in var.something : k => v
if arbitrary_condition_here
}
}
The arbitrary_condition_here expression can, but does not need to, refer to k and v to make decisions on a per-element basis.
In the simple case where you just want to disable something entirely based on a global value, you can write a condition that doesn't refer to the element key or element value, like this:
variable "enable_thing" {
type = bool
}
resource "example" "example" {
for_each = {
for k, v in var.something : k => v
if var.enable_thing
}
}
In any for expression where the if clause refers to neither the key or the value the expression will either keep all of the elements or filter all of the elements out, which in the latter case creates the same effect as setting count = 0.
Hello,
Since there has been no further updates about original topic, I'm going to close the issue. If you have more questions, feel free to start a discussion in the community forum.
Thanks!
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.