DEV Community

Cover image for Terraform - Variable Validation
Marcel.L
Marcel.L

Posted on • Updated on

Terraform - Variable Validation

Overview

Today we will discuss an interesting feature of Terraform by taking a closer look at variable validation rules inside terraform variables.

variable "fruit" {
  type        = string
  description = "What fruit to pick?"
  default     = "apple"

  validation {
    condition     = can(regex("^(lemon|apple|mango|banana|cherry)$", var.fruit))
    error_message = "Invalid fruit selected, only allowed fruits are: 'lemon', 'apple', 'mango', 'banana', 'cherry'. Default 'apple'"
  }
}
Enter fullscreen mode Exit fullscreen mode

The above example validates the fruit variable against a set of predefined fruits. An input that matches the regex pattern passes the validation. If any invalid fruit is passed, the error message quickly informs the users about the allowed values.

Terraform's consistent updates have always aimed to make infrastructure-as-code (IaC) development more efficient, secure, and error-free. One of these updates, the addition of a validation capability for input variables, has significantly improved this IaC tool's robustness.

This blog post will demystify Terraform validation, discussing its utility and providing practical examples using the Azure platform.

Understanding Terraform Variable Validation

Terraform's variable validation helps ensure the values assigned to variables meet specific criteria defined in advance. Introduced in version 0.13, this feature allows you to provide custom validation rules for your input variables. Validation is essentially added as a validation block within the variable declaration, and it uses a condition to determine whether a value is acceptable.

There are two key components in a variable validation block - the condition that expresses the criteria a value must meet, and an error message to alert the user if the value doesn't pass the check. The condition is a boolean expression. When the condition is false, Terraform produces an error displaying the custom message.

The Importance of Terraform Variable Validation

Terraform variable validation brings four key advantages to IaC developers:

  1. Greater Consistency: With variable validation, you ensure that acceptable input values adhere to specific standards. This fosters uniformity across each infrastructure deployment.

  2. Error Reduction: By flagging erroneous or unacceptable variable inputs, the tool drastically reduces errors that might arise during the 'terraform apply' phase.

  3. Enhanced Security: By validating inputs adequately, developers can avoid potential security vulnerabilities resulting from insecure or dangerous variable input.

  4. Improved Developer Experience: Validation improves user experience by quickly catching errors and guiding users towards acceptable values, accelerating the development process.

Variable Validation In Action: Azure Platform Examples

Let's dive into some practical use cases of variable validation with Azure infrastructure deployments.

For instance, when creating a virtual machine, if a user wants to choose their known operating system, we define a terraform variable and validate whether the input falls within our accepted values:

variable "os_type" {
  description = "Operating System to use for the VM"

  validation {
    condition     = contains(["Windows", "Linux"], var.os_type)
    error_message = "The os_type must be either 'Windows' or 'Linux'."
  }
}
Enter fullscreen mode Exit fullscreen mode

In the example above, we utilize the contains function to validate whether the os_type falls within [Windows, Linux]. If a user enters an OS type out of this list, Terraform will display the error message, preventing potential confusion or failure in deployments.

Similarly, you might want to implement a naming convention for a resource group in Azure. For example, the name must always start with a 'rg-' prefix. Terraform validation can assist here:

variable "resource_group_name" {
  description = "Name of the resource group"

  validation {
    condition     = can(regex("^rg-", var.resource_group_name))
    error_message = "The resource group name must start with 'rg-'."
  }
}
Enter fullscreen mode Exit fullscreen mode

Our condition uses a regular expression to test whether the given resource group name starts with 'rg-'. If not, Terraform prompts the user with the specified error_message.

Let's take a look at one more example. The following example demonstrates another use case for Terraform's variable validation, when working with private DNS records and validating the record type. This code sample ensures that only valid DNS record types are specified when deploying resources:

variable "private_dns_record_type" {
  type        = string
  description = "value of the private dns record type, only allowed options are 'A', 'AAAA', 'CNAME', 'MX', 'PTR', 'SRV', 'TXT'"
  default     = "A"

  validation {
    condition     = can(regex("^(A|AAAA|CNAME|MX|PTR|SRV|TXT)$", var.private_dns_record_type))
    error_message = "Invalid value for private_dns_record_type, only allowed options are: 'A', 'AAAA', 'CNAME', 'MX', 'PTR', 'SRV', 'TXT'"
  }
}
Enter fullscreen mode Exit fullscreen mode

The above variable block is a stricter example where it validates the private_dns_record_type against a set of predefined DNS record types. An input that matches the regex pattern passes the validation. If any invalid DNS record type is passed, the error message quickly informs the users about the allowed values.

This variable validation can then be used in the resource block as follows to create a corresponding private DNS record for that type for example:

#A record example
resource "azurerm_private_dns_a_record" "private_dns_a_record" {
  count               = var.private_dns_record_type == "A" ? 1 : 0
  name                = lower(var.private_dns_record_name)
  resource_group_name = var.resource_group_name
  ttl                 = var.private_dns_record_ttl
  zone_name           = var.private_dns_zone_name
  records             = var.private_dns_record_value
  tags                = var.tags
}
Enter fullscreen mode Exit fullscreen mode

or

#CNAME record example
resource "azurerm_private_dns_cname_record" "private_dns_cname_record" {
  count               = var.private_dns_record_type == "CNAME" ? 1 : 0
  name                = lower(var.private_dns_record_name)
  resource_group_name = var.resource_group_name
  ttl                 = var.private_dns_record_ttl
  zone_name           = var.private_dns_zone_name
  record              = var.private_dns_record_value
  tags                = var.tags
}
Enter fullscreen mode Exit fullscreen mode

The resource blocks above creates an Azure Private DNS 'A' or 'CNAME' record, but only if the private_dns_record_type variable is "A" or "CNAME" for example. If the DNS record type doesn't fit that criteria of the validation, count equals 0, and Terraform won't create this record type. This approach ensures the correct DNS record gets created based on the initially validated variable and avoids unnecessary or inaccurate resources.

By integrating variable validation in your Terraform configurations like this, you enhance the accuracy and predictability of your deployments. With this advanced feature, you'll be able to manage resources more effectively on platforms like Azure.

Conclusion

In summary, variable validation enhances Terraform's robustness as an IaC tool by reducing errors, improving security, and fostering a consistent, developer-friendly experience. Our examples on the Azure platform demonstrate how you can avoid complications by ensuring variable inputs align with your requirements during the infrastructure setup process. As you continue to build with Terraform, consider this feature to help bolster your code's reliability and your infrastructure's integrity.

I hope you have enjoyed this post and have learned something new. ❤️

Author

Like, share, follow me on: 🐙 GitHub | 🐧 Twitter | 👾 LinkedIn

Top comments (0)