Enhance SQLAlchemy URL validation in Alembic environment
- Added a new function to reject documentation placeholder hosts in database URLs, improving error handling for misconfigurations. - Updated the `get_database_url` function to incorporate this new validation, ensuring that users are alerted when using "host" as a placeholder. - Enhanced error messages to provide clearer guidance on valid host configurations. These changes aim to improve the robustness and clarity of database connection handling in the application.
This commit is contained in:
@@ -46,10 +46,27 @@ def _validate_sqlalchemy_url(url: str, env_key: str) -> None:
|
||||
except Exception as e:
|
||||
raise RuntimeError(
|
||||
f"{env_key} no es una URL de SQLAlchemy válida. "
|
||||
"Ejemplo: postgresql://usuario:clave@host:5432/nombre_bd"
|
||||
"Ejemplo: postgresql://usuario:clave@127.0.0.1:5432/nombre_bd"
|
||||
) from e
|
||||
|
||||
|
||||
def _reject_documentation_placeholder_host(url: str, source: str) -> None:
|
||||
"""
|
||||
Evita el error críptico de DNS: muchos ejemplos usan @host:5432 como texto literal.
|
||||
"""
|
||||
try:
|
||||
parsed = make_url(url)
|
||||
except Exception:
|
||||
return
|
||||
h = (parsed.host or "").strip().lower()
|
||||
if h == "host":
|
||||
raise RuntimeError(
|
||||
f"{source}: el hostname \"host\" es un placeholder de documentación, no un servidor real. "
|
||||
"Usa el host alcanzable desde el runner (IP, nombre DNS, servicio en docker-compose, "
|
||||
"o host.docker.internal si act corre en contenedor y Postgres en tu máquina)."
|
||||
)
|
||||
|
||||
|
||||
def get_database_url():
|
||||
"""Obtiene la URL de la base de datos (PostgreSQL) desde variables de entorno o alembic.ini."""
|
||||
# CI / pytest: misma URL que los tests (secret TEST_DATABASE_URL) o DATABASE_URL explícita.
|
||||
@@ -60,6 +77,7 @@ def get_database_url():
|
||||
if raw and raw.strip():
|
||||
normalized = _normalize_alembic_sqlalchemy_url(raw)
|
||||
_validate_sqlalchemy_url(normalized, env_key)
|
||||
_reject_documentation_placeholder_host(normalized, env_key)
|
||||
return normalized
|
||||
|
||||
# Construcción desde settings (CORE_DB_* en .env / entorno)
|
||||
@@ -74,7 +92,9 @@ def get_database_url():
|
||||
encoded_user = quote_plus(user)
|
||||
encoded_password = quote_plus(password)
|
||||
encoded_db = quote_plus(db)
|
||||
return f"postgresql+psycopg2://{encoded_user}:{encoded_password}@{host}:{port}/{encoded_db}"
|
||||
built = f"postgresql+psycopg2://{encoded_user}:{encoded_password}@{host}:{port}/{encoded_db}"
|
||||
_reject_documentation_placeholder_host(built, "CORE_DB_HOST")
|
||||
return built
|
||||
except Exception as e:
|
||||
logger.error(f"Error al construir URL: {e}")
|
||||
|
||||
@@ -87,6 +107,7 @@ def get_database_url():
|
||||
"sqlalchemy.url en alembic.ini con placeholders ${...} no está soportado."
|
||||
)
|
||||
|
||||
_reject_documentation_placeholder_host(url, "alembic.ini sqlalchemy.url")
|
||||
return url
|
||||
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ Si `TEST_DATABASE_URL` apunta a una base con datos previos, los builders reutili
|
||||
|
||||
- PostgreSQL test database available.
|
||||
- Environment variable:
|
||||
- `TEST_DATABASE_URL=postgresql://user:pass@host:5432/db_name`
|
||||
- `TEST_DATABASE_URL=postgresql://user:pass@127.0.0.1:5432/db_name` (sustituye por el host real alcanzable desde el runner; no uses el literal `host` de los ejemplos genéricos)
|
||||
|
||||
## Run commands
|
||||
|
||||
|
||||
Reference in New Issue
Block a user