#!/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": 'EventHub', "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": 'DevOps', "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": 'AppGW', "color": "#0078D4", "bg": "#E8F4FD", "category": "Network", "azure_icon_key": "application_gateways" }, "iot_hub": { "icon_svg": 'IoTHub', "color": "#0078D4", "bg": "#E8F4FD", "category": "IoT", "azure_icon_key": "iot_hub" }, "stream_analytics": { "icon_svg": 'StreamAnalytics', "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": 'FrontDoor', "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": 'Firewall', "color": "#E8A000", "bg": "#FFF8E1", "category": "Network", "azure_icon_key": "firewalls" }, "document_intelligence": { "icon_svg": 'DocIntel', "color": "#0078D4", "bg": "#E8F4FD", "category": "AI", "azure_icon_key": "form_recognizer" }, "form_recognizer": { "icon_svg": 'DocIntel', "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": 'CosmosDB', "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": 'Synapse', "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}

{title}

Azure Architecture · {generated_at}
{svc_count} Services
{pe_count} Private Endpoints
{len(connections)} Connections
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)