feat(infra): auto-commit con 56 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user