Search code examples
azureterraformterraform-provider-azure

Configure Storage Account with Sub Modules for each category


I need to create a sub module for each sub resource for Storage Account. I am working on Queue and looking for a way to reference arguments foreach module.

Variable

variable "queues" {
  type = map(object({
    metadata = optional(map(string))
    name     = string
    role_assignments = optional(map(object({
      role_definition_id_or_name             = string
      principal_id                           = string
      description                            = optional(string, null)
      skip_service_principal_aad_check       = optional(bool, false)
      condition                              = optional(string, null)
      condition_version                      = optional(string, null)
      delegated_managed_identity_resource_id = optional(string, null)
    })), {})
    timeouts = optional(object({
      create = optional(string)
      delete = optional(string)
      read   = optional(string)
      update = optional(string)
    }))
  }))
  default     = {}
}
resource "azapi_resource" "queue" {
  for_each = var.queues

  type = "Microsoft.Storage/storageAccounts/queueServices/queues@2023-01-01"
  body = jsonencode({
    properties = {
      # metadata = each.value.metadata
    }
  })
  name                      = each.value.name
  parent_id                 = "${azurerm_storage_account.this.id}/queueServices/default"
  schema_validation_enabled = false

  dynamic "timeouts" {
    for_each = each.value.timeouts == null ? [] : [each.value.timeouts]
    content {
      create = timeouts.value.create
      delete = timeouts.value.delete
      read   = timeouts.value.read
    }
  }
}
module "storage_queue" {
  source = "./modules/storage_queue"

  for_each = var.queues

  name = each.value.name (
  
}

Error i get when i trying to add name:

Unexpected attribute: An attribute named "name" is not expected here Terraform

During the Validation shows following error

│
│   on ../../main.queues.tf line 8, in module "storage_queue":
│    8:   name = each.value
│
│ An argument named "name" is not expected here. ```


Solution

  • Configure Storage Account with Sub Modules for each category using terraform.

    To define a sub-module/child-modules using for-each sub-resource and referencing arguments inside a storage account we need to follow the specific sequence while doing so as the parameters are depending on each other.

    The general understanding for sub-module we need to start writing the sub-module configuration first and then with following up root configuration. So, during sometimes reversing the sequence may also cause the issue you're facing.

    I tried a terraform configuration of your requirement by adding name under module configuration of queue and I was able to overcome the issue and I was able to achieve the requirement successfully using azapi resource for storage queue

    Terraform configuration:

    main.tf:

    provider "azurerm" {
      features {}
    }
    
    variable "queues" {
      type = map(object({
        metadata = optional(map(string))
        name     = string
        role_assignments = optional(map(object({
          role_definition_id_or_name             = string
          principal_id                           = string
          description                            = optional(string, null)
          skip_service_principal_aad_check       = optional(bool, false)
          condition                              = optional(string, null)
          condition_version                      = optional(string, null)
          delegated_managed_identity_resource_id = optional(string, null)
        })), {})
        timeouts = optional(object({
          create = optional(string)
          delete = optional(string)
          read   = optional(string)
          update = optional(string)
        }))
      }))
      default = {}
    }
    
    
    resource "azurerm_resource_group" "example" {
      name     = "sampletestvk-rg"
      location = "East US"
    }
    
    resource "azurerm_storage_account" "example" {
      name                     = "exvksbstrageacct"
      resource_group_name      = azurerm_resource_group.example.name
      location                 = azurerm_resource_group.example.location
      account_tier             = "Standard"
      account_replication_type = "LRS"
    }
    
    module "storage_queue" {
      source             = "./modules/storage_queue"
      for_each           = var.queues
      name               = each.value.name
      metadata           = lookup(each.value, "metadata", {})
      storage_account_id = azurerm_storage_account.example.id
      timeouts           = lookup(each.value, "timeouts", null)
    }
    

    module/storage_queue/main.tf

    terraform {
      required_providers {
        azapi = {
          source = "azure/azapi"
        }
      }
    }
    
    variable "name" {
      description = "The name of the queue."
      type        = string
    }
    
    variable "metadata" {
      description = "Metadata info for the queue."
      type        = map(string)
      default     = {}
    }
    
    variable "storage_account_id" {
      description = "The ID of the storage account."
      type        = string
    }
    
    variable "timeouts" {
      description = "Timeouts of the queue."
      type = object({
        create = optional(string)
        delete = optional(string)
        read   = optional(string)
      })
      default = null
    }
    
    resource "azapi_resource" "queue" {
      type = "Microsoft.Storage/storageAccounts/queueServices/queues@2023-01-01"
      body = jsonencode({
        properties = {
          metadata = var.metadata
        }
      })
      name                      = var.name
      parent_id                 = "${var.storage_account_id}/queueServices/default"
      schema_validation_enabled = false
    
      dynamic "timeouts" {
        for_each = var.timeouts == null ? [] : [var.timeouts]
        content {
          create = timeouts.value.create
          delete = timeouts.value.delete
          read   = timeouts.value.read
        }
      }
    }
    

    Deployment succeeded:

    enter image description here

    enter image description here