python - ¿Es posible almacenar la cadena de conexión de alambique fuera de alembic.ini?
alembic python (5)
Estoy usando Alambique con SQL Alchemy. Con SQL Alchemy, tiendo a seguir un patrón donde no almaceno la cadena de conexión con el código versionado. En cambio, tengo el archivo secret.py
que contiene información confidencial. .gitignore
este nombre de archivo en mi .gitignore
para que no termine en GitHub.
Este patrón funciona bien, pero ahora estoy usando Alembic para migraciones. Parece que no puedo ocultar la cadena de conexión. En cambio, en alembic.ini, coloca la cadena de conexión como un parámetro de configuración :
# the ''revision'' command, regardless of autogenerate
# revision_environment = false
sqlalchemy.url = driver://user:pass@localhost/dbname
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembi
Me temo que voy a cometer accidentalmente un archivo con información de nombre de usuario / contraseña para mi base de datos. Prefiero almacenar esta cadena de conexión en un solo lugar y evitar el riesgo de comprometerla accidentalmente con el control de la versión.
¿Que opciones tengo?
Entonces, lo que parece funcionar es la reimplementación de la creación del motor en env.py, que aparentemente es un lugar para hacer este tipo de personalización. En lugar de usar la cadena sqlalchemy connect en el ini:
engine = engine_from_config(
config.get_section(config.config_ini_section),
prefix=''sqlalchemy.'',
poolclass=pool.NullPool)
Puede reemplazar y especificar su propia configuración de motor:
import store
engine = store.engine
De hecho, los documentos parecen implicar que esto está bien:
sqlalchemy.url: una URL para conectarse a la base de datos a través de SQLAlchemy. De hecho, esta clave solo se referencia en el archivo env.py que es específico de la configuración "genérica"; un archivo que puede ser personalizado por el desarrollador. Una configuración de base de datos múltiple puede responder a varias claves aquí, o puede hacer referencia a otras secciones del archivo.
Otra solución es crear una plantilla de archivo alembic.ini.dist y rastrearla con su código versionado, ignorando a alembic.ini en su VCS.
No agregue ninguna información confidencial en alembic.ini.dist:
sqlalchemy.url = ...
Al implementar su código en una plataforma, copie alembic.ini.dist a alembic.ini (este no será rastreado por su VCS) y modifique alembic.ini con las credenciales de la plataforma.
Ayer tuve el mismo problema y encontré una solución para trabajar. Hago lo siguiente en env.py
:
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config
# this will overwrite the ini-file sqlalchemy.url path
# with the path given in the config of the main code
import config as ems_config
config.set_main_option(''sqlalchemy.url'', ems_config.config.get(''sql'', ''database''))
ems_config
es un módulo externo que contiene mis datos de configuración.
config.set_main_option(...)
esencialmente sobrescribe la clave sqlalchemy.url
en la sección [alembic]
del archivo alembic.ini
. En mi configuración simplemente lo dejo negro.
La documentación de Alembic sugiere el uso de create_engine
con la URL de la base de datos (en lugar de modificar sqlalchemy.url en el código ).
También debe modificar run_migrations_offline para usar la nueva URL. Allan Simon tiene un ejemplo en su blog, pero en resumen, modifique env.py para:
Proporcione una función compartida para obtener la URL de alguna manera (aquí viene de la línea de comando):
def get_url(): url = context.get_x_argument(as_dictionary=True).get(''url'') assert url, "Database URL must be specified on command line with -x url=<DB_URL>" return url
Use la URL en modo fuera de línea:
def run_migrations_offline(): ... url = get_url() context.configure( url=url, target_metadata=target_metadata, literal_binds=True) ...
Use la URL en el modo en línea usando
create_engine
lugar deengine_from_config
:def run_migrations_online(): ... connectable = create_engine(get_url()) with connectable.connect() as connection: ...
Como Doug T. dijo , puede editar env.py para proporcionar URL desde otro lugar que no sea el archivo ini. En lugar de crear un motor nuevo, puede pasar un argumento url
adicional a la función engine_from_config (los kwargs se fusionan más tarde con opciones tomadas del archivo ini). En ese caso, podría, por ejemplo, almacenar la contraseña cifrada en un archivo ini y descifrarla en tiempo de ejecución mediante frase de contraseña almacenada en la variable ENV.
connectable = engine_from_config(
config.get_section(config.config_ini_section),
prefix=''sqlalchemy.'',
poolclass=pool.NullPool,
url=some_decrypted_endpoint)