Featured image of post Unlocking the Power of Terraform Variables: Simplify Your Infrastructure Code - Terraform on Azure - Part 7

Unlocking the Power of Terraform Variables: Simplify Your Infrastructure Code - Terraform on Azure - Part 7

Discover the magic of Terraform variables! In this enlightening guide, we'll explore how variables can make your infrastructure code more reusable, maintainable, and flexible. Get ready to take your Terraform skills to the next level! 🚀

Introduction 🎉

Hello, Everyone! 👋 Welcome back to another exciting installment of our Terraform on Azure series. In our previous posts, we’ve explored the fundamentals of Terraform, set up our development environment, and even created a Windows Virtual Machine on Azure. If you missed any of these posts, don’t worry! You can catch up by starting from Part 1 of the series.

Today, we’ll be diving into a crucial concept that will take your Terraform skills to new heights: variables! 🌟 Variables are the key to creating reusable, maintainable, and flexible infrastructure as code. By the end of this post, you’ll understand how to use variables to parameterize your Terraform configurations, making them more adaptable to different projects and environments.

So, buckle up and get ready to unlock the power of Terraform variables! 💪

Terraform State File

What are Terraform Variables? 🤔

Terraform variables are a way to parameterize your infrastructure code, allowing you to create more reusable and flexible configurations. In essence, variables enable you to define placeholders for values that can change across different projects, environments, or users.

There are three main types of variables in Terraform:

  1. Input Variables: These are variables that are declared in your Terraform configuration files and can be set by the user when running Terraform commands. Input variables are used to customize your infrastructure based on specific needs.

  2. Output Variables: These variables are used to export values from your Terraform configuration, making them accessible to other Terraform modules or external tools. Output variables are useful for sharing information about your infrastructure with other parts of your system.

  3. Local Variables: These variables are defined and used within a single Terraform module. Local variables are helpful for simplifying complex expressions or for creating reusable values within a module.

In this post, we’ll cover all three types of variables, with a focus on input variables, as they are the most commonly used type in Terraform configurations.

Declaring and Using Input Variables 📝

To start using input variables in your Terraform configuration files, you first need to declare them. Input variables are typically declared in a separate file named variables.tf, but they can also be declared in any Terraform configuration file with a .tf extension.

Here’s the syntax for declaring an input variable:

1
2
3
4
5
variable "variable_name" {
  type        = string
  description = "A description of the variable"
  default     = "default_value"
}
  • variable_name: The name of the variable, which is used to reference its value throughout your Terraform configuration files.
  • type: The data type of the variable, such as string, number, bool, list, or map.
  • description: An optional description of the variable, which is used for documentation purposes.
  • default: An optional default value for the variable, which is used if no value is provided when running Terraform commands.

Once you’ve declared your input variables, you can access their values in your Terraform configuration files using the var prefix followed by the variable name. For example:

1
2
3
4
5
6
resource "azurerm_virtual_network" "example" {
  name                = var.virtual_network_name
  address_space       = var.virtual_network_address_space
  location            = var.location
  resource_group_name = azurerm_resource_group.example.name
}

In this example, virtual_network_name, virtual_network_address_space, and location are input variables that are referenced using the var prefix.

By using input variables, you can create more flexible and reusable Terraform configurations that can be easily customized for different projects and environments.

Assigning Values to Input Variables 🎨

There are several ways to assign values to input variables in Terraform. Terraform separates the declaration of variables (in variables.tf) from the assignment of their values (in .tfvars files). This allows you to have a single source of truth for your variable definitions, while enabling flexibility in assigning different values based on the environment or project.

  1. Default Values: If you provide a default value when declaring an input variable, Terraform will use that value if no other value is specified.

  2. Command-Line Flags: You can set variable values using the -var flag when running Terraform commands. For example:

    1
    
    terraform apply -var "location=eastus" -var "virtual_network_name=my-vnet"
    
  3. Variable Files: You can create a file with a .tfvars extension to store variable values. For example, dev.tfvars:

    1
    2
    
    location = "eastus"
    virtual_network_name = "dev-vnet"
    

    To use the variable file, pass it to the Terraform command using the -var-file flag:

    1
    
    terraform apply -var-file="dev.tfvars"
    
  4. Environment Variables: Terraform can also read variable values from environment variables prefixed with TF_VAR_. This is useful when you want to set variable values based on your shell environment or when working with sensitive information that you don’t want to store in plain text files.

    For example, if you set an environment variable TF_VAR_location=eastus, Terraform will automatically use “eastus” as the value for the location input variable.

Using a combination of these methods, you can create flexible and customizable Terraform configurations that adapt to different projects and environments.

Output Variables 📤

Output variables allow you to export values from your Terraform configuration, making them accessible to other Terraform modules or external tools. They are useful for passing information about resources created by your Terraform configuration to other parts of your infrastructure.

For example, if you create a Virtual Network in one Terraform module, you can use an output variable to expose the Virtual Network ID. Other modules, such as subnets or virtual machines, can then reference this output variable to access the Virtual Network ID without needing to know the exact value.

Output variables are defined using the output block and are populated with values after Terraform creates the corresponding resources. You can access output variables using the terraform_output data source or by running the terraform output command.

Here’s an example of declaring an output variable:

1
2
3
4
output "virtual_network_id" {
  value = azurerm_virtual_network.example.id
  description = "The ID of the Virtual Network"
}

In this example, the virtual_network_id output variable exports the ID of the created Virtual Network.

Local Variables 📥

Local variables are used to assign a name to an expression, allowing you to reuse that value multiple times within a Terraform module. They help simplify your Terraform configuration and make it more readable by giving complex expressions a descriptive name.

For example, you can use a local variable to construct a resource name based on a combination of input variables and static values. This makes your Terraform configuration more maintainable and reduces the risk of errors when referencing the same expression in multiple places.

Here’s an example of declaring a local variable:

1
2
3
4
5
6
7
8
locals {
  virtual_network_name = "${var.environment}-vnet"
}

resource "azurerm_virtual_network" "example" {
  name                = local.virtual_network_name
  # ...
}

In this example, the virtual_network_name local variable combines the value of the environment input variable with the string “-vnet”. The environment input variable could be set to values like “dev”, “staging”, or “prod”, depending on the environment you’re deploying to. By using this local variable, you can create different resource names for each environment using the same Terraform code.

For example, if you set the environment input variable to “dev” when running Terraform, the resulting Virtual Network name would be “dev-vnet”. Similarly, if you set it to “prod”, the name would be “prod-vnet”. This allows you to use the same Terraform configuration across multiple environments, promoting code reuse and maintaining consistency.

The local variable is then used to set the name of the Virtual Network resource, ensuring that the resource name is dynamically generated based on the provided environment value.

Best Practices for Using Terraform Variables 🏅

  1. Use Meaningful Names: Choose clear and descriptive names for your variables to make your Terraform code more readable and maintainable.

  2. Organize Variable Definitions: Keep your variable definitions organized by placing them in a dedicated variables.tf file or by grouping them based on their purpose.

  3. Be Mindful of Sensitive Information: Avoid storing sensitive information, such as passwords or API keys, directly in your Terraform configuration files. Instead, use Terraform’s sensitive parameter or tools like Azure Key Vault to securely manage secrets.

Hands-on Example: Refactoring with Variables 🛠️

Let’s refactor a previous example from our series to use input variables. We’ll take the Azure Virtual Machine example from Part 6 and make it more reusable and customizable.

  1. Create a new file named variables.tf and declare the following input variables:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    variable "resource_group_name" {
      type        = string
      description = "The name of the resource group"
    }
    
    variable "location" {
      type        = string
      description = "The Azure region where resources will be created"
      default     = "eastus"
    }
    
    variable "virtual_machine_name" {
      type        = string
      description = "The name of the Virtual Machine"
    }
    
  2. Update the main.tf file to use the input variables:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    resource "azurerm_resource_group" "example" {
      name     = var.resource_group_name
      location = var.location
    }
    
    resource "azurerm_virtual_machine" "example" {
      name                = var.virtual_machine_name
      location            = azurerm_resource_group.example.location
      resource_group_name = azurerm_resource_group.example.name
      # ...
    }
    
  3. Create a dev.tfvars file to store variable values for a development environment:

    1
    2
    
    resource_group_name = "dev-rg"
    virtual_machine_name = "dev-vm"
    
  4. Run Terraform commands with the -var-file flag to use the variable values from dev.tfvars:

    1
    2
    
    terraform plan -var-file="dev.tfvars"
    terraform apply -var-file="dev.tfvars"
    

By refactoring the example to use input variables, you can now easily customize the resource names and location for different environments or projects.

Conclusion 🎉

Congratulations! You’ve unlocked the power of Terraform variables and taken your infrastructure-as-code skills to the next level. 🚀

In this post, we covered:

  • What Terraform variables are and why they’re important
  • How to declare and use input variables
  • Different ways to assign values to input variables
  • Output variables for exporting values from your configuration
  • Local variables for simplifying expressions and creating reusable values
  • Best practices for using Terraform variables effectively
  • A hands-on example of refactoring code to use variables

Now that you understand the fundamentals of Terraform variables, you’re ready to create more reusable, maintainable, and flexible infrastructure code. Start incorporating variables into your Terraform projects and experience the benefits for yourself!

Stay tuned for the next post in our series, where we’ll dive into [insert next topic]. Until then, happy Terraforming! 😄