infra/diagram/main.py
Viktor Barzin c8de2c4803 [ci skip] Sunset Drone CI: remove all artifacts, DNS, configs, and references
Drone CI has been fully replaced by Woodpecker CI at ci.viktorbarzin.me.
Destroys K8s resources (12), removes DNS records, NFS exports, Uptime Kuma
monitor, dashboard entry, and all code/doc references across 18 files.
2026-02-23 19:38:55 +00:00

212 lines
8 KiB
Python

from unicodedata import name
from diagrams import Diagram, Cluster, Edge, Node
from diagrams.generic.compute import Rack
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.k8s.network import Service, Ingress
from diagrams.k8s.compute import Pod
from diagrams.aws.network import ELB
from diagrams.onprem.network import Nginx, Pfsense
from diagrams.generic.network import Firewall, Router, Switch, VPN
from diagrams.generic.storage import Storage
from diagrams.generic.os import Windows, Raspbian, IOS
from diagrams.generic.device import Mobile
from diagrams.onprem.client import Client, Users
from diagrams.aws.iot import IotCamera, IotAnalyticsChannel
from kubernetes import client, config
vpn_clients: dict[str, Node] = {}
# namespaces_to_visualize = {
# "website", "vaultwarden", "uptime", "technitium", "reverse-proxy",
# "oauth2", "monitoring", "mailserver", "kms", "immich", "headscale",
# "frigate", "f1-stream", "excalidraw", "dashy", "calibre", "audiobookshelf"
# }
namespaces_to_not_visualize = {
"ytdlp", "wireguard", "webhook-handler", "url", "travel-blog", "registry",
"redis", "openid-help-page", "localai", "kubernetes-dashboard",
"headscale", "hackmd", "finance-app", "dbaas", "crowdsec",
"cloudflared", "city-guesser"
}
# docs for lib - https://diagrams.mingrammer.com/docs/nodes/k8s
def border_router(
name: str,
include_vpn_client: bool = False,
) -> tuple[Firewall, Router]:
with Cluster(name):
tp_link_fw = Firewall()
tp_link_router = Router()
tp_link_fw >> tp_link_router
if include_vpn_client:
vpn_client = VPN(f"{name} Tailscale Client")
vpn_clients[name] = vpn_client
return tp_link_fw, tp_link_router
def sofia():
with Cluster("Sofia"):
_, tp_link_router = border_router("Border Router")
ext_switch = Switch('Extension Switch')
tp_link_router >> ext_switch
with Cluster('R730'):
with Cluster("Pfsense"):
pfsense = Pfsense('Firewall')
vpn_client = VPN("Pfsense Tailscale Client")
vpn_clients["pfsense"] = vpn_client
with Cluster('Kubernetes Network'):
k8s_switch = Switch()
config.load_kube_config()
v1 = client.CoreV1Api()
network_api = client.NetworkingV1Api()
for namespace in v1.list_namespace(watch=False).items:
namespace_name = namespace.metadata.name
# if namespace_name not in namespaces_to_visualize:
# continue
if namespace_name in namespaces_to_not_visualize:
continue
with Cluster(namespace_name):
for ingress in network_api.list_namespaced_ingress(
namespace_name).items:
# for k8s_svc in v1.list_namespaced_service(
# namespace_name).items:
ingress = Ingress(ingress.spec.rules[0].host)
# service = Service(k8s_svc.metadata.name)
# k8s_switch >> service
k8s_switch >> ingress
pfsense >> k8s_switch
with Cluster('Management Network'):
mgt_switch = Switch()
# Truenas
truenas = Storage("Truenas")
# pxe server
pxe_server = Rack("PXE Server")
# HA
home_assistant = Rack("Home Assistant")
with Cluster("Devvm"):
devvm = Rack("Devvm")
devvm_vpn_client = VPN("Tailscale Client")
vpn_clients["devvm"] = devvm_vpn_client
mgt_switch >> truenas
mgt_switch >> pxe_server
mgt_switch >> home_assistant
mgt_switch >> devvm
pfsense >> mgt_switch
windows10 = Windows("Windows 10 Server")
tp_link_router >> windows10
ext_switch >> pfsense
nas = Storage('Synology NAS')
tp_link_router >> nas
def london():
with Cluster("London"):
_, openwrt = border_router("London OpenWRT", include_vpn_client=True)
rpi = Raspbian()
# client = Mobile()
# ios_client = IOS()
ip_cam = IotCamera("IP Camera")
users = Users()
openwrt >> rpi
# openwrt >> client
# openwrt >> ios_client
openwrt >> users
rpi >> Edge() << ip_cam
def valchedrym():
with Cluster("Valchedrym"):
_, openwrt = border_router("Valchedrym OpenWRT",
include_vpn_client=True)
users = Users()
ip_cam = IotCamera("Surveillance System")
alarm_system = IotAnalyticsChannel("Alarm System")
openwrt >> users
openwrt >> ip_cam
openwrt >> alarm_system
def mladost3():
with Cluster("Mladost 3"):
_, tp_link = border_router("Mladost 3 Router ")
laptop = Windows()
tp_link >> laptop
def outer_infra():
with Diagram("Home Infra", show=False, outformat="png", direction="LR"):
sofia()
london()
valchedrym()
mladost3()
with Cluster("Mobile VPN Clients"):
mobile_vpn_clients = VPN()
vpn_clients["mobile vpn users"] = mobile_vpn_clients
mobile_vpn_users = Users("headscale.viktorbarzin.me/manager")
mobile_vpn_clients >> mobile_vpn_users
# link all vpn clients
existing_links = set()
for vpn_client in vpn_clients.values():
for other_vpn_client in vpn_clients.values():
if other_vpn_client == vpn_client:
continue
key = vpn_client.label + other_vpn_client.label
reverse_key = other_vpn_client.label + vpn_client.label
if key in existing_links or reverse_key in existing_links:
continue
vpn_client >> Edge(color="darkgreen") << other_vpn_client
existing_links.add(key)
def k8s_network():
with Diagram("Kubernetes Network",
show=False,
outformat="png",
direction="LR"):
with Cluster("Kubernetes Network"):
k8s_switch = Switch()
config.load_kube_config()
v1 = client.CoreV1Api()
network_api = client.NetworkingV1Api()
for namespace in v1.list_namespace(watch=False).items:
namespace_name = namespace.metadata.name
# if namespace_name not in namespaces_to_visualize:
# continue
if namespace_name in namespaces_to_not_visualize or namespace_name == "monitoring":
continue
with Cluster(namespace_name):
for ingress in network_api.list_namespaced_ingress(
namespace_name).items:
ing = Ingress(ingress.spec.rules[0].host)
rule = ingress.spec.rules[0]
# for rule in ingress.spec.rules:
path = rule.http.paths[0]
# for path in rule.http.paths:
k8s_svc = path.backend.service
svc = Service(f"{k8s_svc.name}:{k8s_svc.port.number}")
ing >> svc
pods = v1.list_namespaced_pod(namespace_name)
for k8s_pod in pods.items:
if k8s_pod.status.phase != "Running":
continue
pod = Pod(k8s_pod.metadata.name)
svc >> pod
# service = Service(k8s_svc.metadata.name)
# k8s_switch >> service
k8s_switch >> ing
if __name__ == '__main__':
outer_infra()
k8s_network()