J'utilise Alembic avec SQL Alchemy. Avec SQL Alchemy, j'ai tendance à suivre un schéma selon lequel je ne stocke pas la chaîne de connexion avec le code versionné. Au lieu de cela, j'ai le fichier secret.py
qui contient des informations confidentielles. Je jette ce nom de fichier dans mon .gitignore
pour qu'il ne finisse pas sur GitHub.
Ce modèle fonctionne bien, mais je commence maintenant à utiliser Alembic pour les migrations. Il semble que je ne peux pas cacher la chaîne de connexion. Dans alembic.ini, placez plutôt la chaîne de connexion en tant que paramètre de configuration :
# the 'revision' command, regardless of autogenerate
# revision_environment = false
sqlalchemy.url = driver://user:pass@localhost/dbname
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembi
Je crains de valider accidentellement un fichier contenant les informations de nom d'utilisateur/mot de passe pour ma base de données. Je préférerais stocker cette chaîne de connexion à un seul endroit et éviter le risque de la commettre accidentellement au contrôle de version.
Quelles sont mes options?
J'ai eu le même problème hier et j'ai trouvé la solution suivante qui fonctionne: Je procède comme suit dans alembic/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
est un module externe qui contient mes données de configuration.
config.set_main_option(...)
écrase essentiellement la clé sqlalchemy.url
dans la section [alembic]
du fichier alembic.ini
. Dans ma configuration, je le laisse simplement noir.
La documentation Alembic suggère d'utiliser create_engine
avec l'URL de la base de données (au lieu de de modifier sqlalchemy.url dans le code ).
Vous devez également modifier run_migrations_offline pour utiliser la nouvelle URL. Allan Simon a un exemple sur son blog, mais en résumé, modifiez env.py pour:
Fournissez une fonction partagée pour obtenir l’URL d’une manière ou d’une autre (ici elle provient de la ligne de commande):
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
Utilisez l'URL en mode hors connexion:
def run_migrations_offline():
...
url = get_url()
context.configure(
url=url, target_metadata=target_metadata, literal_binds=True)
...
Utilisez l'URL en mode en ligne en utilisant create_engine
au lieu de engine_from_config
:
def run_migrations_online():
...
connectable = create_engine(get_url())
with connectable.connect() as connection:
...
Donc, ce qui semble fonctionner, c’est la réimplémentation de la création de moteur dans env.py, qui est apparemment un endroit approprié pour effectuer ce type de personnalisation. Au lieu d’utiliser la chaîne sqlalchemy connect dans l’ini:
engine = engine_from_config(
config.get_section(config.config_ini_section),
prefix='sqlalchemy.',
poolclass=pool.NullPool)
Vous pouvez remplacer et spécifier votre propre configuration de moteur:
import store
engine = store.engine
En effet, les docs semblent impliquer c’est ok:
sqlalchemy.url - Une URL permettant de se connecter à la base de données via SQLAlchemy. Cette clé n'est en fait référencée que dans le fichier env.py spécifique à la configuration «générique»; un fichier qui peut être personnalisé par le développeur. Une configuration multiple de base de données peut ici répondre à plusieurs clés ou faire référence à d'autres sections du fichier.
Je cherchais depuis un moment comment gérer cela pour plusieurs bases de données
Voici ce que j'ai fait. J'ai deux bases de données: logs et ohlc
D'après le doc , J'ai configuré l'alambic comme ça
alembic init --template multidb
databases = logs, ohlc
[logs]
sqlalchemy.url = postgresql://botcrypto:botcrypto@localhost/logs
[ohlc]
sqlalchemy.url = postgresql://botcrypto:botcrypto@localhost/ohlc
[...]
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config
# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)
logger = logging.getLogger('alembic.env')
# overwrite alembic.ini db urls from the config file
settings_path = os.environ.get('SETTINGS')
if settings_path:
with open(settings_path) as fd:
settings = conf.load(fd, context=os.environ) # loads the config.yml
config.set_section_option("ohlc", "sqlalchemy.url", settings["databases"]["ohlc"])
config.set_section_option("logs", "sqlalchemy.url", settings["databases"]["logs"])
else:
logger.warning('Environment variable SETTINGS missing - use default alembic.ini configuration')
[...]
databases:
logs: postgresql://botcrypto:[email protected]:5432/logs
ohlc: postgresql://botcrypto:[email protected]:5432/ohlc
usage
SETTINGS=config.yml alembic upgrade head
J'espère que ça peut aider!
Comme Doug T. l'a dit vous pouvez éditer env.py pour fournir une URL depuis un fichier autre que le fichier ini. Au lieu de créer un nouveau moteur, vous pouvez passer un argument url
supplémentaire à la fonction engine_from_config
(les kwargs sont ensuite fusionnés avec des options extraites du fichier ini). Dans ce cas, vous pourriez par exemple stocker le mot de passe crypté dans un fichier ini et le décrypter au moment de l'exécution à l'aide de la phrase secrète stockée dans la variable ENV.
connectable = engine_from_config(
config.get_section(config.config_ini_section),
prefix='sqlalchemy.',
poolclass=pool.NullPool,
url=some_decrypted_endpoint)
Une autre solution consiste à créer un modèle de fichier alembic.ini.dist et à le suivre à l'aide de votre code mis à jour, tout en ignorant alembic.ini dans votre VCS.
N'ajoutez aucune information confidentielle dans alembic.ini.dist:
sqlalchemy.url = ...
Lorsque vous déployez votre code sur une plate-forme, copiez alembic.ini.dist dans alembic.ini (celui-ci ne sera pas suivi par votre VCS) et modifiez alembic.ini avec les informations d'identification de la plate-forme.