Refactor visualize.py to use jinja2

This commit is contained in:
Tobias Reisinger 2024-10-14 22:11:20 +02:00
parent 73a1b21cad
commit 20bb2c8fd7
Signed by: serguzim
GPG key ID: 13AD60C237A28DFE
3 changed files with 114 additions and 73 deletions

View file

@ -6,5 +6,6 @@ mkShell {
d2 d2
dnscontrol dnscontrol
opentofu opentofu
python3Packages.jinja2
]; ];
} }

View file

@ -0,0 +1,77 @@
vars: {
d2-config: {
layout-engine: elk
theme-id: 101
}
}
external: {
scaleway: {
s3
}
restic: {
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/restic.webp
}
}
{% for host in hosts %}
{{ host.key }}: {
}
{% endfor %}{# host #}
{% for svc in svcs %}
{{ svc.key }}: {
label: {{ svc.label }}
label.near: top-left
icon: {{ svc.icon }}
icon.near: top-right
}
{% for backup in svc.backup or [] %}
{{ svc.key }} -> external.restic.{{ svc.host }}: backup.name {
style: {
stroke: "#0f0"
stroke-dash: 3
}
}
{% endfor %}{# backup #}
{% if svc.monitoring %}
{{ monitoring_key }} -> {{ svc.key }}: {
style.stroke: "#1E9025"
}
{% endif %}
{% if svc.database %}
{{ svc.key }} -> {{ db_key }}: {
style.stroke: "#336791"
}
{{ db_key }}.{{ svc.name }}
{% endif %}
{% if svc.auth %}
{{ svc.key }} -> {{ auth_key }}: {
style.stroke: "#FD4B2D"
}
{{ auth_key }}.{{ svc.name }}
{% endif %}
{% if svc.s3 %}
{{ svc.key }} -> external.scaleway.s3: {
style: {
stroke: "#110B1E"
stroke-dash: 3
}
}
external.scaleway.s3.{{ svc.name }}
{% endif %}
{% endfor %}{# svc #}
{% for svc in grid_svcs %}
{{ svc }}: {
grid-columns: 3
grid-gap: 0
}
{% endfor %}

View file

@ -3,6 +3,8 @@
import json import json
import sys import sys
import jinja2
icon_overrides = { icon_overrides = {
"acme_dns": "lets-encrypt", "acme_dns": "lets-encrypt",
"extra_services": None, "extra_services": None,
@ -24,41 +26,6 @@ icon_format = {
"tiny-tiny-rss": "webp", "tiny-tiny-rss": "webp",
} }
template_host = """
'serguzim.net'.{host}: {{
label: {host}
}}
"""
template_service = """
{key}: {{
label: {label}
label.near: top-left
icon: {icon}
icon.near: top-right
}}
"""
default_d2 = """
vars: {
d2-config: {
layout-engine: elk
# Terminal theme code
theme-id: 101
}
}
external: {
scaleway: {
s3
}
restic: {
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/restic.webp
}
}
"""
def get_icon(svc): def get_icon(svc):
svc = icon_overrides.get(svc, svc) or 'docker' svc = icon_overrides.get(svc, svc) or 'docker'
fmt = icon_format.get(svc, 'svg') fmt = icon_format.get(svc, 'svg')
@ -66,6 +33,9 @@ def get_icon(svc):
def service_key(svc, data): def service_key(svc, data):
return f"'serguzim.net'.{data['host']}.{svc}" return f"'serguzim.net'.{data['host']}.{svc}"
def host_key(host):
return f"'serguzim.net'.{host}"
def service_key_find(svc_name, services): def service_key_find(svc_name, services):
for svc, data in services.items(): for svc, data in services.items():
@ -75,8 +45,11 @@ def service_key_find(svc_name, services):
def parse_hosts(hosts): def parse_hosts(hosts):
result = [] result = []
for host in hosts.keys(): for host, data in hosts.items():
result.append(template_host.format(host=host)) result.append({
'key': host_key(host),
'name': host,
})
return result return result
def parse_services(services): def parse_services(services):
@ -85,42 +58,23 @@ def parse_services(services):
postgresql_key = service_key_find("postgresql", services) postgresql_key = service_key_find("postgresql", services)
authentik_key = service_key_find("authentik", services) authentik_key = service_key_find("authentik", services)
result.append(f"{postgresql_key}.grid-columns: 3")
result.append(f"{postgresql_key}.grid-gap: 0")
result.append(f"{authentik_key}.grid-columns: 3")
result.append(f"{authentik_key}.grid-gap: 0")
for svc, data in services.items(): for svc, data in services.items():
svc_key = service_key(svc, data) svc_key = service_key(svc, data)
domains = [] domains = []
if data.get("dns"): for dns in data.get("dns") or []:
domains = [] domain = ""
for dns in data["dns"]: if dns.get("target") != "@":
domain = "" domain += f"{dns["target"]}."
if dns.get("target") != "@": domain += dns['domain']
domain += f"{dns["target"]}." domains.append(f"- {domain}")
domain += dns['domain']
domains.append(f"- {domain}")
result.append(template_service.format( data['key'] = svc_key
key=svc_key, data['label'] = "\\n".join([svc] + domains)
label="\\n".join([svc] + domains), data['icon'] = get_icon(svc)
icon=get_icon(svc)
))
for backup in data.get("backup") or []: result.append(data)
result.append(f'({svc_key} -> external.restic.{data['host']}).style.stroke: "#0f0"')
if data.get("database"):
result.append(f"({svc_key} -> {postgresql_key}).style.stroke: '#00f'")
result.append(f"{postgresql_key}.{svc}")
if data.get("auth"):
result.append(f"({svc_key} -> {authentik_key}).style.stroke: '#FD4B2D'")
result.append(f"{authentik_key}.{svc}")
if data.get("s3"):
result.append(f"({svc_key} -> external.scaleway.s3).style.stroke: '#bbb'")
result.append(f"external.scaleway.s3.{svc}")
return result return result
if __name__ == '__main__': if __name__ == '__main__':
@ -128,11 +82,20 @@ if __name__ == '__main__':
services = [] services = []
data = json.loads(sys.stdin.read()) data = json.loads(sys.stdin.read())
hosts = parse_hosts(data["hosts"])
services = parse_services(data["services"])
print("\n".join( db_key = service_key_find("postgresql", data["services"])
[default_d2] auth_key = service_key_find("authentik", data["services"])
+ hosts monitoring_key = service_key_find("gatus", data["services"])
+ services))
jinja_loader = jinja2.FileSystemLoader(searchpath="./templates")
jinja_env = jinja2.Environment(loader=jinja_loader)
template = jinja_env.get_template("infrastructure.d2.j2")
text = template.render(
grid_svcs=[db_key, auth_key],
svcs=parse_services(data["services"]),
hosts=parse_hosts(data["hosts"]),
db_key=db_key,
auth_key=auth_key,
monitoring_key=monitoring_key,
)
print(text)