32c7336bf6
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
111 lines
4.1 KiB
Python
111 lines
4.1 KiB
Python
"""Renderiza la configuración YAML de Glance a partir de servicios normalizados.
|
|
|
|
Glance (https://github.com/glanceapp/glance) es un dashboard self-hosted. Este
|
|
módulo transforma una lista de servicios en el YAML que Glance espera: una página
|
|
con un widget `monitor` por categoría que hace health-check de cada servicio y lo
|
|
pinta verde/rojo. Parte del sistema `local_hub`.
|
|
"""
|
|
|
|
import yaml
|
|
|
|
_HEADER = (
|
|
"# Generado por render_glance_config_py_infra — NO editar a mano. "
|
|
"Fuente: apps/local_hub/local_services.yaml\n"
|
|
)
|
|
|
|
|
|
def render_glance_config(
|
|
services: list[dict],
|
|
title: str = "Procesos locales",
|
|
host_suffix: str = "localhost",
|
|
) -> str:
|
|
"""Construye el YAML de configuración de Glance para una lista de servicios.
|
|
|
|
Función pura y determinista: agrupa los servicios por su clave ``category``,
|
|
crea un widget ``type: monitor`` por categoría (ordenadas alfabéticamente) y
|
|
dentro de cada uno un site por servicio (ordenados por ``title``). Cada site
|
|
apunta a ``http://<subdomain>.<host_suffix>`` (campo ``url``, lo que abre el
|
|
usuario al clicar). Si el servicio trae un ``health_path`` distinto de
|
|
``"/"``, el site añade además ``check-url`` = ``url + health_path``: es la
|
|
ruta que Glance usa para el health-check (muchas APIs dan 404 en ``/`` pero
|
|
200 en ``/api/health``), sin cambiar el enlace que ve el usuario.
|
|
|
|
Args:
|
|
services: lista de dicts de servicio normalizados. Cada uno debe traer al
|
|
menos ``subdomain`` (si falta, el servicio se ignora sin lanzar) y
|
|
``title``; opcionalmente ``category`` (default ``"General"``),
|
|
``icon`` (se omite del site si está vacío o ausente) y ``health_path``
|
|
(si es distinto de ``"/"``, el site emite ``check-url`` = url +
|
|
health_path; si es ``"/"`` o falta, no se emite ``check-url``).
|
|
title: nombre de la página de Glance (campo ``name`` de la página).
|
|
Default ``"Procesos locales"``.
|
|
host_suffix: sufijo de host para las URLs de los sites. Default
|
|
``"localhost"`` -> ``http://<subdomain>.localhost``.
|
|
|
|
Returns:
|
|
String con el YAML completo de Glance, terminado en ``\\n``.
|
|
"""
|
|
# Agrupa por categoría, ignorando servicios sin subdomain.
|
|
by_category: dict[str, list[dict]] = {}
|
|
for svc in services:
|
|
subdomain = svc.get("subdomain")
|
|
if not subdomain:
|
|
continue
|
|
category = svc.get("category") or "General"
|
|
by_category.setdefault(category, []).append(svc)
|
|
|
|
widgets: list[dict] = []
|
|
for category in sorted(by_category.keys()):
|
|
svcs = sorted(
|
|
by_category[category],
|
|
key=lambda s: (s.get("title") or "", s.get("subdomain") or ""),
|
|
)
|
|
sites: list[dict] = []
|
|
for svc in svcs:
|
|
url = f"http://{svc['subdomain']}.{host_suffix}"
|
|
site: dict = {
|
|
"title": svc.get("title") or svc["subdomain"],
|
|
"url": url,
|
|
}
|
|
# El health-check apunta al health_path del servicio (no a "/").
|
|
# Muchas APIs devuelven 404 en la raiz pero 200 en su ruta de salud
|
|
# (ej. /api/health), asi Glance las pinta verde correctamente. El
|
|
# campo `url` (lo que abre el usuario al clicar) sigue siendo la raiz.
|
|
health = svc.get("health_path") or "/"
|
|
if health and health != "/":
|
|
site["check-url"] = url + health
|
|
icon = svc.get("icon")
|
|
if icon:
|
|
site["icon"] = icon
|
|
sites.append(site)
|
|
widgets.append(
|
|
{
|
|
"type": "monitor",
|
|
"title": category,
|
|
"cache": "1m",
|
|
"sites": sites,
|
|
}
|
|
)
|
|
|
|
config = {
|
|
"pages": [
|
|
{
|
|
"name": title,
|
|
"columns": [
|
|
{
|
|
"size": "full",
|
|
"widgets": widgets,
|
|
}
|
|
],
|
|
}
|
|
]
|
|
}
|
|
|
|
body = yaml.safe_dump(
|
|
config,
|
|
sort_keys=False,
|
|
default_flow_style=False,
|
|
allow_unicode=True,
|
|
)
|
|
return _HEADER + body
|