Posted: Wednesday, November 13, 2024

Word Count: 1682

Reading Time: 8 minutes


Mastering Conditional Statements in Terraform

Conditional statements in Terraform enable users to define infrastructure with flexibility, allowing for configurations that adapt based on environment variables, user inputs, or other conditions. In this article, we’ll explore how to use conditional expressions in Terraform, with practical examples to illustrate their power.

What Are Conditional Statements in Terraform?

In Terraform, a conditional expression allows you to define values that depend on a condition. This is similar to the “if-else” logic in more traditional programming. The syntax follows a ternary form, where you provide a condition, a true value, and a false value.

The syntax looks like this:

<condition> ? <value_if_true> : <value_if_false>

Here, the condition is evaluated, and if it’s true, the expression returns value_if_true; otherwise, it returns value_if_false.

Example 1: Simple Boolean-Based Conditional

Let’s start with a basic example that determines whether to enable a certain feature. Suppose you want to enable a monitoring resource only in a production environment. You can use a variable to define the environment and conditionally deploy the resource.

Terraform – Boolean-Based
provider "azurerm" {
  features {}
  subscription_id = var.subscription_id
} 

variable "environment" {
  type    = string
  default = "dev"
}

resource "azurerm_log_analytics_workspace" "monitoring" {
  count               = var.environment == "prod" ? 1 : 0
  name                = "${lower(var.environment)}-log-workspace"
  location            = "East US"
  resource_group_name = azurerm_resource_group.main.name
  sku                 = "PerGB2018"
}

resource "azurerm_resource_group" "main" {
  name     = "example-resources"
  location = "East US"
}
Bits and That Technology Blog

Explanation

In this example:

TERRAFORM PLAN OUTPUT IF VARIABLE IS CHANGED TO PROD

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# azurerm_log_analytics_workspace.monitoring[0] will be created
+ resource "azurerm_log_analytics_workspace" "monitoring" {
+ allow_resource_only_permissions = true
+ daily_quota_gb = -1
+ id = (known after apply)
+ internet_ingestion_enabled = true
+ internet_query_enabled = true
+ local_authentication_disabled = false
+ location = "eastus"
+ name = "prod-log-workspace"
+ primary_shared_key = (sensitive value)
+ resource_group_name = "example-resources"
+ retention_in_days = (known after apply)
+ secondary_shared_key = (sensitive value)
+ sku = "PerGB2018"
+ workspace_id = (known after apply)
}

# azurerm_resource_group.main will be created
+ resource "azurerm_resource_group" "main" {
+ id = (known after apply)
+ location = "eastus"
+ name = "example-resources"
}

Plan: 2 to add, 0 to change, 0 to destroy.

Example 2: Conditional Variable Assignment

Conditionals also shine when defining variable values based on other variables. For instance, you may want to choose different machine sizes based on the environment.

Terraform – Conditional Variable
provider "azurerm" {
  features {}
  subscription_id = var.subscription_id
} 

variable "subscription_id" {
  default = "<Enter your Subcription Id>"
}

variable "environment" {
  type    = string
  default = "dev"
}

variable "storage_sku" {
  type    = string
  default = var.environment == "prod" ? "Standard_GRS" : "Standard_LRS"
}

resource "azurerm_storage_account" "example" {
  name                     = "examplestorageacct${random_integer.suffix.result}"
  resource_group_name      = azurerm_resource_group.main.name
  location                 = azurerm_resource_group.main.location
  account_tier             = "Standard"
  account_replication_type = var.storage_sku

  tags = {
    environment = var.environment
  }
}

resource "azurerm_resource_group" "main" {
  name     = "example-resources"
  location = "East US"
}

resource "random_integer" "suffix" {
  min = 10000
  max = 99999
}
Bits and That Technology Blog

Explanation

In this example:

TERRAFORM PLAN OUTPUT - SINCE DEV WAS SELECTED LRS WAS IS DESIGNATED AS THE REPLICATION TYPE

# azurerm_resource_group.main will be created
+ resource "azurerm_resource_group" "main" {
+ id = (known after apply)
+ location = "eastus"
+ name = "example-resources"
}

# azurerm_storage_account.example will be created
+ resource "azurerm_storage_account" "example" {
+ access_tier = (known after apply)
+ account_kind = "StorageV2"
+ account_replication_type = "LRS"
+ account_tier = "Standard"
+ allow_nested_items_to_be_public = true
+ cross_tenant_replication_enabled = false
+ default_to_oauth_authentication = false
+ dns_endpoint_type = "Standard"
+ https_traffic_only_enabled = true
+ id = (known after apply)
+ infrastructure_encryption_enabled = false
+ is_hns_enabled = false
+ large_file_share_enabled = (known after apply)
+ local_user_enabled = true
+ location = "eastus"
+ min_tls_version = "TLS1_2"
+ name = (known after apply)
+ nfsv3_enabled = false
+ primary_access_key = (sensitive value)
+ primary_blob_connection_string = (sensitive value)
+ primary_blob_endpoint = (known after apply)
+ primary_blob_host = (known after apply)
+ primary_blob_internet_endpoint = (known after apply)
+ primary_blob_internet_host = (known after apply)
+ primary_blob_microsoft_endpoint = (known after apply)
+ primary_blob_microsoft_host = (known after apply)
+ primary_connection_string = (sensitive value)
+ primary_dfs_endpoint = (known after apply)
+ primary_dfs_host = (known after apply)
+ primary_dfs_internet_endpoint = (known after apply)
+ primary_dfs_internet_host = (known after apply)
+ primary_dfs_microsoft_endpoint = (known after apply)
+ primary_dfs_microsoft_host = (known after apply)
+ primary_file_endpoint = (known after apply)
+ primary_file_host = (known after apply)
+ primary_file_internet_endpoint = (known after apply)
+ primary_file_internet_host = (known after apply)
+ primary_file_microsoft_endpoint = (known after apply)
+ primary_file_microsoft_host = (known after apply)
+ primary_location = (known after apply)
+ primary_queue_endpoint = (known after apply)
+ primary_queue_host = (known after apply)
+ primary_queue_microsoft_endpoint = (known after apply)
+ primary_queue_microsoft_host = (known after apply)
+ primary_table_endpoint = (known after apply)
+ primary_table_host = (known after apply)
+ primary_table_microsoft_endpoint = (known after apply)
+ primary_table_microsoft_host = (known after apply)
+ primary_web_endpoint = (known after apply)
+ primary_web_host = (known after apply)
+ primary_web_internet_endpoint = (known after apply)
+ primary_web_internet_host = (known after apply)
+ primary_web_microsoft_endpoint = (known after apply)
+ primary_web_microsoft_host = (known after apply)
+ public_network_access_enabled = true
+ queue_encryption_key_type = "Service"
+ resource_group_name = "example-resources"
+ secondary_access_key = (sensitive value)
+ secondary_blob_connection_string = (sensitive value)
+ secondary_blob_endpoint = (known after apply)
+ secondary_blob_host = (known after apply)
+ secondary_blob_internet_endpoint = (known after apply)
+ secondary_blob_internet_host = (known after apply)
+ secondary_blob_microsoft_endpoint = (known after apply)
+ secondary_blob_microsoft_host = (known after apply)
+ secondary_connection_string = (sensitive value)
+ secondary_dfs_endpoint = (known after apply)
+ secondary_dfs_host = (known after apply)
+ secondary_dfs_internet_endpoint = (known after apply)
+ secondary_dfs_internet_host = (known after apply)
+ secondary_dfs_microsoft_endpoint = (known after apply)
+ secondary_dfs_microsoft_host = (known after apply)
+ secondary_file_endpoint = (known after apply)
+ secondary_file_host = (known after apply)
+ secondary_file_internet_endpoint = (known after apply)
+ secondary_file_internet_host = (known after apply)
+ secondary_file_microsoft_endpoint = (known after apply)
+ secondary_file_microsoft_host = (known after apply)
+ secondary_location = (known after apply)
+ secondary_queue_endpoint = (known after apply)
+ secondary_queue_host = (known after apply)
+ secondary_queue_microsoft_endpoint = (known after apply)
+ secondary_queue_microsoft_host = (known after apply)
+ secondary_table_endpoint = (known after apply)
+ secondary_table_host = (known after apply)
+ secondary_table_microsoft_endpoint = (known after apply)
+ secondary_table_microsoft_host = (known after apply)
+ secondary_web_endpoint = (known after apply)
+ secondary_web_host = (known after apply)
+ secondary_web_internet_endpoint = (known after apply)
+ secondary_web_internet_host = (known after apply)
+ secondary_web_microsoft_endpoint = (known after apply)
+ secondary_web_microsoft_host = (known after apply)
+ sftp_enabled = false
+ shared_access_key_enabled = true
+ table_encryption_key_type = "Service"
+ tags = {
+ "environment" = "dev"
}

+ blob_properties (known after apply)

+ network_rules (known after apply)

+ queue_properties (known after apply)

+ routing (known after apply)

+ share_properties (known after apply)
}

# random_integer.suffix will be created
+ resource "random_integer" "suffix" {
+ id = (known after apply)
+ max = 99999
+ min = 10000
+ result = (known after apply)
}

Plan: 3 to add, 0 to change, 0 to destroy.

Example 3: Complex Conditionals with Nested Expressions

In more advanced cases, you might need to use multiple conditions. Terraform conditionals can be nested or combined with logical operators like && (and) and || (or).

Terraform – Complex Conditionals
provider "azurerm" {
  features {}
  subscription_id = var.subscription_id
} 

variable "subscription_id" {
  default = "<Enter your Subcription Id>"
}

variable "environment" {
  type    = string
  default = "dev"
}

variable "region" {
  type    = string
  default = "us-east-1"
}

variable "use_ha" {
  type    = bool
  default = false
}

output "service_url" {
  value = var.environment == "prod" && var.region == "us-east-1" && var.use_ha ? "https://prod-ha.example.com" : "https://standard.example.com"
}
Bits and That Technology Blog

Explanation

In this example:

TERRAFORM PLAN OUTPUT

Changes to Outputs:
+ service_url = "https://standard.example.com"

When Not to Use Conditionals

Although conditionals offer flexibility, overusing them can lead to complex and hard-to-read configurations. If you find yourself nesting too many conditionals, consider refactoring your code or breaking it down into simpler, modular components.

Key Takeaways

Mastering conditionals in Terraform can make your configurations more efficient, adaptable, and cost-effective. Whether you’re deploying resources conditionally or selecting variable values based on environment contexts, these expressions are powerful tools in any Terraform practitioner’s toolkit.


Leave a Reply

Your email address will not be published. Required fields are marked *