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,140 @@
|
||||
"""Tests para discover_local_services."""
|
||||
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
|
||||
import yaml
|
||||
|
||||
# El modulo hoja se importa por su nombre directo; aseguramos que su directorio
|
||||
# esta en sys.path para poder correr el test desde cualquier cwd.
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from discover_local_services import discover_local_services
|
||||
|
||||
NORMALIZED_KEYS = {
|
||||
"name", "subdomain", "port", "health_path", "title", "icon", "category",
|
||||
"rewrite_host", "up",
|
||||
}
|
||||
|
||||
|
||||
def _write_manifest(tmp_path, services):
|
||||
manifest = {
|
||||
"dashboard_subdomain": "home",
|
||||
"glance_port": 8585,
|
||||
"services": services,
|
||||
}
|
||||
path = tmp_path / "local_services.yaml"
|
||||
path.write_text(yaml.safe_dump(manifest), encoding="utf-8")
|
||||
return str(path)
|
||||
|
||||
|
||||
def test_golden_service_up_with_all_keys(tmp_path):
|
||||
# Abrimos un socket real en un puerto efímero para simular un servicio vivo.
|
||||
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
listener.bind(("127.0.0.1", 0))
|
||||
listener.listen(1)
|
||||
port = listener.getsockname()[1]
|
||||
try:
|
||||
manifest = _write_manifest(tmp_path, [
|
||||
{
|
||||
"name": "metabase",
|
||||
"subdomain": "metabase",
|
||||
"port": port,
|
||||
"health_path": "/api/health",
|
||||
"title": "Metabase",
|
||||
"icon": "si:metabase",
|
||||
"category": "Datos",
|
||||
},
|
||||
])
|
||||
result = discover_local_services(manifest, include_registry=False)
|
||||
assert len(result) == 1
|
||||
svc = result[0]
|
||||
# Todas las claves normalizadas presentes.
|
||||
assert set(svc.keys()) == NORMALIZED_KEYS
|
||||
assert svc["up"] is True
|
||||
assert svc["name"] == "metabase"
|
||||
assert svc["port"] == port
|
||||
assert svc["health_path"] == "/api/health"
|
||||
finally:
|
||||
listener.close()
|
||||
|
||||
|
||||
def test_edge_closed_port_is_down(tmp_path):
|
||||
# Tomamos un puerto efímero y lo cerramos inmediatamente -> debe estar down.
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.bind(("127.0.0.1", 0))
|
||||
closed_port = s.getsockname()[1]
|
||||
s.close()
|
||||
|
||||
manifest = _write_manifest(tmp_path, [
|
||||
{
|
||||
"name": "ghost",
|
||||
"subdomain": "ghost",
|
||||
"port": closed_port,
|
||||
"health_path": "/",
|
||||
"title": "Ghost",
|
||||
"icon": "",
|
||||
"category": "Otros",
|
||||
},
|
||||
])
|
||||
result = discover_local_services(manifest, include_registry=False)
|
||||
assert len(result) == 1
|
||||
assert result[0]["up"] is False
|
||||
|
||||
|
||||
def test_defaults_derived_for_missing_fields(tmp_path):
|
||||
# Servicio mínimo: solo name + port. El resto debe derivarse con defaults.
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.bind(("127.0.0.1", 0))
|
||||
closed_port = s.getsockname()[1]
|
||||
s.close()
|
||||
|
||||
manifest = _write_manifest(tmp_path, [
|
||||
{"name": "barebones", "port": closed_port},
|
||||
])
|
||||
result = discover_local_services(manifest, include_registry=False)
|
||||
svc = result[0]
|
||||
assert set(svc.keys()) == NORMALIZED_KEYS
|
||||
assert svc["title"] == "barebones" # derivado de name
|
||||
assert svc["icon"] == "" # default
|
||||
assert svc["category"] == "Otros" # default
|
||||
assert svc["health_path"] == "/" # default
|
||||
assert svc["subdomain"] == "barebones" # derivado de name
|
||||
assert svc["up"] is False
|
||||
|
||||
|
||||
def test_empty_manifest_returns_empty_list(tmp_path):
|
||||
manifest = _write_manifest(tmp_path, [])
|
||||
result = discover_local_services(manifest, include_registry=False)
|
||||
assert result == []
|
||||
|
||||
|
||||
def test_rewrite_host_passthrough_desde_manifiesto(tmp_path):
|
||||
# Un servicio con rewrite_host: true en el manifiesto debe propagar
|
||||
# rewrite_host == True; uno sin la clave debe dar rewrite_host == False.
|
||||
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
listener.bind(("127.0.0.1", 0))
|
||||
listener.listen(1)
|
||||
port = listener.getsockname()[1]
|
||||
try:
|
||||
manifest = _write_manifest(tmp_path, [
|
||||
{
|
||||
"name": "jupyter",
|
||||
"subdomain": "jupyter",
|
||||
"port": port,
|
||||
"rewrite_host": True,
|
||||
},
|
||||
{
|
||||
"name": "metabase",
|
||||
"subdomain": "metabase",
|
||||
"port": port,
|
||||
# sin clave rewrite_host -> default False
|
||||
},
|
||||
])
|
||||
result = discover_local_services(manifest, include_registry=False)
|
||||
by_name = {s["name"]: s for s in result}
|
||||
assert by_name["jupyter"]["rewrite_host"] is True
|
||||
assert by_name["metabase"]["rewrite_host"] is False
|
||||
finally:
|
||||
listener.close()
|
||||
Reference in New Issue
Block a user