Introduction
This article demonstrates how to use Terraform’s local values and conditional logic for various general-purpose use cases. Instead of focusing solely on environments, we explore scenarios where conditional logic can help manage different aspects of infrastructure, configuration settings, and dynamic behavior.
Use Case
In many infrastructure-as-code workflows, conditional logic allows you to configure dynamic values based on certain conditions, simplifying your Terraform configurations. This article highlights different scenarios where locals and conditionals can be applied effectively.
Example 1: Setting Values Based on Resource Size
# Determines the number of CPUs based on resource size input
locals {
cpu_count = var.resource_size == "large" ? 16 : var.resource_size == "medium" ? 8 : 4
}
output "cpu_count_output" {
description = "The number of CPUs assigned based on the resource size."
value = local.cpu_count
}
# Variable declaration
variable "resource_size" {
description = "Defines the resource size (e.g., large, medium, small)."
type = string
}
Explanation:-
local.cpu_count: This local variable sets the number of CPUs based on the input for `resource_size`. For a `"large"` resource, it assigns `16` CPUs, for `"medium"`, it assigns `8`, and for all other sizes, it defaults to `4`.
- Output: The output reflects the CPU count assigned based on the resource size. This logic can be used to dynamically allocate resources in your infrastructure.
Example 2: Enabling Services Based on Availability Zones
# Conditional logic to enable a service if deployed in certain availability zones
locals {
is_service_enabled = contains(var.availability_zones, "us-west-1a") || contains(var.availability_zones, "us-west-1b") ? true : false
}
output "service_enabled_output" {
description = "Determines if the service is enabled based on availability zones."
value = local.is_service_enabled
}
# Variable declaration
variable "availability_zones" {
description = "List of availability zones to deploy resources."
type = list(string)
}
Explanation:
- local.is_service_enabled: This checks whether specific availability zones (`"us-west-1a"` or `"us-west-1b"`) are present in the list of `availability_zones`. If either zone is found, the service is enabled (`true`), otherwise it’s disabled (`false`).
- Output: The output will return whether the service is enabled or not based on the specified availability zones.
Example 3: Cost Calculation Based on Resource Type
# Conditional logic for cost calculation based on resource type
locals {
resource_cost = var.resource_type == "compute" ? 100 : var.resource_type == "storage" ? 50 : 25
}
output "resource_cost_output" {
description = "The calculated cost for the resource based on its type."
value = local.resource_cost
}
# Variable declaration
variable "resource_type" {
description = "Specifies the type of resource (e.g., compute, storage, network)."
type = string
}
Explanation:
- local.resource_cost: This calculates a cost value based on the `resource_type` variable. Compute resources are assigned a cost of `100`, storage resources a cost of `50`, and all other types default to a cost of `25`.
- Output: The output displays the cost based on the resource type, which can be useful for budgeting or resource allocation in infrastructure.
Example 4: Feature Toggling Based on User Input
# Toggle a feature on or off based on user input
locals {
feature_toggle = var.enable_feature ? "Feature Enabled" : "Feature Disabled"
}
output "feature_toggle_status" {
description = "Displays the status of a feature toggle based on user input."
value = local.feature_toggle
}
# Variable declaration
variable "enable_feature" {
description = "A boolean flag to enable or disable a feature."
type = bool
}
Explanation:
- local.feature_toggle: This local determines if a feature should be enabled or disabled based on a boolean input (`true` or `false`). The feature is toggled on or off dynamically.
- Output: The output provides a message indicating whether the feature is enabled or disabled.
Example 5: Resource Count Based on Scaling Strategy
# Determine resource count based on scaling strategy
locals {
resource_count = var.scaling_strategy == "aggressive" ? 10 : var.scaling_strategy == "moderate" ? 5 : 2
}
output "resource_count_output" {
description = "The number of resources to provision based on scaling strategy."
value = local.resource_count
}
# Variable declaration
variable "scaling_strategy" {
description = "Defines the scaling strategy (e.g., aggressive, moderate, conservative)."
type = string
}
Explanation:
- local.resource_count: This local sets the number of resources to be provisioned based on the chosen scaling strategy. If `"aggressive"`, 10 resources are provisioned, `"moderate"` provisions 5, and for any other strategy, it defaults to 2.
- Output: The output shows how many resources will be provisioned based on the selected scaling strategy.
Example 6: Path Configuration Based on Operating System
# Conditional logic to set a file path based on the operating system
locals {
file_path = var.os_type == "windows" ? "C:\\app\\config" : "/etc/app/config"
}
output "file_path_output" {
description = "The file path set based on the operating system."
value = local.file_path
}
# Variable declaration
variable "os_type" {
description = "Specifies the operating system (e.g., windows, linux)."
type = string
}
Explanation:
- local.file_path: This sets the file path dynamically based on the `os_type` variable. If the OS is `"windows"`, the path uses the Windows-style `C:\\app\\config`, otherwise, it uses the Linux-style `/etc/app/config`.
- Output: The output reflects the correct file path based on the operating system.
Example 7: Additional Condition Check Based on Multiple Inputs
# Additional check based on two variables
locals {
requires_additional_check = var.resource_type == "compute" && var.resource_zone == "zone-1" ? false : true
}
output "requires_additional_check" {
description = "Indicates if additional checks are required based on the resource type and zone."
value = local.requires_additional_check
}
# Variable declarations
variable "resource_type" {
description = "Specifies the type of resource (e.g., compute, storage)."
type = string
}
variable "resource_zone" {
description = "Specifies the resource zone (e.g., zone-1, zone-2)."
type = string
}
Explanation:
- local.requires_additional_check: This logic checks two conditions: if the resource type is compute and if it is in zone-1. If both conditions are met, additional checks are not required (returns false); otherwise, additional checks are required (true).
- Output: This output helps determine whether the configuration needs further validation based on these two variables.
Example 8: Negation Logic for General Conditions
# Negation logic for checking if the input is not a specific value
locals {
is_not_compute = !(var.resource_type == "compute") ? true : false
}
output "is_not_compute" {
description = "Indicates whether the resource type is not 'compute'."
value = local.is_not_compute
}
# Variable declaration
variable "resource_type" {
description = "Specifies the type of resource (e.g., compute, storage)."
type = string
}
Explanation:
- local.is_not_compute: This logic negates the condition to check if the resource type is **not** compute. If the resource type is not `"compute"`, the result is `true`; otherwise, it returns `false`.
- Output: This output helps determine if a different configuration is required when the resource type is not compute.
Conclusion
Using locals and conditional logic in Terraform allows for more flexible configurations, dynamically adjusting values based on various inputs. This approach helps avoid hardcoding values and provides a scalable, maintainable way to manage different aspects of your infrastructure across a wide range of use cases.
Additional Information
https://developer.hashicorp.com/terraform/language/expressions/conditionals