Learn how to use conditional attributes in Terraform to create dynamic and flexible infrastructure deployments based on specific conditions and variables.
Terraform offers powerful ways to manage your infrastructure, but it doesn't allow you to directly use conditions to control if an attribute exists or not within a resource block. However, you can still implement conditional logic effectively using alternative Terraform features. Let's explore four common methods and important factors to consider.
Terraform doesn't directly support conditional attributes within resource blocks. You can't have an attribute appear or disappear based on a variable's value directly. However, you can achieve conditional logic using other Terraform constructs:
1. Conditional Expressions:
ternary
operator (condition ? true_val : false_val
) to dynamically set an attribute's value.
resource "example_resource" "example" {
attribute = var.condition ? "value_if_true" : "value_if_false"
}
2. Dynamic Blocks:
lifecycle_rule
in aws_s3_bucket
), use dynamic
blocks with a for_each
loop.
resource "aws_s3_bucket" "example" {
# ...
dynamic "lifecycle_rule" {
for_each = var.enable_lifecycle_rules ? [1] : []
content {
# ... lifecycle rule configuration
}
}
}
var.enable_lifecycle_rules
is true, the lifecycle_rule
block is created; otherwise, it's omitted.3. Conditional Objects and for_each
:
locals {
eventbridge_rules = {
rule_one = {
name = "rule_one"
schedule_expression = "cron(12 30 * * ? *)"
}
rule_two = {
name = "rule_two"
# No schedule_expression here
}
rule_three = {
name = "rule_three"
schedule_expression = var.enable_rule_three ? "cron(0 * * * ? *)" : null
}
}
}
resource "aws_cloudwatch_event_rule" "schedule" {
for_each = local.eventbridge_rules
name = each.value.name
schedule_expression = each.value.schedule_expression
}
schedule_expression
for rule_three
is set based on var.enable_rule_three
.4. Conditional Modules:
count
or for_each
meta-arguments to conditionally include entire modules.
module "optional_module" {
source = "./module-path"
# ... module inputs
count = var.enable_module ? 1 : 0
}
Important Considerations:
null
. Use empty strings or other appropriate defaults.This code provides examples of using conditional logic in Terraform to manage resources dynamically. It demonstrates using conditional expressions for simple decisions, dynamic blocks for optional resource attributes, conditional objects and for_each for iterating over varying data structures, and conditional modules for including or excluding entire infrastructure components based on conditions. These techniques offer flexibility in defining infrastructure that adapts to different environments or requirements.
This code demonstrates the techniques described in the article for implementing conditional logic in Terraform.
1. Conditional Expressions:
variable "create_database" {
type = bool
default = false
}
resource "aws_rds_instance" "example" {
# ... other RDS instance configurations
# Conditionally create the database
db_name = var.create_database ? "my_database" : null
}
2. Dynamic Blocks:
variable "enable_logging" {
type = bool
default = false
}
resource "aws_s3_bucket" "example" {
# ... other S3 bucket configurations
dynamic "logging" {
for_each = var.enable_logging ? [1] : []
content {
target_bucket = aws_s3_bucket.log_bucket.id
target_prefix = "logfiles/"
}
}
}
3. Conditional Objects and for_each
:
variable "enable_rule_two" {
type = bool
default = false
}
locals {
iam_roles = {
role_one = {
name = "role_one"
policy_arns = ["arn:aws:iam::aws:policy/AmazonS3FullAccess"]
}
role_two = {
name = "role_two"
policy_arns = var.enable_rule_two ? ["arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"] : []
}
}
}
resource "aws_iam_role" "example" {
for_each = local.iam_roles
name = each.value.name
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "example" {
for_each = { for role in local.iam_roles : role.name => role }
role = aws_iam_role.example[each.key].name
policy_arn = each.value.policy_arns[0]
}
4. Conditional Modules:
variable "create_vpc" {
type = bool
default = false
}
module "vpc" {
source = "./modules/vpc"
# ... module inputs
count = var.create_vpc ? 1 : 0
}
These examples illustrate how to conditionally manage resources and configurations in Terraform using various techniques. Remember to choose the approach that best suits your specific needs and maintains the readability of your code.
By understanding these nuances and carefully applying the techniques described, you can effectively manage conditional logic within your Terraform projects and build flexible, adaptable infrastructure.
Terraform doesn't allow attributes to appear conditionally within resource blocks. However, you can achieve conditional logic using these methods:
| Technique | Description
While Terraform doesn't directly support conditional attributes within resource blocks, you can achieve conditional logic effectively using techniques like conditional expressions, dynamic blocks, conditional objects with for_each
, and conditional modules. Each approach offers a unique way to manage resources and configurations dynamically based on variables or conditions. When implementing these workarounds, it's crucial to consider their impact on Terraform's planning phase and potential resource recreation. Always prioritize the readability of your code and thoroughly test your configurations to ensure your infrastructure behaves as expected in different scenarios. By understanding these nuances and choosing the appropriate method for your use case, you can leverage Terraform's flexibility to build robust and adaptable infrastructure.