16

I have been trying to conditionally use a module from the root module, so that for certain environments this module is not created. Many people claim that by setting the count in the module to either 0 or 1 using a conditional does the trick.

module "conditionally_used_module" {
  source = "./modules/my_module"
  count  = (var.create == true) ? 1 : 0
}

However, this changes the type of conditionally_used_module: instead of an object (or map) we will have a list (or tuple) containing a single object. Is there another way to achieve this, that does not imply changing the type of the module?

ccoutinho
  • 3,308
  • 5
  • 39
  • 47

2 Answers2

13

To conditionally create a module you can use a variable, lets say it's called create_module in the variables.tf file of the module conditionally_used_module.

Then for every resource inside the conditionally_used_module module you will use the count to conditionally create or not that specific resource.

The following example should work and provide you with the desired effect.

# Set a variable to know if the resources inside the module should be created
module "conditionally_used_module" {
  source = "./modules/my_module"
  create_module = var.create
}

# Inside the conditionally_used_module file
# ( ./modules/my_module/main.tf ) most likely 
# for every resource inside use the count to create or not each resource
resource "resource_type" "resource_name" {
 count = var.create_module ? 1 : 0
 ... other resource properties 
}
Mihai Stancu
  • 424
  • 2
  • 6
  • 15
    While this works, it's a bit hacky. I wish Terraform officially supported conditional – Spencer Sutton Apr 29 '22 at 15:58
  • 3
    Same problem as the OP pointed out. All resources in the module become lists. – wbr Aug 15 '22 at 07:28
  • 3
    If you add this count hack for existing resource already created, it will recreate the resource. I encounter this problem when I need to modify the resource to not create in DR region but create in main region. – Andy N Sep 19 '22 at 21:31
  • 2
    Yes Andy, it is correct. When you use counter on previously created resource it will force a recreate. If you wish to not recreate the resource and only update the code to use a counter you can also move the existing resource to counter [0] with terraform state mv. But be careful using this command, create a state backup to force push in anything goes wrong – Mihai Stancu Sep 20 '22 at 22:10
3

I used this in conjunction with workspaces to build a resource only for certain envs. The advantage is for me that I get a single terraform.tfvars file to control the all the environments structure for a project.

Inside main.tf:

    workspace = terraform.workspace    
    #....
    module "gcp-internal-lb" {
      source = "../../modules/gcp-internal-lb"
      # Deploy conditionally based on deploy_internal_lb variable
      count = var.deploy_internal_lb[local.workspace] == true ? 1 : 0
      # module attributes here
    }

Then in variables.tf

variable "deploy_internal_lb" {
  description = "Set to true if you want to create an internal LB"
  type        = map(string)
}

And in terraform.tfvars:

deploy_internal_lb = {
  # DEV
  myproject-dev        = false
  # QA
  myproject-qa         = false
  # PROD
  myproject-prod       = true
}

I hope it helps.

TudorIftimie
  • 1,050
  • 11
  • 21