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:
|
except Exception as e:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"{env_key} no es una URL de SQLAlchemy válida. "
|
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
|
) 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():
|
def get_database_url():
|
||||||
"""Obtiene la URL de la base de datos (PostgreSQL) desde variables de entorno o alembic.ini."""
|
"""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.
|
# 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():
|
if raw and raw.strip():
|
||||||
normalized = _normalize_alembic_sqlalchemy_url(raw)
|
normalized = _normalize_alembic_sqlalchemy_url(raw)
|
||||||
_validate_sqlalchemy_url(normalized, env_key)
|
_validate_sqlalchemy_url(normalized, env_key)
|
||||||
|
_reject_documentation_placeholder_host(normalized, env_key)
|
||||||
return normalized
|
return normalized
|
||||||
|
|
||||||
# Construcción desde settings (CORE_DB_* en .env / entorno)
|
# Construcción desde settings (CORE_DB_* en .env / entorno)
|
||||||
@@ -74,7 +92,9 @@ def get_database_url():
|
|||||||
encoded_user = quote_plus(user)
|
encoded_user = quote_plus(user)
|
||||||
encoded_password = quote_plus(password)
|
encoded_password = quote_plus(password)
|
||||||
encoded_db = quote_plus(db)
|
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:
|
except Exception as e:
|
||||||
logger.error(f"Error al construir URL: {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."
|
"sqlalchemy.url en alembic.ini con placeholders ${...} no está soportado."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_reject_documentation_placeholder_host(url, "alembic.ini sqlalchemy.url")
|
||||||
return 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.
|
- PostgreSQL test database available.
|
||||||
- Environment variable:
|
- 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
|
## Run commands
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user