terraformterraform-loop

terraform dynamic block for_each construction


Newbie question.

This is my variable file

 instances = ["instance1", "instance2"]

cors_rules = {
  instance1 = {
    origin       = ["https://instance.com", "http://localhost:4200"],
  },
  instance2 = {
    origin        = [https://instance2.com"", "http://localhost:4200"],
  }

}

This is my resource file

resource "azurerm_storage_account" "storage-account" {
  count                    = length(var.instances)
  name                     = "${var.storageAccount.name}${var.instances[count.index]}"
  location                 = var.location
  resource_group_name      = var.resource_name
  account_tier             = "Standard"
  account_replication_type = "LRS"


 blob_properties {
    dynamic "cors_rule" {
        for_each = need to construct 
  }
      content {
        allowed_origins    = 
        allowed_methods    = ["DELETE", "GET", "POST", "OPTIONS", "PUT", "PATCH"]
        allowed_headers    = ["*"]
        exposed_headers    = ["*"]
        max_age_in_seconds = 200
      }
    }
  }
}

Current i am having two instances. I want to add allowed_origins ["https://instance.com", "http://localhost:4200"] in one instance and [https://instance2.com"", "http://localhost:4200"] in second instance. can you help me with constructing a for_each inside dynamic block?


Solution

  • You don't need a dynamic cors_rule block in this case, because the azurerm_storage_account is configured to accept a list. I would use the cors_rule object as a map so that you can look up the rules by their name. This would allow you to dynamically fetch the cors block based on a for_each of the azurerm_storage_account. I'll include an example below.

     instances = ["instance1", "instance2"]
    
    cors_rules = {
      instance1 = {
        origin       = ["https://instance.com", "http://localhost:4200"],
      },
      instance2 = {
        origin        = [https://instance2.com"", "http://localhost:4200"],
      }
    
    }
    
    resource "azurerm_storage_account" "storage-account" {
      for_each                 = var.instances
      name                     = "${var.storageAccount.name}${each.value}"
      location                 = var.location
      resource_group_name      = var.resource_name
      account_tier             = "Standard"
      account_replication_type = "LRS"
    
    
     blob_properties {
          cors_rule {
            content {
                allowed_origins    = var.cors_rules[each.value]
                allowed_methods    = ["DELETE", "GET", "POST", "OPTIONS", "PUT", "PATCH"]
                allowed_headers    = ["*"]
                exposed_headers    = ["*"]
                max_age_in_seconds = 200
            }
          }
        }
      }
    }
    
    

    You could also merge the two variables, and simply for_each off the objects. This is a better approach anyways because Terraform will index off the map key name instead of list index which can change when you add/remove values from the list.

    instances = {
       instance1 = {
        origin  = ["https://instance.com", "http://localhost:4200"]
       },
      instance2 = {
        origin  = [https://instance2.com"", "http://localhost:4200"],
      }
    }
    
    resource "azurerm_storage_account" "storage-account" {
      for_each                 = var.instances
      name                     = "${var.storageAccount.name}${each.key}"
      location                 = var.location
      resource_group_name      = var.resource_name
      account_tier             = "Standard"
      account_replication_type = "LRS"
    
    
     blob_properties {
          cors_rule {
            content {
                allowed_origins    = each.value["origin"]
                allowed_methods    = ["DELETE", "GET", "POST", "OPTIONS", "PUT", "PATCH"]
                allowed_headers    = ["*"]
                exposed_headers    = ["*"]
                max_age_in_seconds = 200
            }
          }
        }
      }
    }