main.tf (186 lines of code) (raw):
########################################################
#
# Local Variables definition
#
#######################################################
locals {
environment_suffix = var.environment == "prod" ? "prd" : "nprd"
region_source = replace(var.source_location, " ", "-")
region_target = replace(var.target_location, " ", "-")
}
locals {
vault_name_template = "vault-${var.vault_name}-${local.environment_suffix}-${random_string.unique_suffix.result}"
site_recovery_fabric_name_source = "srfab-${local.region_source}-${local.environment_suffix}"
site_recovery_fabric_name_target = "srfab-${local.region_target}-${local.environment_suffix}"
protection_container_name_source = "pc-src-${random_string.unique_suffix.result}"
protection_container_name_target = "pc-tgt-${random_string.unique_suffix.result}"
replication_policy_name = "rp-${local.environment_suffix}-${random_string.unique_suffix.result}"
protection_container_mapping_name = "pcm-${local.environment_suffix}-${random_string.unique_suffix.result}"
capacity_reservation_group_name = "${var.replicated_vm_name}-crg-${local.environment_suffix}-${random_string.unique_suffix.result}"
capacity_reservation_name = "${local.capacity_reservation_group_name}-reservation"
replicated_vm_name = "${var.replicated_vm_name}-${local.environment_suffix}-${random_string.unique_suffix.result}"
}
locals {
network_mapping_names = { for vm_name in keys(var.replicated_vms) : vm_name => "${vm_name}-network-mapping" }
}
########################################################
#
# Data sources
#
#######################################################
data "azurerm_subscription" "current" {}
data "azurerm_recovery_services_vault" "existing_vault" {
count = var.use_existing_vault ? 1 : 0
name = var.vault_name
resource_group_name = var.vault_resource_group_name
provider = azurerm.target
}
resource "random_string" "unique_suffix" {
length = 8
numeric = true
special = false
upper = false
}
########################################################
#
# Recovery Infrastructure
#
#######################################################
resource "azurerm_recovery_services_vault" "vault" {
count = var.use_existing_vault ? 0 : 1
name = local.vault_name_template
location = var.target_location
resource_group_name = var.target_resource_group_name
sku = "Standard"
tags = var.tags
provider = azurerm.target
}
resource "azurerm_site_recovery_fabric" "source" {
name = local.site_recovery_fabric_name_source
resource_group_name = var.target_resource_group_name
recovery_vault_name = var.use_existing_vault ? data.azurerm_recovery_services_vault.existing_vault[0].name : azurerm_recovery_services_vault.vault[0].name
location = var.source_location
provider = azurerm.target
}
resource "azurerm_site_recovery_fabric" "target" {
name = local.site_recovery_fabric_name_target
resource_group_name = var.target_resource_group_name
recovery_vault_name = var.use_existing_vault ? data.azurerm_recovery_services_vault.existing_vault[0].name : azurerm_recovery_services_vault.vault[0].name
location = var.target_location
provider = azurerm.target
}
resource "azurerm_site_recovery_protection_container" "source" {
name = local.protection_container_name_source
resource_group_name = var.target_resource_group_name
recovery_vault_name = var.use_existing_vault ? data.azurerm_recovery_services_vault.existing_vault[0].name : azurerm_recovery_services_vault.vault[0].name
recovery_fabric_name = azurerm_site_recovery_fabric.source.name
provider = azurerm.target
}
resource "azurerm_site_recovery_protection_container" "target" {
name = local.protection_container_name_target
resource_group_name = var.target_resource_group_name
recovery_vault_name = var.use_existing_vault ? data.azurerm_recovery_services_vault.existing_vault[0].name : azurerm_recovery_services_vault.vault[0].name
recovery_fabric_name = azurerm_site_recovery_fabric.target.name
provider = azurerm.target
}
resource "azurerm_site_recovery_replication_policy" "policy" {
name = local.replication_policy_name
resource_group_name = var.target_resource_group_name
recovery_vault_name = var.use_existing_vault ? data.azurerm_recovery_services_vault.existing_vault[0].name : azurerm_recovery_services_vault.vault[0].name
recovery_point_retention_in_minutes = var.recovery_point_retention_in_minutes
application_consistent_snapshot_frequency_in_minutes = var.application_consistent_snapshot_frequency_in_minutes
provider = azurerm.target
}
resource "azurerm_site_recovery_protection_container_mapping" "mapping" {
name = local.protection_container_mapping_name
resource_group_name = var.target_resource_group_name
recovery_vault_name = var.use_existing_vault ? data.azurerm_recovery_services_vault.existing_vault[0].name : azurerm_recovery_services_vault.vault[0].name
recovery_fabric_name = azurerm_site_recovery_fabric.source.name
recovery_source_protection_container_name = azurerm_site_recovery_protection_container.source.name
recovery_target_protection_container_id = azurerm_site_recovery_protection_container.target.id
recovery_replication_policy_id = azurerm_site_recovery_replication_policy.policy.id
provider = azurerm.target
}
resource "random_string" "storage_account_name" {
length = 16
special = false
upper = false
numeric = true
lower = true
}
resource "azurerm_storage_account" "staging" {
name = "sa${random_string.storage_account_name.result}${local.environment_suffix}"
resource_group_name = var.target_resource_group_name
location = var.source_location
account_tier = "Standard"
account_replication_type = var.staging_replication_type
provider = azurerm.target
}
resource "azurerm_site_recovery_network_mapping" "network_mapping" {
# Only create network mapping if the source and target locations are different
count = var.source_location != var.target_location ? length(local.network_mapping_names) : 0
name = local.network_mapping_names[count.index]
resource_group_name = azurerm_recovery_services_vault.vault[0].resource_group_name
recovery_vault_name = azurerm_recovery_services_vault.vault[0].name
source_recovery_fabric_name = azurerm_site_recovery_fabric.source.name
target_recovery_fabric_name = azurerm_site_recovery_fabric.target.name
source_network_id = var.replicated_vms[local.network_mapping_names[count.index]].source_network_id
target_network_id = var.replicated_vms[local.network_mapping_names[count.index]].target_network_id
provider = azurerm.target
}
########################################################
#
# Capacity Reservation
#
#######################################################
resource "azurerm_capacity_reservation_group" "shared_cr_group" {
count = var.create_capacity_reservation_group == true ? 1 : 0
name = local.capacity_reservation_group_name
location = var.target_location
resource_group_name = var.target_resource_group_name
provider = azurerm.target
tags = var.tags
}
resource "azurerm_capacity_reservation" "per_vm" {
for_each = { for vm in var.replicated_vms : vm.key => vm.vm_id if vm.create_capacity_reservation == true }
name = "${each.key}-capacity-reservation-${local.environment_suffix}-${random_string.unique_suffix.result}"
capacity_reservation_group_id = var.existing_capacity_reservation_group_id != "" ? var.existing_capacity_reservation_group_id : azurerm_capacity_reservation_group.shared_cr_group[0].id
sku {
name = each.value.capacity_reservation_sku
capacity = 1
}
tags = var.tags
provider = azurerm.target
}
########################################################
#
# Replicated VM
#
#######################################################
resource "azurerm_site_recovery_replicated_vm" "replicated_vm" {
for_each = var.replicated_vms
name = "${each.key}-${local.environment_suffix}-${random_string.unique_suffix.result}"
resource_group_name = azurerm_recovery_services_vault.vault[0].resource_group_name
recovery_vault_name = var.use_existing_vault ? data.azurerm_recovery_services_vault.existing_vault[0].name : azurerm_recovery_services_vault.vault[0].name
source_recovery_fabric_name = azurerm_site_recovery_fabric.source.name
source_vm_id = each.value.vm_id
recovery_replication_policy_id = azurerm_site_recovery_replication_policy.policy.id
target_resource_group_id = each.value.target_resource_group_id
target_recovery_fabric_id = azurerm_site_recovery_fabric.target.id
target_recovery_protection_container_id = azurerm_site_recovery_protection_container.target.id
source_recovery_protection_container_name = azurerm_site_recovery_protection_container.source.name
target_capacity_reservation_group_id = each.value.create_capacity_reservation == true ? azurerm_capacity_reservation.per_vm[each.key].capacity_reservation_group_id : null
target_availability_set_id = each.value.target_availability_set_id
target_zone = each.value.target_zone
target_edge_zone = each.value.target_edge_zone
target_network_id = each.value.target_network_id
target_proximity_placement_group_id = each.value.target_proximity_placement_group_id
target_boot_diagnostic_storage_account_id = each.value.target_boot_diagnostic_storage_account_id
target_virtual_machine_scale_set_id = each.value.target_virtual_machine_scale_set_id
test_network_id = each.value.test_network_id
multi_vm_group_name = each.value.multi_vm_group_name
dynamic "managed_disk" {
for_each = { for disk in each.value.managed_disks : disk.disk_id => disk }
content {
disk_id = managed_disk.value.disk_id
staging_storage_account_id = azurerm_storage_account.staging.id
target_resource_group_id = each.value.target_resource_group_id
target_disk_type = managed_disk.value.disk_type
target_replica_disk_type = managed_disk.value.replica_disk_type
target_disk_encryption_set_id = managed_disk.value.target_disk_encryption_set_id
}
}
dynamic "network_interface" {
for_each = { for nic in each.value.network_interfaces : nic.network_interface_id => nic }
content {
source_network_interface_id = network_interface.value.network_interface_id
target_subnet_name = network_interface.value.target_subnet_name
target_static_ip = network_interface.value.target_static_ip
recovery_public_ip_address_id = network_interface.value.recovery_public_ip_address_id
failover_test_static_ip = network_interface.value.failover_test_static_ip
failover_test_subnet_name = network_interface.value.failover_test_subnet_name
failover_test_public_ip_address_id = network_interface.value.failover_test_public_ip_address_id
}
}
provider = azurerm.target
depends_on = [azurerm_site_recovery_network_mapping.network_mapping]
timeouts {
create = "5h30m"
update = "2h"
delete = "20m"
}
}