Menu

Virtual Geek

Tales from real IT system administrators world and non-production environment

Terraform for_each loop on resource example

In this article I will be using for_each loop to deploy same resources multiple time. This is a third part of earlier series of Terraform for_each loop on map example. Using the for_each loop I will deploy multiple Subnet resources inside Azure Virtual Network (VNET). Using loop I can keep my terraform scripts small and simple, easy to comprehend. Here I have 3 files main.tf, variable.tf and plugin.tf. For the testing I have already created Azure Resource Group and is in place. 

In the given terraform script I have 3 files.

plugin.tf: It contains the information about azurerm provider blocks.
main.tf: This file is mentioned with Azure Virtual Network and Subnet resources block information which will be deployed on Azure Cloud.
variables.tf: This is variables file, and has default values for the resources.

Below is the tf script files, Subnet is created with foreach loop from map data.

#plugin.tf - for_each resource example
# We strongly recommend using the required_providers block to set the
# Azure Provider source and version being used
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">=2.86.0"
    }
  }
}

# Configure the Microsoft Azure Provider
provider "azurerm" {
  features {}
}

#main.tf - for_each resource example
resource "azurerm_virtual_network" "vnet" {
  name                = var.vnet_name
  location            = var.location
  resource_group_name = var.rg_name
  address_space       = var.address_space
}

resource "azurerm_subnet" "subnet" {
  for_each = var.subnet

  name                 = each.value["name"]
  resource_group_name  = each.value["resource_group_name"]
  virtual_network_name = each.value["virtual_network_name"]
  address_prefixes     = each.value["address_prefixes"]
  depends_on           = [azurerm_virtual_network.vnet]
}

locals {
  subnets = {
    for key, value in azurerm_subnet.subnet : key => value
  }
}

output "app_subnet" {
  value = lookup(local.subnets, "app_subnet", "not_found")
}

#variables.tf - for_each resource example
variable "vnet_name" {
  type    = string
  default = "example_vnet"
}

variable "rg_name" {
  type    = string
  default = "vCloud-lab.com"
}

variable "location" {
  type    = string
  default = "West US"
}

variable "address_space" {
  type    = list(any)
  default = ["10.0.0.0/16"]
}

variable "subnet" {
  description = "Map of Azure VNET subnet configuration"
  type        = map(any)
  default = {
    app_subnet = {
      name                 = "app_subnet"
      resource_group_name  = "vCloud-lab.com"
      virtual_network_name = "example_vnet"
      address_prefixes     = ["10.0.1.0/24"]
    },
    db_subnet = {
      name                 = "db_subnet"
      resource_group_name  = "vCloud-lab.com"
      virtual_network_name = "example_vnet"
      address_prefixes     = ["10.0.2.0/24"]
    }
  }
}

Download this script Terraform_for_each_resources_example.zip here or it is also available on github.com.

Before applying terraform tf scripts, I have validated (command validates the configuration files in a directory) tf files and directory and formatted it using fmt command (used to rewrite Terraform configuration files to a canonical format and style).

Microsoft Azure Terraform validate fmt main.tf variables.tf plugin.tf azurerm virtual network subnet plan apply --auto-approve for_each loop lookup output locals.png

Below is the result after applying terraform configuration. Here Virtual Network is defined separately and while creating subnet I am using for_each loop. Data is in hashicorp map format, mentioned inside variables file. I am using [depends on] to make sure VNET resource is created before creating subnets (if you use VNET resource name inside subnet resource, you can skip [depends on] parameter, simply by referring virtual network resources inside subnet module). Blocks for locals and output is used to filter and show the selected subnet details. Instead of locals and output block you can also use data source of subnet resource once subnet resource is created, to use with other resources or further use.

Microsoft Azure Resource deployment terraform apply --auto-approve create azurerm plugin module virtual network address_space address_prefixes destroy.png

terraform apply --auto-approve  

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_subnet.subnet["app_subnet"] will be created
  + resource "azurerm_subnet" "subnet" {
      + address_prefix                                 = (known after apply)
      + address_prefixes                               = [
          + "10.0.1.0/24",
        ]
      + enforce_private_link_endpoint_network_policies = false
      + enforce_private_link_service_network_policies  = false
      + id                                             = (known after apply)
      + name                                           = "app_subnet"
      + resource_group_name                            = "vCloud-lab.com"
      + virtual_network_name                           = "example_vnet"
    }

  # azurerm_subnet.subnet["db_subnet"] will be created
  + resource "azurerm_subnet" "subnet" {
      + address_prefix                                 = (known after apply)
      + address_prefixes                               = [
          + "10.0.2.0/24",
        ]
      + enforce_private_link_endpoint_network_policies = false
      + enforce_private_link_service_network_policies  = false
      + id                                             = (known after apply)
      + name                                           = "db_subnet"
      + resource_group_name                            = "vCloud-lab.com"
      + virtual_network_name                           = "example_vnet"
    }

  # azurerm_virtual_network.vnet will be created
  + resource "azurerm_virtual_network" "vnet" {
      + address_space         = [
          + "10.0.0.0/16",
        ]
      + dns_servers           = (known after apply)
      + guid                  = (known after apply)
      + id                    = (known after apply)
      + location              = "westus"
      + name                  = "example_vnet"
      + resource_group_name   = "vCloud-lab.com"
      + subnet                = (known after apply)
      + vm_protection_enabled = false
    }

  "name" = "app_subnet"
  "resource_group_name" = "vCloud-lab.com"
  "service_endpoint_policy_ids" = toset(null) /* of string */
  "service_endpoints" = tolist(null) /* of string */
  "timeouts" = null /* object */
  "virtual_network_name" = "example_vnet"}

Once terraform apply is successful, checked on the Azure portal and I see Virtual Network with Subnets are deployed successfully.

Microsoft Azure terraform fmt virtual network subnets automation hashicorp for_each foreach for loop resources data source output variable main.tf.png

Useful Articles
Create an Azure App registrations in Azure Active Directory using PowerShell & AzureCLI
Get started and configure with certificate-based authentication in Azure
Create a Virtual machine on Microsoft Azure
PowerShell List All Azure Resverations
Powershell get the list of Azure Reservations Virtual Machines instances
Get the list Azure Reservation Catalog with PowerShell and AzureCLI
Azure automation account DSC for On-Premise Virtual Machine on boarding
Azure Powershell : Operation returned an invalid status code 'BadRequest'
Get Azure virtual machine backup reports using Powershell

Go Back

Comment

Blog Search

Page Views

11375248

Follow me on Blogarama