Create multiple Azure Storage Account with Multiple FileShare under each Storage Account

I am trying to create multiple Azure Storage accounts with specific Azure File shares under each account using the variable type as map:object. I have created the following terraform code but getting the error :

Code

StorageAccount = {
  "dev" = {
    SName       = "test"
    SAFileShare = [logs1", "logs3"]
  }
  "prd" = {
    SName       = "test1"
    SAFileShare = ["logs3", "logs4"]

  }
}

variable "StorageAccount" {
  type = map(object({
    SName       = string
    SAFileShare = list(string)
    SABlob      = list(string)
  }))
}


# Storage Account
resource "azurerm_storage_account" "Storage" {
  for_each                 = var.StorageAccount
  name                     = each.value["SName"]
  location                 = var.Location
  resource_group_name      = azurerm_resource_group.ResourceGroup.name
  account_tier             = var.accountTier
  account_replication_type = var.accountReplicationType
}

# File Share 
resource "azurerm_storage_share" "FileShare" {
  for_each             = var.StorageAccount
  name                 = each.value["SAFileShare"]
  storage_account_name = azurerm_storage_account.Storage[each.key].name
  quota                = 50
}

Error

Error: Incorrect attribute value type
│
│   on main.tf line 4, in resource "azurerm_storage_share" "FileShare":
│    4:   name                 = each.value["SAFileShare"]
│     ├────────────────
│     │ each.value["SAFileShare"] is list of string with 2 elements
│
│ Inappropriate value for attribute "name": string required.

The error you are encountering is due to the way you are iterating over the SAFileShare list within each storage account. The azurerm_storage_share resource expects a single string for the name attribute, but you are providing a list of strings. To resolve this, you need to modify your for_each to iterate over each file share within each storage account.

Here’s a revised version of your Terraform code that should work:

variable “StorageAccount” {
type = map(object({
SName = string
SAFileShare = list(string)
}))
}

Storage Account

resource “azurerm_storage_account” “Storage” {
for_each = var.StorageAccount
name = each.value.SName
location = var.Location
resource_group_name = azurerm_resource_group.ResourceGroup.name
account_tier = var.accountTier
account_replication_type = var.accountReplicationType
}

File Share

resource “azurerm_storage_share” “FileShare” {
for_each = { for sa_key, sa_value in var.StorageAccount : sa_key => sa_value.SAFileShare… }
name = each.value
storage_account_name = azurerm_storage_account.Storage[each.key].name
quota = 50
}

Hii,
here the foreach expresion is correct and for study purpose I ran the code but on fileshare name attribute its giving error as below:

on Az_fileShare.tf line 29, in resource "azurerm_storage_share" "FileShare":
│   29: name = each.value
│     ├────────────────
│     │ each.value is list of string with 2 elements
│
│ Inappropriate value for attribute "name": string required.

if I give index as each.value[0] its working but in this case he wants fileshare to be for both strings, so how can he do??

Here’s the solution for your situation:

resource "azurerm_storage_share" "FileShare" {
  for_each             = merge([ for sa_key, sa_value in var.StorageAccount: { for val in sa_value["SAFileShare"] : val => sa_key }]...)
  name                 = each.key
  storage_account_name = azurerm_storage_account.Storage[each.value].name
  quota                = 50
}

you can use merge function to loop twice in your map of object and do your iteration.
the result of this merge function is as follow:

Test = {
      + logs1 = "dev"
      + logs2 = "dev"
      + logs3 = "prd"
      + logs4 = "prd"
    }

Thank you…