Terraform Core: Advanced Input Variables and Custom Validation
Scenario
You are writing a Terraform configuration that will be used by other developers. They need to supply an environment name and an instance size. If they supply a machine type that is too expensive (e.g., n2-standard-32), or an environment name outside of the approved list ("dev", "staging", "prod"), the deployment should fail before calling any GCP APIs. You enforce this using Variable Validation.
- Define a variable environment. Add a validation block that ensures the string is either dev, staging, or prod.
- Define a variable machine_type and add a validation block that uses regex to ensure it starts with e2-.
- Pass these variables into a simple google_compute_instance resource.
Additional Context
Variable validations run at plan time, making them a "shift-left" security check. The deployment fails almost instantly if the user provides bad inputs, saving time and preventing misconfiguration.
The condition argument inside a validation block must evaluate to a boolean. You can use any standard Terraform functions here, like contains(), length(), and can(regex()).
variables.tf
variable "project_id" { type = string }
variable "gcp_zone" { type = string; default = "us-central1-a" }
variable "environment" {
type = string
description = "The target deployment environment."
# Custom Validation Rule 1: Array inclusion
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "The environment must be 'dev', 'staging', or 'prod'."
}
}
variable "machine_type" {
type = string
description = "Compute Engine machine type."
default = "e2-micro"
# Custom Validation Rule 2: Regex matching
validation {
condition = can(regex("^e2-.*", var.machine_type))
error_message = "For budget reasons, only e2 machine types (e.g., e2-micro, e2-medium) are permitted."
}
}main.tf
provider "google" {
project = var.project_id
zone = var.gcp_zone
}
resource "google_compute_instance" "app" {
name = "app-server-${var.environment}"
machine_type = var.machine_type
boot_disk {
initialize_params { image = "debian-cloud/debian-11" }
}
network_interface {
network = "default"
}
labels = {
environment = var.environment
}
}Workflow Commands
terraform init
# This will succeed (vars meet validation conditions)
terraform apply -var="project_id=my-gcp-project-123" \
-var="environment=dev" \
-var="machine_type=e2-small"
# TEST: This will fail immediately at Plan phase due to bad environment
terraform plan -var="project_id=my-gcp-project-123" \
-var="environment=QA"
# TEST: This will fail immediately due to bad regex match
terraform plan -var="project_id=my-gcp-project-123" \
-var="environment=prod" \
-var="machine_type=n2-standard-4"
terraform destroy -var="project_id=my-gcp-project-123" -var="environment=dev"Error: Invalid value for variable
on variables.tf line 4:
4: variable "environment" {
The environment must be 'dev', 'staging', or 'prod'.
