#!/usr/bin/env python3
"""
Azure Interactive Architecture Diagram Generator v3
Generates interactive HTML diagrams with Azure official icons (Base64 inline).
"""
import json
from datetime import datetime
from icons import get_icon_data_uri
_HAS_OFFICIAL_ICONS = True
# Azure service icons: SVG, colors + official icon key mapping
# icon: 48x48 viewBox SVG path (fallback)
# azure_icon_key: key in icons.py (official Azure icon)
SERVICE_ICONS = {
"openai": {
"icon_svg": 'AI ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "AI",
"azure_icon_key": "azure_openai"
},
"ai_foundry": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "AI",
"azure_icon_key": "ai_foundry"
},
"ai_hub": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "AI",
"azure_icon_key": "machine_learning"
},
"search": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "AI",
"azure_icon_key": "cognitive_search"
},
"ai_search": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "AI",
"azure_icon_key": "cognitive_search"
},
"aml": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "AI",
"azure_icon_key": "machine_learning"
},
"storage": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "storage_accounts"
},
"adls": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "data_lake_storage_gen1"
},
"fabric": {
"icon_svg": 'F ',
"color": "#E8740C", "bg": "#FEF3E8", "category": "Data",
"azure_icon_key": "microsoft_fabric"
},
"synapse": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "azure_synapse_analytics"
},
"adf": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "data_factory"
},
"data_factory": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "data_factory"
},
"keyvault": {
"icon_svg": ' ',
"color": "#E8A000", "bg": "#FEF7E0", "category": "Security",
"azure_icon_key": "key_vaults"
},
"kv": {
"icon_svg": ' ',
"color": "#E8A000", "bg": "#FEF7E0", "category": "Security",
"azure_icon_key": "key_vaults"
},
"vnet": {
"icon_svg": ' ',
"color": "#5C2D91", "bg": "#F3EEF9", "category": "Network",
"azure_icon_key": "virtual_networks"
},
"pe": {
"icon_svg": ' ',
"color": "#5C2D91", "bg": "#F3EEF9", "category": "Network",
"azure_icon_key": "private_endpoints"
},
"nsg": {
"icon_svg": ' ',
"color": "#5C2D91", "bg": "#F3EEF9", "category": "Network",
"azure_icon_key": "network_security_groups"
},
"acr": {
"icon_svg": 'ACR ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Compute"
},
"aks": {
"icon_svg": 'K ',
"color": "#326CE5", "bg": "#EBF0FC", "category": "Compute",
"azure_icon_key": "kubernetes_services"
},
"appservice": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Compute",
"azure_icon_key": "app_services"
},
"appinsights": {
"icon_svg": ' ',
"color": "#773ADC", "bg": "#F0EAFA", "category": "Monitor",
"azure_icon_key": "application_insights"
},
"monitor": {
"icon_svg": ' ',
"color": "#773ADC", "bg": "#F0EAFA", "category": "Monitor",
"azure_icon_key": "monitor"
},
"vm": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Compute",
"azure_icon_key": "virtual_machine"
},
"bastion": {
"icon_svg": ' ',
"color": "#5C2D91", "bg": "#F3EEF9", "category": "Network",
"azure_icon_key": "bastions"
},
"jumpbox": {
"icon_svg": 'JB ',
"color": "#5C2D91", "bg": "#F3EEF9", "category": "Network",
"azure_icon_key": "virtual_machine"
},
"vpn": {
"icon_svg": ' ',
"color": "#5C2D91", "bg": "#F3EEF9", "category": "Network",
"azure_icon_key": "virtual_network_gateways"
},
"user": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "External"
},
"app": {
"icon_svg": ' ',
"color": "#666666", "bg": "#F5F5F5", "category": "External"
},
"default": {
"icon_svg": '? ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Azure"
},
"cdn": {
"icon_svg": 'CDN ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Network",
"azure_icon_key": "cdn_profiles"
},
"event_hub": {
"icon_svg": 'Event Hub ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Integration",
"azure_icon_key": "event_hubs"
},
"redis": {
"icon_svg": 'Redis ',
"color": "#D83B01", "bg": "#FEF0E8", "category": "Data",
"azure_icon_key": "cache_redis"
},
"devops": {
"icon_svg": 'Dev Ops ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "DevOps",
"azure_icon_key": "azure_devops"
},
"acr": {
"icon_svg": 'ACR ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Compute",
"azure_icon_key": "container_registries"
},
"container_registry": {
"icon_svg": 'ACR ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Compute",
"azure_icon_key": "container_registries"
},
"app_gateway": {
"icon_svg": 'App GW ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Network",
"azure_icon_key": "application_gateways"
},
"iot_hub": {
"icon_svg": 'IoT Hub ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "IoT",
"azure_icon_key": "iot_hub"
},
"stream_analytics": {
"icon_svg": 'Stream Analytics ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "stream_analytics_jobs"
},
"vpn_gateway": {
"icon_svg": ' ',
"color": "#5C2D91", "bg": "#F3EEF9", "category": "Network",
"azure_icon_key": "virtual_network_gateways"
},
"front_door": {
"icon_svg": 'Front Door ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Network",
"azure_icon_key": "front_door_and_cdn_profiles"
},
"ai_hub": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "AI",
"azure_icon_key": "ai_studio"
},
"firewall": {
"icon_svg": 'Fire wall ',
"color": "#E8A000", "bg": "#FFF8E1", "category": "Network",
"azure_icon_key": "firewalls"
},
"document_intelligence": {
"icon_svg": 'Doc Intel ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "AI",
"azure_icon_key": "form_recognizer"
},
"form_recognizer": {
"icon_svg": 'Doc Intel ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "AI",
"azure_icon_key": "form_recognizer"
},
"databricks": {
"icon_svg": 'DB ',
"color": "#FF3621", "bg": "#FFF0EE", "category": "Data",
"azure_icon_key": "azure_databricks"
},
"sql_server": {
"icon_svg": 'SQL ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "sql_server"
},
"sql_database": {
"icon_svg": 'SQL ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "sql_database"
},
"cosmos_db": {
"icon_svg": 'Cosmos DB ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "azure_cosmos_db"
},
"app_service": {
"icon_svg": 'App ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Compute",
"azure_icon_key": "app_services"
},
"aks": {
"icon_svg": 'K8s ',
"color": "#326CE5", "bg": "#EBF0FA", "category": "Compute",
"azure_icon_key": "kubernetes_services"
},
"function_app": {
"icon_svg": 'ƒ ',
"color": "#F0AD4E", "bg": "#FFF8ED", "category": "Compute",
"azure_icon_key": "function_apps"
},
"synapse": {
"icon_svg": 'Syn apse ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "azure_synapse_analytics"
},
"log_analytics": {
"icon_svg": 'Log ',
"color": "#5C2D91", "bg": "#F3EDF7", "category": "Monitoring",
"azure_icon_key": "log_analytics_workspaces"
},
"app_insights": {
"icon_svg": 'AI ',
"color": "#5C2D91", "bg": "#F3EDF7", "category": "Monitoring",
"azure_icon_key": "application_insights"
},
"nsg": {
"icon_svg": 'NSG ',
"color": "#E8A000", "bg": "#FFF8E1", "category": "Network",
"azure_icon_key": "network_security_groups"
},
"apim": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Integration",
"azure_icon_key": "api_management_services"
},
"api_management": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Integration",
"azure_icon_key": "api_management_services"
},
"service_bus": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Integration",
"azure_icon_key": "azure_service_bus"
},
"logic_apps": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Integration",
"azure_icon_key": "logic_apps"
},
"logic_app": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Integration",
"azure_icon_key": "logic_apps"
},
"event_grid": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Integration",
"azure_icon_key": "event_grid_topics"
},
"container_apps": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Compute",
"azure_icon_key": "container_apps_environments"
},
"container_app": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Compute",
"azure_icon_key": "container_apps_environments"
},
"postgresql": {
"icon_svg": 'PG ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "azure_database_postgresql_server"
},
"mysql": {
"icon_svg": 'My ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "azure_database_mysql_server"
},
"load_balancer": {
"icon_svg": ' ',
"color": "#5C2D91", "bg": "#F3EEF9", "category": "Network",
"azure_icon_key": "load_balancers"
},
"nat_gateway": {
"icon_svg": 'NAT ',
"color": "#5C2D91", "bg": "#F3EEF9", "category": "Network",
"azure_icon_key": "nat"
},
"expressroute": {
"icon_svg": ' ',
"color": "#5C2D91", "bg": "#F3EEF9", "category": "Network",
"azure_icon_key": "expressroute_circuits"
},
"sentinel": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Security",
"azure_icon_key": "azure_sentinel"
},
"data_explorer": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "azure_data_explorer_clusters"
},
"kusto": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Data",
"azure_icon_key": "azure_data_explorer_clusters"
},
"signalr": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Integration",
"azure_icon_key": "signalr"
},
"notification_hub": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Integration",
"azure_icon_key": "notification_hubs"
},
"spring_apps": {
"icon_svg": '🌱 ',
"color": "#6DB33F", "bg": "#EFF8E8", "category": "Compute",
"azure_icon_key": "azure_spring_apps"
},
"static_web_app": {
"icon_svg": 'SWA ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Compute",
"azure_icon_key": "static_apps"
},
"digital_twins": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "IoT",
"azure_icon_key": "digital_twins"
},
"backup": {
"icon_svg": ' ',
"color": "#0078D4", "bg": "#E8F4FD", "category": "Management",
"azure_icon_key": "backup_vault"
},
}
CONNECTION_STYLES = {
"api": {"color": "#0078D4", "dash": "0"},
"data": {"color": "#0F9D58", "dash": "0"},
"security": {"color": "#E8A000", "dash": "5,5"},
"private": {"color": "#5C2D91", "dash": "3,3"},
"network": {"color": "#5C2D91", "dash": "5,5"},
"default": {"color": "#999999", "dash": "0"},
}
_TYPE_ALIASES = {
# Azure ARM resource names → canonical diagram type
# Network
"private_endpoints": "pe", "private_endpoint": "pe",
"virtual_networks": "vnet", "virtual_network": "vnet",
"network_security_groups": "nsg", "network_security_group": "nsg",
"bastion_hosts": "bastion", "bastion_host": "bastion",
"application_gateways": "app_gateway", "application_gateway": "app_gateway",
"front_doors": "front_door", "front_door_and_cdn_profiles": "front_door",
"virtual_network_gateways": "vpn", "vpn_gateways": "vpn",
"load_balancers": "load_balancer",
"nat_gateways": "nat_gateway",
"expressroute_circuits": "expressroute",
"firewalls": "firewall",
"cdn_profiles": "cdn",
# Data
"data_factories": "adf", "data_factory": "adf",
"storage_accounts": "storage", "storage_account": "storage",
"data_lake": "adls", "adls_gen2": "adls", "data_lake_storage": "adls",
"fabric_capacities": "fabric", "fabric_capacity": "fabric", "microsoft_fabric": "fabric",
"synapse_workspaces": "synapse", "synapse_workspace": "synapse", "synapse_analytics": "synapse",
"cosmos": "cosmos_db", "cosmosdb": "cosmos_db", "documentdb": "cosmos_db",
"sql_databases": "sql_database", "sql_db": "sql_database",
"sql_servers": "sql_server",
"redis_caches": "redis", "redis_cache": "redis", "cache_redis": "redis",
"stream_analytics_jobs": "stream_analytics",
"databricks_workspaces": "databricks",
"data_explorer_clusters": "data_explorer", "azure_data_explorer": "data_explorer",
"postgresql_server": "postgresql", "postgresql_servers": "postgresql",
"mysql_server": "mysql", "mysql_servers": "mysql",
# AI
"cognitive_services": "ai_foundry", "ai_services": "ai_foundry", "foundry": "ai_foundry",
"azure_openai": "openai",
"cognitive_search": "search", "search_services": "search", "search_service": "search",
"machine_learning": "aml", "ml": "aml", "machine_learning_workspaces": "aml",
"form_recognizers": "document_intelligence",
"ai_studio": "ai_hub", "foundry_project": "ai_hub",
# Security
"key_vault": "keyvault", "key_vaults": "keyvault",
"sentinel": "sentinel", "azure_sentinel": "sentinel",
# Compute
"virtual_machines": "vm", "virtual_machine": "vm",
"app_services": "appservice", "web_apps": "appservice", "web_app": "appservice",
"function_apps": "function_app", "functions": "function_app",
"kubernetes_services": "aks", "managed_clusters": "aks", "kubernetes": "aks",
"container_registries": "acr",
"container_apps_environments": "container_apps",
"spring_apps": "spring_apps", "azure_spring_apps": "spring_apps",
"static_apps": "static_web_app", "static_web_apps": "static_web_app",
# Integration
"event_hubs": "event_hub",
"event_grid_topics": "event_grid", "event_grid_domains": "event_grid",
"api_management_services": "apim",
"service_bus_namespaces": "service_bus",
"logic_app": "logic_apps",
"notification_hubs": "notification_hub",
# Monitoring
"log_analytics_workspaces": "log_analytics",
"application_insights": "appinsights", "app_insight": "appinsights",
# IoT
"iot_hubs": "iot_hub",
# Management
"backup_vaults": "backup", "backup_vault": "backup",
}
def get_service_info(svc_type: str) -> dict:
t = svc_type.lower().replace("-", "_").replace(" ", "_")
t = _TYPE_ALIASES.get(t, t)
info = SERVICE_ICONS.get(t, SERVICE_ICONS["default"]).copy()
# Add official Azure icon data URI if available
azure_key = info.get("azure_icon_key", t)
icon_uri = get_icon_data_uri(azure_key)
info["icon_data_uri"] = icon_uri
return info
def generate_html(services: list, connections: list, title: str, vnet_info: str = "", hierarchy: list = None) -> str:
def _norm(t):
t = t.lower().replace("-", "_").replace(" ", "_")
return _TYPE_ALIASES.get(t, t)
nodes_js = json.dumps([{
"id": svc["id"],
"name": svc["name"],
"type": _norm(svc.get("type", "default")),
"sku": svc.get("sku", ""),
"private": svc.get("private", False),
"details": svc.get("details", []),
"subscription": svc.get("subscription", ""),
"resourceGroup": svc.get("resourceGroup", ""),
"icon_svg": get_service_info(svc.get("type", "default"))["icon_svg"],
"icon_data_uri": get_service_info(svc.get("type", "default")).get("icon_data_uri", ""),
"color": get_service_info(svc.get("type", "default"))["color"],
"bg": get_service_info(svc.get("type", "default"))["bg"],
"category": get_service_info(svc.get("type", "default"))["category"],
} for svc in services], ensure_ascii=False)
hierarchy_js = json.dumps(hierarchy or [], ensure_ascii=False)
edges_js = json.dumps([{
"from": conn["from"],
"to": conn["to"],
"label": conn.get("label", ""),
"type": conn.get("type", "default"),
"color": CONNECTION_STYLES.get(conn.get("type", "default"), CONNECTION_STYLES["default"])["color"],
"dash": CONNECTION_STYLES.get(conn.get("type", "default"), CONNECTION_STYLES["default"])["dash"],
} for conn in connections], ensure_ascii=False)
pe_count = sum(1 for s in services if _norm(s.get("type", "default")) == "pe")
svc_count = len(services) - pe_count
generated_at = datetime.now().strftime("%Y-%m-%d %H:%M")
vnet_info_js = json.dumps(vnet_info, ensure_ascii=False)
html = f"""
{title}
100%
Drag nodes · Scroll to zoom · Drag empty space to pan
"""
return html
def generate_diagram(services, connections, title="Azure Architecture", vnet_info="", hierarchy=None):
"""Generate an interactive Azure architecture diagram as an HTML string.
Args:
services: list of dicts with keys id, name, type, sku, private, details, etc.
connections: list of dicts with keys from, to, label, type.
title: diagram title string.
vnet_info: VNet CIDR info string.
hierarchy: optional subscription/RG hierarchy list.
Returns:
HTML string containing the interactive diagram.
"""
return generate_html(services, connections, title, vnet_info=vnet_info, hierarchy=hierarchy)