### Terraform Configuration for IPAM Basic Example Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/ipam_basic/README.md This Terraform configuration sets up the necessary providers, modules, and resources for the IPAM basic example, including network manager and IPAM pool creation with retry configurations. ```hcl terraform { required_version = ">= 1.9.2" required_providers { azapi = { source = "Azure/azapi" version = "~> 2.4" } azurerm = { source = "hashicorp/azurerm" version = "~> 4.0" } random = { source = "hashicorp/random" version = "~> 3.5" } } } provider "azurerm" { features { resource_group { prevent_deletion_if_contains_resources = false } } } module "naming" { source = "Azure/naming/azurerm" version = "0.4.2" } resource "azurerm_resource_group" "this" { location = local.selected_region name = "${module.naming.resource_group.name_unique}-retry-test" } data "azurerm_subscription" "this" {} # Create Network Manager and IPAM Pool resource "azapi_resource" "network_manager" { location = azurerm_resource_group.this.location name = replace(azurerm_resource_group.this.name, "rg-", "avnm-") parent_id = azurerm_resource_group.this.id type = "Microsoft.Network/networkManagers@2024-07-01" body = { properties = { networkManagerScopeAccesses = [] networkManagerScopes = { subscriptions = [data.azurerm_subscription.this.id] } } } retry = { interval_seconds = 10 max_interval_seconds = 180 error_message_regex = ["CannotDeleteResource", "Cannot delete resource while nested resources exist"] } schema_validation_enabled = false } resource "azapi_resource" "ipam_pool" { location = azurerm_resource_group.this.location name = "pool-retry-test" parent_id = azapi_resource.network_manager.id type = "Microsoft.Network/networkManagers/ipamPools@2024-07-01" body = { properties = { addressPrefixes = ["10.0.0.0/16"] description = "IPAM Pool for testing retry logic with multiple simultaneous subnet allocations" displayName = "Retry Test Pool" } } retry = { interval_seconds = 10 max_interval_seconds = 180 error_message_regex = ["BadRequest", "Ipam pool.*has Azure resources associated"] } schema_validation_enabled = false depends_on = [azapi_resource.network_manager] } # TEST: Multiple IPAM subnets created simultaneously (no time delays) ``` -------------------------------- ### Terraform Module Usage Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/complete/_footer.md Standard Terraform commands to initialize, plan, and apply the module. Ensure Terraform is installed and Azure CLI is authenticated. ```bash terraform init terraform plan terraform apply ``` -------------------------------- ### Example - IPAM Subnet Allocation Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/modules/subnet/README.md Demonstrates IPAM usage for dynamic subnet allocation. Ensure the parent VNet is IPAM-enabled and the IPAM pool exists in the same region. ```terraform module "avm-res-network-virtualnetwork-subnet" { source = "Azure/avm-res-network-virtualnetwork/azurerm//modules/subnet" name = "subnet-app" parent_id = azurerm_virtual_network.ipam_vnet.id # Must be IPAM-enabled VNet # Dynamic allocation from IPAM pool ipam_pools = [{ pool_id = azapi_resource.ipam_pool.id prefix_length = 24 # /24 subnet (256 IP addresses) }] } ``` -------------------------------- ### Deploying a Virtual Network with Encryption and Peerings Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/complete/README.md This example demonstrates how to deploy a virtual network (vnet2) using the module, configuring its location, parent resource group, address space, and encryption settings. It also sets up a peering connection to another virtual network (vnet1) with specific transit and verification settings. ```terraform module "vnet2" { source = "../../" location = azurerm_resource_group.this.location parent_id = azurerm_resource_group.this.id address_space = ["10.0.0.0/27"] encryption = { enabled = true enforcement = "AllowUnencrypted" } name = "${module.naming.virtual_network.name_unique}2" peerings = { peertovnet1 = { name = "${module.naming.virtual_network_peering.name_unique}-vnet2-to-vnet1" remote_virtual_network_resource_id = module.vnet1.resource_id allow_forwarded_traffic = true allow_gateway_transit = true allow_virtual_network_access = true do_not_verify_remote_gateways = false enable_only_ipv6_peering = false use_remote_gateways = false create_reverse_peering = true reverse_name = "${module.naming.virtual_network_peering.name_unique}-vnet1-to-vnet2" reverse_allow_forwarded_traffic = false reverse_allow_gateway_transit = false reverse_allow_virtual_network_access = true reverse_do_not_verify_remote_gateways = false reverse_enable_only_ipv6_peering = false reverse_use_remote_gateways = false sync_remote_address_space_enabled = true sync_remote_address_space_triggers = [ var.address_space_vnet1, var.address_space_vnet2 ] } } } ``` -------------------------------- ### Create IPAM Subnet with Dynamic Allocation Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/modules/subnet/_header.md This example demonstrates creating a subnet using IPAM for dynamic IP address allocation. The parent Virtual Network must be IPAM-enabled, and an IPAM pool ID with a specified prefix length must be provided. ```terraform module "avm-res-network-virtualnetwork-subnet" { source = "Azure/avm-res-network-virtualnetwork/azurerm//modules/subnet" name = "subnet-app" parent_id = azurerm_virtual_network.ipam_vnet.id # Must be IPAM-enabled VNet # Dynamic allocation from IPAM pool ipam_pools = [{ pool_id = azapi_resource.ipam_pool.id prefix_length = 24 # /24 subnet (256 IP addresses) }] } ``` -------------------------------- ### Terraform Configuration and Provider Setup Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/complete/README.md Defines the required Terraform version, providers (azurerm, http, random), and provider configurations, including specific features for the azurerm provider. ```hcl terraform { required_version = ">= 1.9, < 2.0" required_providers { azurerm = { source = "hashicorp/azurerm" version = "~> 4.0" } http = { source = "hashicorp/http" version = "~> 3.4" } random = { source = "hashicorp/random" version = "~> 3.5" } } } provider "azurerm" { features { resource_group { prevent_deletion_if_contains_resources = false } } storage_use_azuread = true } ``` -------------------------------- ### Terraform - IPAM Enabled VNet and Subnets Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/existing_vnet_ipam_subnets/_header.md This example demonstrates creating an IPAM-enabled VNet and then adding both IPAM and traditional subnets to it using the enhanced subnet module. It showcases dynamic IPAM allocation and static addressing within the same VNet. ```terraform module "vnet_ipam_enabled" { source = "../../" # ... other vnet configurations ... ipam_enabled = true } module "subnet_ipam_test" { source = "../subnet" # ... ipam subnet configurations ... virtual_network_name = module.vnet_ipam_enabled.name ipam_pools = [ { name = "default" # ... pool configurations ... } ] } module "subnet_traditional_test" { source = "../subnet" # ... traditional subnet configurations ... virtual_network_name = module.vnet_ipam_enabled.name address_prefixes = ["10.0.1.0/24"] } ``` -------------------------------- ### Create Basic Subnet with Explicit Addressing Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/modules/subnet/_header.md Use this example to create a new subnet with traditional explicit IP addressing. Ensure the parent_id points to an existing Virtual Network. ```terraform module "avm-res-network-virtualnetwork-subnet" { source = "Azure/avm-res-network-virtualnetwork/azurerm//modules/subnet" name = "subnet-web" parent_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVNet" address_prefixes = ["10.0.0.0/24"] } ``` -------------------------------- ### IPAM Virtual Network with Multiple Subnets Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/_header.md This example demonstrates using IPAM for VNet and subnet address allocation. Ensure the parent VNet is created with IPAM pools for its address space. ```terraform module "avm-res-network-virtualnetwork" { source = "Azure/avm-res-network-virtualnetwork/azurerm" location = "East US" name = "myIPAMVNet" parent_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup" # VNet address space from IPAM pool ipam_pools = [{ id = azapi_resource.ipam_pool.id prefix_length = 24 }] # Multiple subnets allocated from IPAM pool subnets = { "web_subnet" = { name = "subnet-web" ipam_pools = [{ pool_id = azapi_resource.ipam_pool.id prefix_length = 26 }] } "app_subnet" = { name = "subnet-app" ipam_pools = [{ pool_id = azapi_resource.ipam_pool.id prefix_length = 26 }] } "data_subnet" = { name = "subnet-data" ipam_pools = [{ pool_id = azapi_resource.ipam_pool.id prefix_length = 27 }] } } } ``` -------------------------------- ### Basic Virtual Network Peering Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/modules/peering/_header.md Use this example to create a new bi-directional peering between two virtual networks. Ensure the virtual network resource IDs are correctly specified. ```terraform module "avm-res-network-virtualnetwork-subnet" { source = "Azure/avm-res-network-virtualnetwork/azurerm//modules/peering" virtual_network = { resource_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroupSpoke/providers/Microsoft.Network/virtualNetworks/myVNetLocal" } remote_virtual_network = { resource_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroupHub/providers/Microsoft.Network/virtualNetworks/myVNetRemote" } name = "local-to-remote" allow_forwarded_traffic = true allow_gateway_transit = true allow_virtual_network_access = true use_remote_gateways = false create_reverse_peering = true reverse_name = "remote-to-local" reverse_allow_forwarded_traffic = false reverse_allow_gateway_transit = false reverse_allow_virtual_network_access = true reverse_use_remote_gateways = false } ``` -------------------------------- ### Pinning AVM Module Version in Terraform Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/AGENTS.md When using AVM modules, it's crucial to pin to a specific version for predictable deployments. This example shows how to specify the version. ```terraform version = "1.2.3" ``` -------------------------------- ### Terraform Module Source from GitHub Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/AGENTS.md This format shows how to specify the source of an AVM module when it's hosted on GitHub. ```terraform source = "https://github.com/Azure/terraform-avm-{type}-{service}-{resource}" ``` -------------------------------- ### Basic Virtual Network with Subnets Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/_header.md Use this snippet to create a virtual network with static IP addressing and define subnets within it. ```terraform module "avm-res-network-virtualnetwork" { source = "Azure/avm-res-network-virtualnetwork/azurerm" address_space = ["10.0.0.0/16"] location = "eastus2" name = "vnet-demo-eastus2-001" parent_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-demo-eastus2-001" subnets = { "subnet1" = { name = "subnet1" address_prefixes = ["10.0.0.0/24"] } "subnet2" = { name = "subnet2" address_prefixes = ["10.0.1.0/24"] } } } ``` -------------------------------- ### Define Virtual Network (vnet-1) with Subnets and Settings Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/complete/README.md Configures the first virtual network (vnet-1) using the virtual network module. It includes settings for address space, DDoS protection, diagnostic settings, DNS servers, encryption, flow timeout, name, role assignments, and subnets. ```terraform module "vnet1" { source = "../../" location = azurerm_resource_group.this.location parent_id = azurerm_resource_group.this.id address_space = var.address_space_vnet1 ddos_protection_plan = { id = azurerm_network_ddos_protection_plan.this.id # due to resource cost enable = false } diagnostic_settings = { sendToLogAnalytics = { name = "sendToLogAnalytics" workspace_resource_id = azurerm_log_analytics_workspace.this.id log_analytics_destination_type = "Dedicated" } } dns_servers = { dns_servers = ["8.8.8.8", "1.1.1.1", "1.0.0.1"] } enable_vm_protection = true encryption = { enabled = true #enforcement = "DropUnencrypted" # NOTE: This preview feature requires approval, leaving off in example: Microsoft.Network/AllowDropUnecryptedVnet enforcement = "AllowUnencrypted" } flow_timeout_in_minutes = 30 name = module.naming.virtual_network.name_unique role_assignments = { role1 = { principal_id = azurerm_user_assigned_identity.this.principal_id role_definition_id_or_name = "Contributor" } } subnets = { subnet0 = { name = "${module.naming.subnet.name_unique}0" default_outbound_access_enabled = false #sharing_scope = "Tenant" #NOTE: This preview feature requires approval, leaving off in example: Microsoft.Network/EnableSharedVNet address_prefixes = ["192.168.0.0/24", "192.168.2.0/24"] } subnet1 = { name = "${module.naming.subnet.name_unique}1" address_prefixes = ["192.168.1.0/24"] default_outbound_access_enabled = false delegations = [{ name = "Microsoft.Web.serverFarms" service_delegation = { name = "Microsoft.Web/serverFarms" } }] nat_gateway = { id = azurerm_nat_gateway.this.id } network_security_group = { id = azurerm_network_security_group.https.id } route_table = { id = azurerm_route_table.this.id } service_endpoints_with_location = [ { service = "Microsoft.Storage" }, { service = "Microsoft.KeyVault" locations = [azurerm_resource_group.this.location] } ] service_endpoint_policies = { policy1 = { id = azurerm_subnet_service_endpoint_storage_policy.this.id } } role_assignments = { role1 = { principal_id = azurerm_user_assigned_identity.this.principal_id ``` -------------------------------- ### Terraform Module Source from Registry Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/AGENTS.md This format shows how to specify the source of an AVM module when using the Terraform Registry. ```terraform source = "https://registry.terraform.io/modules/Azure/{module}/azurerm/latest" ``` -------------------------------- ### Terraform Configuration for Enhanced Subnet Module Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/existing_vnet_ipam_subnets/README.md This Terraform configuration sets up the necessary providers and resources, including a network manager and IPAM pool, to demonstrate the enhanced subnet module. It also creates an IPAM-enabled VNet and an IPAM subnet using the standalone subnet module. ```hcl terraform { required_version = ">= 1.9.2" required_providers { azapi = { source = "Azure/azapi" version = "~> 2.4" } azurerm = { source = "hashicorp/azurerm" version = "~> 4.0" } random = { source = "hashicorp/random" version = "~> 3.5" } } } provider "azurerm" { features { resource_group { prevent_deletion_if_contains_resources = false } } } module "naming" { source = "Azure/naming/azurerm" version = "0.4.2" } resource "azurerm_resource_group" "this" { location = local.selected_region.name name = module.naming.resource_group.name_unique } data "azurerm_subscription" "this" {} # Network Manager and IPAM Pool resource "azapi_resource" "network_manager" { location = azurerm_resource_group.this.location name = replace(module.naming.resource_group.name_unique, module.naming.resource_group.slug, "avnm") parent_id = azurerm_resource_group.this.id type = "Microsoft.Network/networkManagers@2024-07-01" body = { properties = { networkManagerScopeAccesses = [] networkManagerScopes = { subscriptions = [data.azurerm_subscription.this.id] } } } retry = { interval_seconds = 10 max_interval_seconds = 180 error_message_regex = ["CannotDeleteResource", "Cannot delete resource while nested resources exist"] } schema_validation_enabled = false } resource "azapi_resource" "ipam_pool" { location = azurerm_resource_group.this.location name = "pool-subnet-test" parent_id = azapi_resource.network_manager.id type = "Microsoft.Network/networkManagers/ipamPools@2024-07-01" body = { properties = { addressPrefixes = ["10.0.0.0/16"] description = "IPAM Pool for standalone subnet module testing" displayName = "Subnet Test Pool" } } retry = { interval_seconds = 10 max_interval_seconds = 180 error_message_regex = ["BadRequest", "Ipam pool.*has Azure resources associated"] } schema_validation_enabled = true } # Create VNet with IPAM addressing (REQUIRED for IPAM subnets) # NOTE: In production, you would typically reference an existing IPAM-enabled VNet # using data sources rather than creating a new one module "ipam_vnet" { source = "../../" location = azurerm_resource_group.this.location parent_id = azurerm_resource_group.this.id enable_telemetry = true # VNet gets address space from IPAM pool ipam_pools = [{ id = azapi_resource.ipam_pool.id prefix_length = 16 # /16 VNet (65,536 IP addresses) }] name = "${module.naming.virtual_network.name_unique}-ipam-test" tags = { Environment = "test" Purpose = "ipam-subnet-module-demo" } } resource "azurerm_network_security_group" "app" { location = azurerm_resource_group.this.location name = "${module.naming.network_security_group.name}-app" resource_group_name = azurerm_resource_group.this.name security_rule { access = "Allow" destination_address_prefix = "*" destination_port_ranges = ["80", "443"] direction = "Inbound" name = "AllowHTTP" priority = 1001 protocol = "Tcp" source_address_prefix = "*" source_port_range = "*" } } # Test: Create IPAM subnet using the standalone subnet module module "ipam_subnet" { source = "../../modules/subnet" name = "subnet-ipam-test" parent_id = module.ipam_vnet.resource_id # IPAM allocation ipam_pools = [{ pool_id = azapi_resource.ipam_pool.id prefix_length = 24 # /24 subnet (256 IP addresses) }] network_security_group = { id = azurerm_network_security_group.app.id } service_endpoints_with_location = [{ service = "Microsoft.Storage" locations = [local.selected_region.name, local.selected_region.paired_region_name] }] } # Test: Create traditional subnet using the same module ``` -------------------------------- ### VNet with IPAM Address Space and Traditional Subnets Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/ipam_vnet_only/README.md This snippet defines a Virtual Network where the overall address space is managed by IPAM, but individual subnets are configured with static address prefixes. Use this when you need centralized IP address management for the VNet but require specific, predictable IP ranges for your subnets. ```terraform module "vnet_ipam_traditional_subnets" { source = "../../" location = azurerm_resource_group.this.location parent_id = azurerm_resource_group.this.id # DNS servers configuration dns_servers = { dns_servers = toset(["1.1.1.1", "8.8.8.8"]) } enable_telemetry = true # VNet address space allocated from IPAM pool ipam_pools = [{ id = azapi_resource.ipam_pool.id number_of_ip_addresses = "65536" # /16 VNet from the /12 pool }] name = "${module.naming.virtual_network.name_unique}-ipam-vnet" # Traditional subnets with static addressing (IPAM VNet gets dynamic space) subnets = { # Static addressing - these addresses will work within common IPAM allocations web = { name = "subnet-web" address_prefixes = ["172.16.0.0/24"] # First /24 in common /16 IPAM range network_security_group = { id = azurerm_network_security_group.web.id } service_endpoints_with_location = [ { service = "Microsoft.Storage" locations = [local.selected_region.name, local.selected_region.paired_region_name] }, { service = "Microsoft.Sql" locations = [local.selected_region.name] } ] } app = { name = "subnet-app" address_prefixes = ["172.16.1.0/24"] # Second /24 in common /16 IPAM range network_security_group = { id = azurerm_network_security_group.app.id } service_endpoints_with_location = [{ service = "Microsoft.Storage" locations = [local.selected_region.name, local.selected_region.paired_region_name] }] } data = { name = "subnet-data" address_prefixes = ["172.16.2.0/25"] # /25 in common /16 IPAM range network_security_group = { id = azurerm_network_security_group.app.id } } # Small management subnet at end of range management = { name = "subnet-management" address_prefixes = ["172.16.255.240/28"] # Small management subnet network_security_group = { id = azurerm_network_security_group.app.id } } } tags = { Environment = "test" Purpose = "ipam-vnet-only-demo" Scenario = "ipam-vnet-traditional-subnets" } } ``` -------------------------------- ### Terraform Configuration for Virtual Network Peering with Specified Address Spaces Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/peer_only_specified_address_spaces/README.md This Terraform configuration sets up two virtual networks and configures a peering between them. It demonstrates how to use `local_peered_address_spaces` and `remote_peered_address_spaces` to control which IP address ranges are accessible through the peering, and also configures the reverse peering with its own address space specifications. ```hcl terraform { required_version = ">= 1.9, < 2.0" required_providers { azurerm = { source = "hashicorp/azurerm" version = "~> 4.0" } random = { source = "hashicorp/random" version = "~> 3.5" } } } provider "azurerm" { features { resource_group { prevent_deletion_if_contains_resources = false } } } # This ensures we have unique CAF compliant names for our resources. module "naming" { source = "Azure/naming/azurerm" version = "0.4.2" } # This is required for resource modules resource "azurerm_resource_group" "this" { location = local.selected_region name = module.naming.resource_group.name_unique } #Defining the first virtual network (vnet-1) with its subnets and settings. module "vnet1" { source = "../../" location = azurerm_resource_group.this.location parent_id = azurerm_resource_group.this.id address_space = ["10.4.0.0/16", "10.5.0.0/16"] name = "${module.naming.virtual_network.name_unique}-1" subnets = { subnet1 = { name = "${module.naming.subnet.name_unique}-1-1" address_prefixes = ["10.4.1.0/24", "10.4.2.0/24"] } subnet2 = { name = "${module.naming.subnet.name_unique}-1-2" address_prefixes = ["10.4.3.0/24", "10.4.4.0/24"] } subnet3 = { name = "${module.naming.subnet.name_unique}-1-3" address_prefixes = ["10.5.5.0/24", "10.5.6.0/24"] } } } module "vnet2" { source = "../../" location = azurerm_resource_group.this.location parent_id = azurerm_resource_group.this.id address_space = ["10.6.0.0/16", "10.7.0.0/16"] name = "${module.naming.virtual_network.name_unique}-2" peerings = { peertovnet1 = { name = "${module.naming.virtual_network_peering.name_unique}-vnet2-to-vnet1" remote_virtual_network_resource_id = module.vnet1.resource_id allow_forwarded_traffic = true allow_gateway_transit = true allow_virtual_network_access = true peer_complete_vnets = false local_peered_address_spaces = [ { address_prefix = "10.6.1.0/24" }, { address_prefix = "10.6.2.0/24" } ] remote_peered_address_spaces = [ { address_prefix = "10.4.1.0/24" }, { address_prefix = "10.4.2.0/24" } ] create_reverse_peering = true reverse_name = "${module.naming.virtual_network_peering.name_unique}-vnet1-to-vnet2" reverse_allow_forwarded_traffic = false reverse_allow_gateway_transit = false reverse_allow_virtual_network_access = true reverse_peer_complete_vnets = false reverse_local_peered_address_spaces = [ { address_prefix = "10.4.1.0/24" }, { address_prefix = "10.4.2.0/24" } ] reverse_remote_peered_address_spaces = [ { address_prefix = "10.6.1.0/24" }, { address_prefix = "10.6.2.0/24" } ] } } subnets = { subnet1 = { name = "${module.naming.subnet.name_unique}-2-1" address_prefixes = ["10.6.1.0/24", "10.6.2.0/24"] } subnet2 = { name = "${module.naming.subnet.name_unique}-2-2" address_prefixes = ["10.6.3.0/24", "10.6.4.0/24"] } subnet3 = { name = "${module.naming.subnet.name_unique}-2-3" address_prefixes = ["10.7.5.0/24", "10.7.6.0/24"] } } } ``` -------------------------------- ### Configure Storage Account Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/complete/README.md Sets up an Azure Storage Account with ZRS replication and Standard tier. It disables public nested item access and shared access keys for enhanced security. ```terraform resource "azurerm_storage_account" "this" { account_replication_type = "ZRS" account_tier = "Standard" location = azurerm_resource_group.this.location name = module.naming.storage_account.name_unique resource_group_name = azurerm_resource_group.this.name allow_nested_items_to_be_public = false shared_access_key_enabled = false } ``` -------------------------------- ### Naming Module for Resource Management Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/complete/README.md Integrates the Azure naming module to ensure CAF compliant and unique names for all created Azure resources. ```hcl # This ensures we have unique CAF compliant names for our resources. module "naming" { source = "Azure/naming/azurerm" version = "0.4.2" } ``` -------------------------------- ### Naming Module and Resource Group Creation Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/ipam_vnet_only/README.md Utilizes the Azure naming module for generating unique resource group names and then creates the resource group in the selected region. ```hcl module "naming" { source = "Azure/naming/azurerm" version = "0.4.2" } resource "azurerm_resource_group" "this" { location = local.selected_region.name name = module.naming.resource_group.name_unique } ``` -------------------------------- ### Virtual Network Module Configuration Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/new_security_rule/README.md Configures a virtual network using a local module. It defines the address space and creates multiple subnets, each with a unique name and IP address prefix, and associates the previously defined Network Security Group with each subnet. ```hcl locals { address_space = "10.0.0.0/16" subnets = { for i in range(3) : "subnet${i}" => { name = "${module.naming.subnet.name_unique}${i}" address_prefixes = [cidrsubnet(local.address_space, 8, i)] network_security_group = { id = azurerm_network_security_group.ssh.id } } } } #Creating a virtual network with specified configurations, subnets, and associated Network Security Groups. module "vnet" { source = "../../" location = azurerm_resource_group.this.location parent_id = azurerm_resource_group.this.id address_space = ["10.0.0.0/16"] name = module.naming.virtual_network.name_unique subnets = local.subnets } ``` -------------------------------- ### Terraform Configuration and Providers Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/ipam_vnet_only/README.md Sets up the Terraform configuration, including required versions for Terraform and providers like azapi, azurerm, and random. Configures the azurerm provider to allow resource group deletion. ```hcl terraform { required_version = ">= 1.9.2" required_providers { azapi = { source = "Azure/azapi" version = "~> 2.4" } azurerm = { source = "hashicorp/azurerm" version = "~> 4.0" } random = { source = "hashicorp/random" version = "~> 3.5" } } } provider "azurerm" { features { resource_group { prevent_deletion_if_contains_resources = false } } } ``` -------------------------------- ### Virtual Network with IPAM Subnets for Retry Test Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/ipam_basic/README.md This snippet configures a virtual network module to test IPAM retry logic by defining multiple subnets that simultaneously request IP address allocations from IPAM pools. Ensure the 'azapi' provider is configured. ```terraform module "vnet_retry_test" { source = "../../" location = azurerm_resource_group.this.location parent_id = azurerm_resource_group.this.id enable_telemetry = true # VNet gets address space from IPAM pool ipam_pools = [{ id = azapi_resource.ipam_pool.id number_of_ip_addresses = "256" }] name = "${module.naming.virtual_network.name_unique}-retry-test" # Multiple IPAM subnets - this should test the retry logic subnets = { # All these will try to allocate simultaneously subnet1 = { name = "subnet1-retry-test" ipam_pools = [{ pool_id = azapi_resource.ipam_pool.id number_of_ip_addresses = "64" }] } subnet2 = { name = "subnet2-retry-test" ipam_pools = [{ pool_id = azapi_resource.ipam_pool.id number_of_ip_addresses = "64" }] } subnet3 = { name = "subnet3-retry-test" ipam_pools = [{ pool_id = azapi_resource.ipam_pool.id number_of_ip_addresses = "32" }] } subnet4 = { name = "subnet4-retry-test" ipam_pools = [{ pool_id = azapi_resource.ipam_pool.id number_of_ip_addresses = "32" }] } } } ``` -------------------------------- ### Using Pessimistic Version Constraints for Providers in Terraform Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/AGENTS.md For Terraform providers used with AVM modules, it's recommended to use pessimistic version constraints to ensure compatibility. ```terraform version = "~> 1.0" ``` -------------------------------- ### DNS Servers Configuration Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/README.md Specifies a list of IP addresses for custom DNS servers to be used by the virtual network. ```hcl object({ dns_servers = list(string) }) ``` -------------------------------- ### IPAM Pool Configuration for Virtual Networks Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/README.md Specifies IPAM settings for requesting an address space from an IP Pool. Supports IPv4 and IPv6 pools with optional number of IP addresses or prefix length. ```hcl list(object({ id = string number_of_ip_addresses = optional(string) prefix_length = optional(number) })) ``` -------------------------------- ### Create Subnet on Pre-existing Virtual Network Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/_header.md Use this snippet to add a subnet to an existing virtual network. Ensure the parent VNet exists before applying this configuration. ```terraform module "avm-res-network-subnet" { source = "Azure/avm-res-network-virtualnetwork/azurerm//modules/subnet" parent_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNetworks/myVNet" name = "subnet1" address_prefixes = ["10.0.0.0/24"] } ``` -------------------------------- ### Terraform Configuration for Azure Virtual Network Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/default/README.md This configuration sets up the necessary Terraform providers and modules to create an Azure Virtual Network with default settings. It includes provider configurations for Azure and random, and utilizes the naming module for resource naming. ```hcl terraform { required_version = ">= 1.9, < 2.0" required_providers { azurerm = { source = "hashicorp/azurerm" version = "~> 4.0" } random = { source = "hashicorp/random" version = "~> 3.5" } } } provider "azurerm" { features { resource_group { prevent_deletion_if_contains_resources = false } } } # This ensures we have unique CAF compliant names for our resources. module "naming" { source = "Azure/naming/azurerm" version = "0.4.2" } # This is required for resource modules resource "azurerm_resource_group" "this" { location = local.selected_region name = module.naming.resource_group.name_unique } # Creating a virtual network with a unique name, telemetry settings, and in the specified resource group and location. module "vnet" { source = "../../" location = azurerm_resource_group.this.location parent_id = azurerm_resource_group.this.id address_space = ["10.0.0.0/16"] enable_telemetry = true name = module.naming.virtual_network.name } ``` -------------------------------- ### Retry Configuration Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/modules/subnet/README.md Defines retry settings for resource operations, including IPAM-specific error patterns. Includes a list of error message regexes, interval in seconds, and maximum interval in seconds. ```hcl object({ error_message_regex = optional(list(string), [ "AnotherOperationInProgress", "ReferencedResourceNotProvisioned", "OperationNotAllowed", "NetcfgSubnetRangesOverlap", "BadRequest.*overlap", "Conflict.*subnet.*range", "subnet.*address.*conflict" ]) interval_seconds = optional(number, 15) max_interval_seconds = optional(number, 300) }) ``` -------------------------------- ### Create Azure Network Manager for IPAM Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/ipam_vnet_only/README.md Provisions an Azure Network Manager instance within a resource group, configured to manage IPAM scopes for subscriptions. Includes retry logic for common transient errors. ```hcl resource "azapi_resource" "network_manager" { location = azurerm_resource_group.this.location name = replace(module.naming.resource_group.name_unique, module.naming.resource_group.slug, "avnm") parent_id = azurerm_resource_group.this.id type = "Microsoft.Network/networkManagers@2024-07-01" body = { properties = { networkManagerScopeAccesses = [] networkManagerScopes = { subscriptions = [data.azurerm_subscription.this.id] } } } retry = { interval_seconds = 10 max_interval_seconds = 180 error_message_regex = ["CannotDeleteResource", "Cannot delete resource while nested resources exist"] } schema_validation_enabled = false } ``` -------------------------------- ### Route Table Creation Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/complete/README.md Creates an Azure Route Table with a unique name in the specified location and associates it with the resource group. ```hcl #Creating a Route Table with a unique name in the specified location. resource "azurerm_route_table" "this" { location = azurerm_resource_group.this.location name = module.naming.route_table.name_unique resource_group_name = azurerm_resource_group.this.name } ``` -------------------------------- ### Terraform Configuration for Virtual Network with Service Endpoints Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/service_endpoints_with_locations/README.md This Terraform configuration sets up a virtual network with subnets, defining service endpoints with specific location requirements for idempotency. It includes provider configurations and resource definitions for a resource group and the virtual network itself. ```hcl terraform { required_version = ">= 1.9, < 2.0" required_providers { azurerm = { source = "hashicorp/azurerm" version = "~> 4.0" } random = { source = "hashicorp/random" version = "~> 3.5" } } } provider "azurerm" { features { resource_group { prevent_deletion_if_contains_resources = false } } } ## Section to provide a random suffix for the resource names # This allows us to randomize the names of the resources resource "random_string" "this" { length = 6 numeric = true special = false upper = false } ## Section to create a resource group for the virtual network # This creates a resource group in the specified location resource "azurerm_resource_group" "this" { location = local.selected_region.name name = "rg-avm-vnet-service-endpoints-${random_string.this.result}" } # This is the module call # Do not specify location here as the PIN data will be used to determine the deployment region module "virtualnetwork" { source = "../../" location = azurerm_resource_group.this.location parent_id = azurerm_resource_group.this.id address_space = ["10.0.0.0/16"] name = "vnet-avm-service-endpoints-${random_string.this.result}" subnets = { # Subnet with service endpoints for all regions subnet_all_endpoints = { name = "subnet-all-regions" address_prefix = "10.0.0.0/24" # New format: allow all regions with "*" service_endpoints_with_location = [ { service = "Microsoft.Storage" locations = [local.selected_region.name, local.selected_region.paired_region_name] }, { service = "Microsoft.Sql" locations = [local.selected_region.name] }, { service = "Microsoft.AzureCosmosDB" locations = ["*"] }, { service = "Microsoft.KeyVault" locations = ["*"] }, { service = "Microsoft.ServiceBus" locations = ["*"] }, { service = "Microsoft.EventHub" locations = ["*"] }, { service = "Microsoft.Web" locations = ["*"] }, { service = "Microsoft.CognitiveServices" locations = ["*"] } # Container registry is in preview and not available in all regions # { # service = "Microsoft.ContainerRegistry" # locations = ["*"] # }, ] } subnet_storage_global = { name = "subnet-storage-global" address_prefix = "10.0.1.0/24" service_endpoints_with_location = [ { service = "Microsoft.Storage.Global" locations = ["*"] }, ] } } } ``` -------------------------------- ### VNet IPAM Configuration - Static Subnets Source: https://github.com/azure/terraform-azurerm-avm-res-network-virtualnetwork/blob/main/examples/ipam_vnet_only/_header.md Define subnets with static IP address ranges when the exact address is known. Ensure the static address prefixes fall within the VNet's IPAM-allocated space. ```hcl subnets = { management = { name = "subnet-management" address_prefixes = ["172.16.255.240/28"] } } ```