skip to Main Content

I wrote it as follows by referring to this link.

https://github.com/claranet/terraform-azurerm-storage-account/blob/master/r-storage-account.tf

Blocks of type "dynamic" are not expected here error occurs. The "dynamic" indicator seems to be getting an error somewhere, but I can’t find it. I ask for your help me. I’m a beginner who just started terraform.

  • Error
│ Error: Unsupported block type
│
│   on storage.tf line 54, in resource "azurerm_storage_account" "storageaccount":
│   54:       dynamic "private_link_access" {
│
│ Blocks of type "dynamic" are not expected here.
╵
  • main.tf
resource "azurerm_storage_account" "storageaccount" {
  name                     = var.azstorageaccount_name
  resource_group_name      = data.azurerm_resource_group.system_rg_name.name
  location                 = var.location
  account_tier             = var.account_tier
  account_replication_type = var.account_replication_type
  account_kind             = var.account_kind
  access_tier              = var.access_tier
  large_file_share_enabled = var.large_file_share_enabled
  is_hns_enabled           = var.is_hns_enabled
  sftp_enabled          = var.is_sftp_enabled
  public_network_access_enabled     = var.public_network_access_enabled

  blob_properties  {
    container_delete_retention_policy {
      days = var.container_delete_retention_policy
    }
    delete_retention_policy {
      days = var.delete_retention_policy
    }
  }
  
  dynamic "network_rules" {
    for_each = var.network_rules
    content {
      default_action             = "Deny"
      ip_rules                   = var.network_rules.ip_rules
      virtual_network_subnet_ids = var.network_rules.subnet_ids
      bypass                     = var.network_rules.bypass
    }
      dynamic "private_link_access" {
        for_each = var.private_link_access
        content {
          endpoint_resource_id = private_link_access.value.endpoint_resource_id
          endpoint_tenant_id   = private_link_access.value.endpoint_tenant_id
      }
    }
  }
}
  • var.tf
variable "location" {
  type    = string
  default = "Korea Central"
}

variable "system_rg" {
  description = "The Prefix used for all resources in this example"
  type        = string
  default     = "testrg"
}

variable "tag" {
  type    = string
  default = "prd"
}

variable "azstorageaccount_name" {
  type    = string
  default = "teststorage001"
}

variable "large_file_share_enabled" {
  type    = string
  default = "false"
}

variable "account_tier" {
  type = string
  default = "Standard"
}

variable "account_replication_type" {
  type = string
  default = "LRS"
}

variable "account_kind" {
  type = string
  default = "StorageV2"
}

variable "access_tier" {
  type = string
  default = "Hot"
}

variable "is_hns_enabled" {
  type = string
  default = "false"
}

variable "is_sftp_enabled" {
  type = string
  default = "false"
}

variable "public_network_access_enabled" {
  type    = string
  default = "true"
}

variable "container_delete_retention_policy" {
  type    = string
  default = "7"
}

variable "delete_retention_policy" {
  type    = string
  default = "7"
}

variable "network_rules" {
  type = object({
    ip_rules = list(string)
    subnet_ids = list(string)
    bypass = list(string)
  })
  default = {
    ip_rules = [ "xxx.xxx.xxx.xxx", "xxx.xxx.xxx.xxx" ]
    subnet_ids = [ "/subscriptions/000000-000000-00000/resourceGroups/...ids" ]
    bypass = [ "Logging", "Metrics" ]
  }
}

variable "private_link_access" {
  description = "List of Privatelink objects to allow access from."
  type = list(object({
    endpoint_resource_id = string
    endpoint_tenant_id = optional(string, null)
  }))
  default = [ 
    { 
      endpoint_resource_id = "/subscriptions/0000-000000-000000-0000/providers/Microsoft.Security/datascanners/storageDataScanner"
      endpoint_tenant_id = null
    },
    # { 
    #   endpoint_resource_id = 
    #   endpoint_tenant_id = 
    # }
  ]
  nullable = false
}

With your help, we found out that there was a typo. And I corrected it as below, but there was another error. I ask for your help once again.

  dynamic "network_rules" {
    for_each = var.network_rules
    content {
      default_action             = "Deny"
      ip_rules                   = var.network_rules.ip_rules
      virtual_network_subnet_ids = var.network_rules.subnet_ids
      bypass                     = var.network_rules.bypass
      dynamic "private_link_access" {
        for_each = var.private_link_access
        content {
          endpoint_resource_id = private_link_access.value.endpoint_resource_id
          endpoint_tenant_id   = private_link_access.value.endpoint_tenant_id
        }
      }
    }
  }
Planning failed. Terraform encountered an error while generating this plan.

╷
│ Error: Too many network_rules blocks
│
│   on storage.tf line 48, in resource "azurerm_storage_account" "storageaccount":
│   48:     content {
│
│ No more than 1 "network_rules" blocks are allowed

2

Answers


  1. Chosen as BEST ANSWER

    "Too much network_rules blocks" I'm not sure, but I think this is the problem. I changed the code as below and confirmed that Terraform works correctly.

    • var.tf
    ###### Network rules block ######
    variable "network_rules_enabled" {
      description = "Boolean to enable Network Rules on the Storage Account, requires `network_bypass`, `allowed_cidrs`, `subnet_ids` or `default_firewall_action` correctly set if enabled."
      type        = bool
      default     = true
    }
    
    variable "network_rules_default_action" {
      type = string
      default = "Deny"
    }
    
    variable "network_rules_ip_rules" {
      type = list(string)
      default = [ "xxx.xxx.xxx.xxx" ]
    }
    
    # variable "network_rules_virtual_network_subnet_ids" {
    #   type = list(string)
    #   default = [ "/subscriptions/..." ]
    # }
    
    variable "network_rules_bypass" {
      type = list(string)
      default = [ "AzureServices" ]
    }
    
    variable "private_link_access" {
      description = "List of Privatelink objects to allow access from."
      type = list(object({
        endpoint_resource_id = string
        endpoint_tenant_id = optional(string, null)
      }))
      default = [ 
        { 
          endpoint_resource_id = "/subscriptions/.../Microsoft.Security/datascanners/storageDataScanner"
          endpoint_tenant_id = null
        },
        # { 
        #   endpoint_resource_id = 
        #   endpoint_tenant_id = 
        # }
      ]
      nullable = false
    }
    
    • main.tf
    ...
      dynamic "network_rules" {
        for_each = var.network_rules_enabled ? ["true"] : []
        content {
          default_action             = var.network_rules_default_action
          ip_rules                   = var.network_rules_ip_rules
          # virtual_network_subnet_ids = var.network_rules_virtual_network_subnet_ids
          bypass                     = var.network_rules_bypass
          dynamic "private_link_access" {
            for_each = var.private_link_access
            content {
              endpoint_resource_id = private_link_access.value.endpoint_resource_id
              endpoint_tenant_id   = private_link_access.value.endpoint_tenant_id
            }
          }
        }
      }
      tags = {
        Environment = "${var.tag}"
      }
    }
    ...
    
    

  2. Maybe because the nested dynamic block must be in the content block.

    dynamic "network_rules" {
    for_each = var.network_rules
    content {
      default_action             = "Deny"
      ip_rules                   = var.network_rules.ip_rules
      virtual_network_subnet_ids = var.network_rules.subnet_ids
      bypass                     = var.network_rules.bypass
    // } <- Do not close here.
      dynamic "private_link_access" {
        for_each = var.private_link_access
        content {
          endpoint_resource_id = private_link_access.value.endpoint_resource_id
          endpoint_tenant_id   = private_link_access.value.endpoint_tenant_id
      }
    }
    

    }

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search