**Approach (brief)**Provide a single reusable module that accepts two "sides" (side_a, side_b) describing desired cloud type ("aws" or "azure"), network parameters, and relies on provider aliasing passed from the root module via the module "providers" map. Inside the module, create provider-specific resources conditionally (count = 0/1) to avoid duplication. Export network ids and peering/connection details.**Module: variables.tf**hcl
variable "side_a" {
type = object({
provider = string # "aws" or "azure"
name = string
cidr = string
})
}
variable "side_b" {
type = object({
provider = string
name = string
cidr = string
})
}
variable "tags" {
type = map(string)
default = {}
}
**Module: main.tf (resource skeleton with comments)**hcl
# AWS VPC (created only when side.provider == "aws")
resource "aws_vpc" "side_a" {
count = var.side_a.provider == "aws" ? 1 : 0
cidr_block = var.side_a.cidr
tags = merge(var.tags, { Name = var.side_a.name })
# provider used is the aws provider passed into module via providers map
}
resource "aws_vpc" "side_b" {
count = var.side_b.provider == "aws" ? 1 : 0
cidr_block = var.side_b.cidr
tags = merge(var.tags, { Name = var.side_b.name })
}
# Azure Virtual Network (created only when provider == "azure")
resource "azurerm_virtual_network" "side_a" {
count = var.side_a.provider == "azure" ? 1 : 0
name = var.side_a.name
address_space = [var.side_a.cidr]
location = "placeholder-location"
resource_group_name = "placeholder-rg"
tags = var.tags
}
resource "azurerm_virtual_network" "side_b" {
count = var.side_b.provider == "azure" ? 1 : 0
name = var.side_b.name
address_space = [var.side_b.cidr]
location = "placeholder-location"
resource_group_name = "placeholder-rg"
tags = var.tags
}
# Cross-cloud peering: example patterns (high-level wrappers)
# For AWS->Azure use Transit Gateway / Virtual Network Gateway (not fully implemented here)
# Use null_resource or cloud-specific resources to wire the two sides: conditional blocks show intent
resource "null_resource" "peering_placeholder" {
# create only when both sides exist
count = (var.side_a.provider != var.side_b.provider) ? 1 : 0
triggers = {
side_a = jsonencode(var.side_a)
side_b = jsonencode(var.side_b)
}
# In real implementation: call aws_dx_gateway_attachment / azurerm_virtual_network_peering equivalents
}
**Module: outputs.tf**hcl
output "side_a_network_id" {
value = coalesce(
try(aws_vpc.side_a[0].id, null),
try(azurerm_virtual_network.side_a[0].id, null)
)
}
output "side_b_network_id" {
value = coalesce(
try(aws_vpc.side_b[0].id, null),
try(azurerm_virtual_network.side_b[0].id, null)
)
}
output "peering_placeholder_id" {
value = try(null_resource.peering_placeholder[0].id, "")
}
**Provider aliasing strategy (root module)**- Configure each cloud provider with aliases in root.- Pass provider instances into module via the module "providers" map so module resources use those concrete providers without hardcoding regions/accounts.**Root example (root main.tf)**hcl
provider "aws" {
alias = "acct1"
region = "us-west-2"
# creds...
}
provider "aws" {
alias = "acct2"
region = "us-east-1"
}
provider "azurerm" {
alias = "east"
features = {}
subscription_id = "sub-xxxxx"
}
module "multicloud_net" {
source = "./modules/vnet-peering"
# pass provider instances so resources inside module use them
providers = {
aws = aws.acct1 # module aws references will use this provider
azurerm = azurerm.east # module azurerm references will use this provider
}
side_a = {
provider = "aws"
name = "vpc-a"
cidr = "10.0.0.0/16"
}
side_b = {
provider = "azure"
name = "vnet-b"
cidr = "10.1.0.0/16"
}
tags = { Owner = "network-team" }
}
**Why this design**- Single module handles both clouds via conditional creation—avoids duplicating logic per provider.- Root controls provider aliasing and passes concrete provider instances to the module, enabling multi-account/region setups.- Keeps module cloud-agnostic surface (sides objects) so higher-level orchestration can instantiate many pairings.