Reputation: 97
I'm trying to figure out how to use what I think might require a nested loop in Terraform.
I have a module that creates Azure storage accounts from a list of storage accounts.
I would like to extend this module to be able to include a list of storage containers inside the definition.
The variable is a map object for the storage_account that contains a sub map object for containers as shown below:
variables.tf
variable "location" {
type = string
description = "Location for storage account resource"
}
variable "resource_group_name" {
type = string
description = "Resource group the resource will fall under"
}
variable "storage_account" {
type = map(object({
name = string
access_tier = string
account_kind = string
account_replication_type = string
account_tier = string
containers = optional(map(object({
name = string
container_access_type = optional(string, "private")
})))
network_rules = list(object({
default_action = string
bypass = optional(set(string))
ip_rules = optional(set(string))
virtual_network_subnet_ids = optional(set(string))
}))
}))
}
The module code looks like this:
main.tf
resource "azurerm_storage_account" "storage" {
for_each = var.storage_account
name = each.value.name
resource_group_name = var.resource_group_name
location = var.location
account_tier = each.value.account_tier
account_replication_type = each.value.account_replication_type
account_kind = each.value.account_kind
access_tier = each.value.access_tier
public_network_access_enabled = true
tags = var.tags
}
resource "azurerm_storage_container" "storage"{
for_each = {
for key, value in var.storage_account : key => value
}
name = each.value.name
storage_account_name = azurerm_storage_account.storage[each.key].name
}
I call/use the module using something like this:
main.tf
module "storage_account" {
source = "./modules/azurerm_storage_account"
resource_group_name = "rg-temp"
location = "uksouth"
storage_account = {
"bigrandomthingy01" = {
name = "bigrandomthingy01"
account_kind = "StorageV2"
account_tier = "Standard"
account_replication_type = "LRS"
access_tier = "Hot"
network_rules = []
containers = {
"container-01" = {
name = "randomaa"
container_access_type = "private"
},
"container-02" = {
name = "randomab"
container_access_type = "private"
}
}
},
"bigrandomthingy02" = {
name = "bigrandomthingy02"
account_kind = "StorageV2"
account_tier = "Standard"
account_replication_type = "LRS"
access_tier = "Hot"
network_rules = []
containers = {
"container-01" = {
name = "random01"
container_access_type = "private"
},
"container-02" = {
name = "random02"
container_access_type = "private"
}
}
}
}
}
The code loops over each storage account and creates it no problem.
But it then also creates a single storage_container in the account that has the same name as the storage account.
I know my loop code is way off, but I'm not sure what I need to do to loop over the list of containers to create in each storage account?
Is this something that would need me to use flatten
? Would this be an 'inner and outer' loop?
I've never really nested a loop before in TF, it's very confusing.
Upvotes: 0
Views: 106
Reputation: 7725
You can use the code below to create two storage accounts
, each containing two containers
with specified names.
Here is my directory structure
├── main.tf
├── modules
│ └── azurerm_storage_account
│ ├── main.tf
│ └── variables.tf
main.tf
provider "azurerm" {
features {}
subscription_id = "8332bf56-aa7c-xxxxxxx-d7e60e5f09a9"
}
resource "azurerm_resource_group" "example" {
name = "storage-rg"
location = "East US"
}
module "storage_accounts" {
source = "./modules/azurerm_storage_account"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
storage_accounts = {
"venaktstoragedemo" = ["venkatcontainer1", "venkatcontainer2"],
"thejastoragedemo" = ["thejacontainer1", "thejacontainer2"]
}
}
modules/azurerm_storage_account/main.tf
resource "azurerm_storage_account" "this" {
for_each = var.storage_accounts
name = each.key
resource_group_name = var.resource_group_name
location = var.location
account_tier = "Standard"
account_replication_type = "LRS"
}
locals {
storage_containers = flatten([
for storage_account, containers in var.storage_accounts : [
for container in containers : {
name = container
storage_account_name = storage_account
}
]
])
}
resource "azurerm_storage_container" "this" {
for_each = { for container in local.storage_containers : container.name => container }
name = each.value.name
storage_account_name = each.value.storage_account_name
container_access_type = "private"
}
modules/storage_with_containers/variables.tf
variable "resource_group_name" {
description = "The name of the resource group."
type = string
}
variable "location" {
description = "The Azure location where the storage accounts will be created."
type = string
}
variable "storage_accounts" {
description = "A map of storage accounts with their associated container names."
type = map(list(string))
}
terrafrom apply
After running the Terraform code, two storage accounts and two containers in each account were created successfully.
Upvotes: 1