TFLAB13-Conditional Expressions: If-Then-Else in HCL

Conditional Expressions: If-Then-Else in HCL

🔧 Terraform Core ⭐ Beginner Ternary Operator Conditional Attributes Conditional Tags

Scenario

Different environments need different configurations: production buckets should have versioning enabled and a compliance tag; dev buckets should not. Instead of maintaining separate configs per environment, you want a single config that adapts its behavior based on the environment variable.

Your Objectives
  • Use the ternary operator condition ? true_val : false_val to set versioning based on environment.
  • Conditionally include a "Compliance" tag only in production.
  • Conditionally set a bucket prefix based on a bool variable.
  • Use conditionals inside locals for computed values.

Additional Context

HCL doesn't have if/else statements. Instead, it uses the ternary operator everywhere. The syntax is: condition ? value_if_true : value_if_false. Both branches must return the same type.

For conditionally creating entire resources, combine with count = condition ? 1 : 0 (covered in Lab 10).

variables.tf

variable "environment" { type = string; default = "dev" }
variable "use_prefix"  { type = bool;   default = false }
variable "aws_region"  { type = string; default = "us-east-1" }

main.tf

terraform {
  required_version = ">= 1.5.0"
  required_providers {
    aws = { source = "hashicorp/aws", version = "~> 5.0" }
  }
}

provider "aws" { region = var.aws_region }

data "aws_caller_identity" "current" {}

locals {
  # Conditional in locals — adapt behavior per environment
  is_prod     = var.environment == "prod"
  bucket_name = var.use_prefix ? "prefixed-app-${var.environment}" : "app-${var.environment}"

  # Conditional tags — merge compliance tag only in prod
  base_tags = { Environment = var.environment, ManagedBy = "terraform" }
  prod_tags = { Compliance = "SOC2", DataClass = "restricted" }
  all_tags  = local.is_prod ? merge(local.base_tags, local.prod_tags) : local.base_tags
}

resource "aws_s3_bucket" "app" {
  bucket = "${local.bucket_name}-${data.aws_caller_identity.current.account_id}"
  tags   = local.all_tags
}

resource "aws_s3_bucket_versioning" "app" {
  bucket = aws_s3_bucket.app.id
  versioning_configuration {
    # Conditional attribute: versioning on in prod, off in dev
    status = local.is_prod ? "Enabled" : "Suspended"
  }
}

outputs.tf

output "bucket_name" { value = aws_s3_bucket.app.id }
output "is_prod"     { value = local.is_prod }
output "versioning"  { value = local.is_prod ? "Enabled" : "Suspended" }
output "tags"        { value = local.all_tags }

Workflow Commands

terraform init

# Dev mode (default) — no compliance tags, versioning suspended
terraform apply

# Prod mode — compliance tags added, versioning enabled
terraform apply -var="environment=prod"

# With prefix enabled
terraform apply -var="use_prefix=true"

terraform destroy
✓ Expected Output (environment=prod)
Outputs:

bucket_name = "app-prod-123456789012"
is_prod     = true
tags        = tomap({
  "Compliance"  = "SOC2"
  "DataClass"   = "restricted"
  "Environment" = "prod"
  "ManagedBy"   = "terraform"
})
versioning  = "Enabled"