Saturday, January 23, 2021

Manageable Infra scripts with Terraform for-each

While we are working on IT projects, you might get requirements such as provisioning hundreds of app services for a project. If you choose to do that task manually, that would get long time to complete the task. As a solution, we can use Infrastructure automation tools such as Azure CLI, ARM template, Terraform, etc. However, we need to write these Infa scripts well organized manner and manageable way. Otherwise, you will get into more trouble of maintaining long and repetitive scripts.

Terraform has several ways such as modules and loops to reduce number of lines of the script. In this blog, we will be discussing the for-each loop of the Terraform.

In the following sample we use main.tf and variable.tf files.  Three app service plans and three app services will be created using the script. Let's go thought the Main.tf file to understand how we define the for-each.

First, we create the resource group with following script. We create an Azure resource group called "rg-dev-appservice" using this script section.

resource "azurerm_resource_group" "appservicerg" {

  name     = "rg-dev-appservice"

  location = "West Europe"

}

Following script is used to create the appservice plan. We use for-each and use same resource block to create multiple app service plans.

We need to add "for_each  = var.appservice" to beginning of the resource block. var.appservice is the variable name which has the names of the resources we are going to create with the loop. You would be able to learn more in variable.tf explanation.

Resource name has defined as "plan-${each.value.serviceplan}". This will read each serviceplan value in the appservice variable via  for-each loop and create app service plan names.

resource "azurerm_app_service_plan" "appserviceplan" {

  for_each            = var.appservice   

  name                = "plan-${each.value.serviceplan}"

  location            = azurerm_resource_group.appservicerg.location

  resource_group_name = azurerm_resource_group.appservicerg.name

  sku {

    tier = "Standard"

    size = "S1"

  }

}

Now we have resource block to create multiple app service plans using the for-each. Let's see how we can create multiple app services using the for-each loop.

The resource name given as "app-${each.key}". Hence, loop will read key of the appservice variable via loop and create the name for the resource. Further, we need to provide the app service plan we are going to use with each app service. We can do that by providing the app service plan id also as the loop value (azurerm_app_service_plan.appserviceplan[each.key].id).

resource "azurerm_app_service" "appservicetest" {

  for_each            = var.appservice   

  name                = "app-${each.key}"

  location            = azurerm_resource_group.appservicerg.location

  resource_group_name = azurerm_resource_group.appservicerg.name

  app_service_plan_id = azurerm_app_service_plan.appserviceplan[each.key].id

  site_config {

    dotnet_framework_version = "v4.0"

    scm_type                 = "LocalGit"

  }

app_settings = {

    "SOME_KEY" = "some-value"

  }

}

Find the main.tf script as follows

resource "azurerm_resource_group" "appservicerg" {
  name     = "rg-dev-appservice"
  location = "West Europe"
}

resource "azurerm_app_service_plan" "appserviceplan" {
  for_each            = var.appservice   
  name                = "plan-${each.value.serviceplan}"
  location            = azurerm_resource_group.appservicerg.location
  resource_group_name = azurerm_resource_group.appservicerg.name

  sku {
    tier = "Standard"
    size = "S1"
  }
}

resource "azurerm_app_service" "appservicetest" {
  for_each            = var.appservice   
  name                = "app-${each.key}"
  location            = azurerm_resource_group.appservicerg.location
  resource_group_name = azurerm_resource_group.appservicerg.name
  app_service_plan_id = azurerm_app_service_plan.appserviceplan[each.key].id

  site_config {
    dotnet_framework_version = "v4.0"
    scm_type                 = "LocalGit"
  }

  app_settings = {
    "SOME_KEY" = "some-value"
  }

}

Let's look at the variable.tf  file to understand how to define appservice variable. Variable block would be similar to follows. app service is the name of the variable block. we use type "map" to use with loops. invoice, customer and sale are keys. serviceplan is the value of each key. This sample has only one value under each key, but, there can be multiple values under each key. 

variable appservice{
description = "Map of names to configuration."
  type        = map
  default     = {
    invoice = {
      serviceplan = "sp1"
    },
    customer = {
      serviceplan = "sp2"  
    },
    sale = {
      serviceplan = "sp3"  
    }
  }

Once execute the scripts we can find the resources has created in the azure subscription.


This blog explained how to use one resource block to create multiple resources using the for-each in terraform to create more maintainable infra scripts.




No comments:

Post a Comment