I have two child modules, Is there a way to call either of the child module conditionally? I do not need to deploy resources in both the modules… But either of them conditionally.
Terraform does not support deciding dynamically whether to call a module, but it does allow you to decide how many instances of a called module to create, and it’s valid to instantiate a module zero times so that the call effectively represents nothing at all.
The two ways you can dynamically choose a number of instances to declare are:
- The
for_each
meta-argument, which declares that there should be one instance of a module for each element of a map. If you provide an empty map then you’d declare that there should be zero instances. - The
count
meta-argument directly specifies how many instances there should be, as a number. If you set it to zero then there will be no instances at all.
For your situation where the two module calls are exclusive, the idea would be to set either for_each
or count
on both of the module
blocks in such a way that one of them always specifies zero instances while the other always specifies one or more instances.
I don’t know from your question exactly what the condition is, so here’s a contrived simple example using a pair of input variables, which hopefully you can extrapolate into something more realistic:
variable "instance_count" {
type = number
}
variable "alternative_thing" {
type = bool
default = false
}
module "standard_thing" {
count = var.alternative_thing ? 0 : var.instance_count
}
module "alternative_thing" {
count = var.alternative_thing ? var.instance_count : 0
}
Notice that module "standard_thing"
and module "alternative_thing"
have mutually-exclusive count
expressions: only one of them can possibly be nonzero at a time. (In this case it’s also possible for them both to be zero, if instance_count
is set to zero, but that’s just an artifact of how I wrote this example and not directly related to your question).
Here’s a similar example using for_each
, so that the number of instances is decided based on a map:
variable "instances" {
type = map(object({
# (attributes for the instances here)
}))
}
variable "alternative_thing" {
type = bool
default = false
}
module "standard_thing" {
for_each = {
for k, v in var.instances : k => v
if !var.alternative_thing
}
}
module "alternative_thing" {
for_each = {
for k, v in var.instances : k => v
if var.alternative_thing
}
}
This case is a little more verbose, using a for
expression to filter out all of the map elements for one of the two module
blocks, so that again at least one of them will always have zero elements.
(It’s also possible to write variations of this where some elements of var.instances
get associated with “standard_thing” and some others get associated with “alternative_thing”, but it sounds like you don’t need that here so I’ll leave that as an exercise for another day.)
Thanks @apparentlymart … It worked
Thanks for detailed instructions, we are getting very strange issue while using count in conjunction with Module. Below code doesn’t instantiate the module even if both the variable values are matching, we tried to assign static value i.e. count = 1, but in that case as well we don’t see the module getting instantiated. Please suggest what could be the possible fix.
module “mymodule” {
source = “./module/sample”
count = var.xyz == var.abc ? 1 : 0
}
Hi @prafull.patil,
I can’t guess why those variable values would not compare as equal without knowing what those values are.
Note that two values can be equal in Terraform only if they are off exactly the same type. Therefore specifying exact version constraints in the type
arguments of each variable – both of them matching and neither including the any
placeholder anywhere – would help ensure consistent type information.
If you have further questions on this, please start a new topic and share in it the full information about what you are trying. This topic was for @francisabletreasa’s question and is now resolved.