Add visualization script
This commit is contained in:
parent
13b69d5d4b
commit
dc398ddb6e
4 changed files with 137 additions and 0 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -10,3 +10,5 @@ secrets.auto.tfvars
|
||||||
inventory/group_vars/all/serguzim.net.yml
|
inventory/group_vars/all/serguzim.net.yml
|
||||||
inventory/group_vars/all/opentofu.yml
|
inventory/group_vars/all/opentofu.yml
|
||||||
inventory/group_vars/all/all_services.yml
|
inventory/group_vars/all/all_services.yml
|
||||||
|
|
||||||
|
infrastructure.svg
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -52,3 +52,10 @@ all:
|
||||||
$(MAKE) dns
|
$(MAKE) dns
|
||||||
@printf "\n=====\n\n"
|
@printf "\n=====\n\n"
|
||||||
ansible-playbook ./playbooks/serguzim.net.yml -t $(TAGS)
|
ansible-playbook ./playbooks/serguzim.net.yml -t $(TAGS)
|
||||||
|
|
||||||
|
visualize:
|
||||||
|
tofu output --json \
|
||||||
|
| jq 'with_entries(.value |= .value)' \
|
||||||
|
| ./visualize.py \
|
||||||
|
| d2 - infrastructure.svg
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ mkShell {
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
ansible
|
ansible
|
||||||
ansible-lint
|
ansible-lint
|
||||||
|
d2
|
||||||
dnscontrol
|
dnscontrol
|
||||||
opentofu
|
opentofu
|
||||||
];
|
];
|
||||||
|
|
127
visualize.py
Executable file
127
visualize.py
Executable file
|
@ -0,0 +1,127 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
icon_overrides = {
|
||||||
|
"acme_dns": "lets-encrypt",
|
||||||
|
"extra_services": None,
|
||||||
|
"faas": None,
|
||||||
|
"forgejo_runner": "forgejo",
|
||||||
|
"healthcheck": "healthchecks",
|
||||||
|
"mailcowdockerized": "mailcow",
|
||||||
|
"reitanlage_oranienburg": "grav",
|
||||||
|
"tandoor": "tandoor-recipes",
|
||||||
|
"teamspeak_fallback": None,
|
||||||
|
"tinytinyrss": "tiny-tiny-rss",
|
||||||
|
"wiki_js": "wiki-js",
|
||||||
|
"woodpecker": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
template_host = """
|
||||||
|
'serguzim.net'.{host}: {{
|
||||||
|
label: {host}
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
|
||||||
|
template_service = """
|
||||||
|
{key}: {{
|
||||||
|
label: {label}
|
||||||
|
label.near: top-left
|
||||||
|
icon: https://cdn.jsdelivr.net/gh/selfhst/icons/webp/{icon}.webp
|
||||||
|
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 service_key(svc, data):
|
||||||
|
return f"'serguzim.net'.{data['host']}.{svc}"
|
||||||
|
|
||||||
|
def service_key_find(svc_name, services):
|
||||||
|
for svc, data in services.items():
|
||||||
|
if svc == svc_name:
|
||||||
|
return service_key(svc, data)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def parse_hosts(hosts):
|
||||||
|
result = []
|
||||||
|
for host in hosts.keys():
|
||||||
|
result.append(template_host.format(host=host))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def parse_services(services):
|
||||||
|
result = []
|
||||||
|
|
||||||
|
postgresql_key = service_key_find("postgresql", 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():
|
||||||
|
svc_key = service_key(svc, data)
|
||||||
|
|
||||||
|
domains = []
|
||||||
|
if data.get("dns"):
|
||||||
|
domains = []
|
||||||
|
for dns in data["dns"]:
|
||||||
|
domain = ""
|
||||||
|
if dns.get("target") != "@":
|
||||||
|
domain += f"{dns["target"]}."
|
||||||
|
domain += dns['domain']
|
||||||
|
domains.append(f"- {domain}")
|
||||||
|
|
||||||
|
result.append(template_service.format(
|
||||||
|
key=svc_key,
|
||||||
|
label="\\n".join([svc] + domains),
|
||||||
|
icon=icon_overrides.get(svc, svc) or "docker",
|
||||||
|
))
|
||||||
|
|
||||||
|
for backup in data.get("backup") or []:
|
||||||
|
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
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
hosts = []
|
||||||
|
services = []
|
||||||
|
|
||||||
|
data = json.loads(sys.stdin.read())
|
||||||
|
|
||||||
|
hosts = parse_hosts(data["hosts"])
|
||||||
|
services = parse_services(data["services"])
|
||||||
|
|
||||||
|
print("\n".join(
|
||||||
|
[default_d2]
|
||||||
|
+ hosts
|
||||||
|
+ services))
|
Loading…
Reference in a new issue