Conditionally call modules

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.

Hi @francisabletreasa,

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