šŸ¶
Terraform

Terraform Conditional Module Creation: A How-To Guide

By Filip on 11/11/2024

Learn how to use conditional logic in Terraform to dynamically create a module only when certain conditions are met, optimizing your infrastructure provisioning workflow.

Terraform Conditional Module Creation: A How-To Guide

Table of Contents

Introduction

This document outlines a pattern for conditionally creating Terraform modules using variables and the for_each meta-argument. This approach provides flexibility in your infrastructure deployments by allowing you to control module instantiation based on input variables. The example demonstrates a simple scenario with a boolean variable, but the concept can be extended to more complex conditions and multiple modules.

Step-by-Step Guide

  1. Define a variable for your condition:

    variable "create_module" {
      type = bool
      default = false
    }
  2. Use the for_each meta-argument on the module block:

    module "my_module" {
      source = "./my_module"
      # ... other module inputs ...
      for_each = var.create_module ? { "enabled" = true } : {}
    }
  3. Access module outputs conditionally:

    output "module_output" {
      value = try(module.my_module.some_output, null)
    }

Explanation:

  • The for_each argument creates an instance of the module for each key in the map.
  • The conditional expression creates a map with a single key "enabled" if var.create_module is true, otherwise an empty map.
  • This results in either one instance (module enabled) or zero instances (module disabled).
  • The try() function handles cases where the module is not created and prevents errors when accessing outputs.

Code Example

This Terraform code defines a module named "my_module" that can be conditionally created based on the value of a boolean variable "create_module". The "for_each" meta-argument in the module block uses a conditional expression to control module instantiation. If "create_module" is true, the module is created and its output "some_output" is accessible. Otherwise, the module is not created and the output defaults to null. This allows for flexible and dynamic infrastructure provisioning based on user-defined conditions.

This example demonstrates how to conditionally create a module based on a variable.

main.tf:

# Define a variable to control module creation
variable "create_module" {
  type    = bool
  default = false
}

# Define the module block with conditional for_each
module "my_module" {
  source = "./my_module"

  # ... other module inputs ...

  # Conditionally create the module
  for_each = var.create_module ? { "enabled" = true } : {}
}

# Access module outputs conditionally
output "module_output" {
  value = try(module.my_module.enabled.some_output, null)
}

my_module/variables.tf:

variable "some_input" {
  type = string
}

my_module/outputs.tf:

output "some_output" {
  value = var.some_input
}

Explanation:

  1. Variable Definition: The create_module variable determines whether the module should be created.
  2. Conditional for_each: The for_each meta-argument on the module block uses a conditional expression. If create_module is true, it creates a map with a single key "enabled". Otherwise, it creates an empty map.
  3. Module Instantiation: Terraform iterates over the for_each map. If the map is empty (when create_module is false), no module instance is created. If the map has the "enabled" key, a single instance of the module is created.
  4. Conditional Output Access: The try() function in the output block handles cases where the module is not created. If the module exists, it retrieves the some_output value. Otherwise, it returns null, preventing errors.

To use this example:

  1. Create the files main.tf, my_module/variables.tf, and my_module/outputs.tf with the code above.
  2. Run terraform init to initialize the working directory.
  3. Run terraform apply to create the infrastructure. By default, the module will not be created.
  4. To enable the module, set the create_module variable to true in your Terraform configuration or using the command line: terraform apply -var 'create_module=true'.
  5. Run terraform destroy to destroy the infrastructure when you are finished.

Additional Notes

  • Alternatives to for_each: While for_each is the recommended approach for conditional module creation in Terraform 0.13 and above, you can achieve similar results using count with conditional expressions in earlier versions. However, this approach can be less readable and maintainable.
  • Variable Scope: Remember that the variable used for the condition (create_module in this case) should be defined in a scope accessible to both the module definition and the location where you are calling the module.
  • Module Dependencies: If your conditionally created module has dependencies on other resources, ensure that those dependencies are also handled conditionally or are always present.
  • Error Handling: The try() function is crucial for gracefully handling cases where the module is not created. Without it, attempting to access outputs from a non-existent module would result in errors.
  • Complex Conditions: You can use more complex conditional expressions within the for_each meta-argument to create modules based on multiple variables or logical operations.
  • Dynamic Module Counts: While this example focuses on creating zero or one instance, you can dynamically create multiple module instances by adjusting the map provided to for_each. For example, you could use a map of resource names to create a module instance for each resource.
  • Best Practices: Clearly document the purpose of the conditional module creation and the variable controlling it. This helps improve the readability and maintainability of your Terraform code.
  • Testing: Ensure you thoroughly test your Terraform code with both the module enabled and disabled to verify the expected behavior in all scenarios.

Summary

This document outlines a pattern for conditionally creating Terraform modules based on a variable.

Steps:

  1. Define a Boolean Variable:

    • Create a variable (e.g., create_module) to control module creation. Set its default to false.
  2. Use for_each with a Conditional Expression:

    • In your module block, utilize the for_each meta-argument.
    • Assign it a conditional expression that generates a single-key map ({"enabled": true}) if the variable is true, or an empty map ({}) otherwise.
  3. Access Outputs Conditionally:

    • When referencing module outputs, employ the try() function to gracefully handle cases where the module wasn't created due to the condition being false.

How it Works:

  • for_each dynamically creates module instances based on the provided map.
  • The conditional expression ensures either one instance (module enabled) or zero instances (module disabled).
  • try() prevents errors when accessing outputs of a potentially non-existent module.

Benefits:

  • Cleanly manage optional modules based on conditions.
  • Avoid errors by gracefully handling absent module outputs.

Conclusion

By combining variables, the for_each meta-argument, and the try() function, Terraform users can implement conditional module creation, enhancing the flexibility and control over infrastructure deployments. This approach allows for modules to be included or excluded based on specific conditions, leading to more efficient and adaptable infrastructure as code configurations.

References

Were You Able to Follow the Instructions?

šŸ˜Love it!
šŸ˜ŠYes
šŸ˜Meh-gical
šŸ˜žNo
šŸ¤®Clickbait