Added alembic support for database migrations

Change-Id: If5923734315efcecc64127edb4abd3d6005c30ed
This commit is contained in:
Stéphane Albert 2014-08-08 14:34:38 +02:00
parent 6903c5c2fd
commit 3d16526bc7
6 changed files with 172 additions and 0 deletions

View File

View File

View File

View File

@ -0,0 +1,59 @@
# A generic, single database configuration.
[alembic]
# path to migration scripts
script_location = alembic
# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s
# max length of characters to apply to the
# "slug" field
#truncate_slug_length = 40
# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false
# set to 'true' to allow .pyc and .pyo files without
# a source .py file to be detected as revisions in the
# versions/ directory
# sourceless = false
# sqlalchemy.url = driver://user:pass@localhost/dbname
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
qualname =
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

View File

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Objectif Libre
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# @author: Stéphane Albert
#
from logging import config as log_config
from alembic import context
from cloudkitty import db
config = context.config
log_config.fileConfig(config.config_file_name)
def run_migrations_online(target_metadata, version_table):
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
:param target_metadata: Model's metadata used for autogenerate support.
:param version_table: Override the default version table for alembic.
"""
engine = db.get_engine()
with engine.connect() as connection:
context.configure(connection=connection,
target_metadata=target_metadata,
version_table=version_table)
with context.begin_transaction():
context.run_migrations()

View File

@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Objectif Libre
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# @author: Stéphane Albert
#
import os
import alembic
from alembic import config as alembic_config
ALEMBIC_INI_PATH = os.path.join(os.path.dirname(__file__), 'alembic.ini')
def load_alembic_config(repo_path, ini_path=ALEMBIC_INI_PATH):
if not os.path.exists(repo_path):
raise Exception('Repo path (%s) not found.' % repo_path)
if not os.path.exists(ini_path):
raise Exception('Ini path (%s) not found.' % ini_path)
config = alembic_config.Config(ini_path)
config.set_main_option('script_location', repo_path)
return config
def upgrade(config, version):
return alembic.command.upgrade(config, version or 'head')
def downgrade(config, version):
if isinstance(version, int) or version is None or version.isdigit():
version = 'base'
return alembic.command.downgrade(config, version)
def version(config):
return alembic.command.current(config)
def revision(config, message='', autogenerate=False):
"""Creates template for migration.
:param message: Text that will be used for migration title
:type message: string
:param autogenerate: If True - generates diff based on current database
state
:type autogenerate: bool
"""
return alembic.command.revision(config, message=message,
autogenerate=autogenerate)
def stamp(config, revision):
"""Stamps database with provided revision.
:param revision: Should match one from repository or head - to stamp
database with most recent revision
:type revision: string
"""
return alembic.command.stamp(config, revision=revision)