Custom validation in Terraform is a way to ensure that input variables meet specific conditions or constraints before being applied. It helps in enforcing custom rules and preventing misconfigurations by validating input data. Here’s a comprehensive breakdown of how to use and understand custom validations in Terraform:
1. Overview of Custom Validation in Terraform
- Custom validation allows you to set specific constraints on input variables, ensuring that users provide valid values according to defined rules.
- Terraform uses the validationblock within avariableblock to enforce these constraints.
- This feature helps in reducing errors, especially in complex infrastructure setups, by catching potential misconfigurations early.
2. Basic Structure of Custom Validation
- The validationblock is defined inside thevariableblock.
- A typical validationblock consists of:- 
condition: An expression that evaluates to trueorfalse. Iffalse, Terraform will throw an error.
- error_message: A custom error message displayed if the condition fails.
 
- 
condition: An expression that evaluates to 
Here’s a simple syntax:
   variable "example_variable" {
     type = string
     validation {
       condition     = <expression>
       error_message = "Your custom error message here."
     }
   }
  
  
  3. How condition and error_message Work
- 
condition: This is the core of the custom validation. It contains an expression that evaluates the input.
- If the condition is true, Terraform accepts the input value.
- If false, Terraform returns the specifiederror_message.
 
- If the condition is 
- 
error_message: Used to guide users when the input value doesn’t meet the specified criteria.
- It’s important to make this message descriptive to inform users what went wrong and possibly how to fix it.
 
4. Practical Examples of Custom Validation
Example 1: Enforcing a String Length Limit
- Imagine you want to limit an input string to a maximum of 10 characters:
   variable "username" {
     type = string
     validation {
       condition     = length(var.username) <= 10
       error_message = "The 'username' variable must be 10 characters or less."
     }
   }
Example 2: Validating Number Ranges
- Let’s say you want to restrict an integer input to a range between 1 and 10:
   variable "instance_count" {
     type = number
     validation {
       condition     = var.instance_count >= 1 && var.instance_count <= 10
       error_message = "The 'instance_count' must be between 1 and 10."
     }
   }
Example 3: Restricting String Values to a Set of Options
- If you want to ensure a variable only accepts certain values, use contains()andlistfunctions:
   variable "environment" {
     type = string
     validation {
       condition     = contains(["dev", "stage", "prod"], var.environment)
       error_message = "The 'environment' variable must be one of 'dev', 'stage', or 'prod'."
     }
   }
Example 4: Validating CIDR Format
- Suppose you want to ensure an input is a valid CIDR block:
   variable "subnet_cidr" {
     type = string
     validation {
       condition     = can(regex("^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$", var.subnet_cidr))
       error_message = "The 'subnet_cidr' must be a valid CIDR block, like '192.168.0.0/16'."
     }
   }
5. Advanced Validation Techniques
  
  
  Using can for Error Handling in Validation
- The can()function helps prevent Terraform from failing due to invalid expressions by testing if an expression can be evaluated without errors.
- Example:
   variable "instance_type" {
     type = string
     validation {
       condition     = can(length(var.instance_type) > 0)
       error_message = "The 'instance_type' must be a non-empty string."
     }
   }
Combining Multiple Conditions
- You can combine conditions using logical operators (&&,||) to create complex validations.
- Example: Check if a number is either between 1-10 or between 20-30.
   variable "number" {
     type = number
     validation {
       condition     = (var.number >= 1 && var.number <= 10) || (var.number >= 20 && var.number <= 30)
       error_message = "The 'number' must be between 1-10 or 20-30."
     }
   }
6. When to Use Custom Validation
- Use custom validation when you need:
- Specific value constraints not achievable with only the typeattribute.
- Rules based on the context of your infrastructure (e.g., only certain regions, specific CIDR formats).
- To avoid common user mistakes in providing input variables.
 
- Specific value constraints not achievable with only the 
7. Limitations of Custom Validation
- Custom validation cannot be used for enforcing relational constraints between two different variables directly. You may need workarounds or consider using Terraform modules if the constraints are too complex.
- It currently only works within the scope of the variableblock, so custom validations for resources or outputs are not supported.
8. Best Practices for Custom Validation
- Use Descriptive Error Messages: Make sure your error messages clearly explain what went wrong and, if possible, suggest how to fix it.
- Test Validations: Test each validation thoroughly to ensure it works as expected, especially for complex conditions.
- Keep Conditions Simple: Overly complex validation conditions can be harder to understand and maintain.
- Consider Usability: Think about how the validation might affect users. For example, don’t enforce overly restrictive rules unless necessary.
9. Real-World Example
Suppose you are setting up a variable for an AWS instance type with specific instance types allowed only in production:
   variable "instance_type" {
     type = string
     validation {
       condition = (
         (var.environment == "prod" && contains(["t2.large", "t3.large"], var.instance_type)) ||
         (var.environment != "prod" && contains(["t2.micro", "t3.micro"], var.instance_type))
       )
       error_message = "In 'prod' environment, 'instance_type' must be 't2.large' or 't3.large'. Otherwise, use 't2.micro' or 't3.micro'."
     }
   }
Summary
Custom validation in Terraform is a powerful feature that enforces specific rules on variables to prevent misconfiguration. By defining condition and error_message in the validation block, you can ensure inputs meet the required constraints, making your infrastructure more robust and resilient.
 

 
    
Top comments (0)