Add alembic support with initial migration

This commit is contained in:
Yuriy Taraday 2016-03-02 17:45:12 +03:00
parent e00980ab57
commit 4f40d2e6ba
6 changed files with 303 additions and 0 deletions

40
alembic.ini Normal file
View File

@ -0,0 +1,40 @@
[alembic]
script_location = tuning_box/migrations
# use in-memory sqlite to generate revisions
sqlalchemy.url = sqlite:///
# 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

@ -6,3 +6,4 @@ pbr>=1.6
flask
flask-sqlalchemy
flask-restful
alembic

View File

@ -0,0 +1,75 @@
# 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.
import logging.config
from alembic import context
import sqlalchemy
from tuning_box import db
config = context.config
if config.get_main_option('table_prefix') is None:
config.set_main_option('table_prefix', '')
logging.config.fileConfig(config.config_file_name)
target_metadata = db.db.metadata
def run_migrations_offline():
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
context.configure(
url=config.get_main_option('sqlalchemy.url'),
version_table=config.get_main_option('version_table'),
literal_binds=True,
)
with context.begin_transaction():
context.run_migrations()
def run_migrations_online():
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""
connectable = sqlalchemy.engine_from_config(
config.get_section(config.config_ini_section),
prefix='sqlalchemy.',
poolclass=sqlalchemy.pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=target_metadata,
version_table=config.get_main_option('version_table'),
)
with context.begin_transaction():
context.run_migrations()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()

View File

@ -0,0 +1,41 @@
# 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.
"""${message}
Revision ID: ${up_revision}
Revises:${" " if down_revision else ""}${down_revision | comma,n}
Create Date: ${create_date}
"""
# revision identifiers, used by Alembic.
revision = ${repr(up_revision)}
down_revision = ${repr(down_revision)}
branch_labels = ${repr(branch_labels)}
depends_on = ${repr(depends_on)}
from alembic import context
from alembic import op
import sqlalchemy as sa
import tuning_box.db
${imports if imports else ""}
def upgrade():
table_prefix = context.config.get_main_option('table_prefix')
${upgrades if upgrades else "pass"}
def downgrade():
table_prefix = context.config.get_main_option('table_prefix')
${downgrades if downgrades else "pass"}

View File

@ -0,0 +1,140 @@
# 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.
"""Initial revision
Revision ID: f16eb4eff7c
Revises:
Create Date: 2016-03-02 17:10:04.750584
"""
# revision identifiers, used by Alembic.
revision = 'f16eb4eff7c'
down_revision = None
branch_labels = None
depends_on = None
from alembic import context
from alembic import op
import sqlalchemy as sa
import tuning_box.db
def upgrade():
table_prefix = context.config.get_main_option('table_prefix')
op.create_table(
table_prefix + 'component',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=True),
sa.PrimaryKeyConstraint('id'),
)
op.create_table(
table_prefix + 'environment',
sa.Column('id', sa.Integer(), nullable=False),
sa.PrimaryKeyConstraint('id'),
)
op.create_table(
table_prefix + 'namespace',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=True),
sa.PrimaryKeyConstraint('id'),
)
op.create_table(
table_prefix + 'environment_components',
sa.Column('environment_id', sa.Integer(), nullable=True),
sa.Column('component_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
['component_id'], [table_prefix + 'component.id']),
sa.ForeignKeyConstraint(
['environment_id'], [table_prefix + 'environment.id']),
)
op.create_table(
table_prefix + 'environment_hierarchy_level',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('environment_id', sa.Integer(), nullable=True),
sa.Column('name', sa.String(length=128), nullable=True),
sa.Column('parent_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
['environment_id'], [table_prefix + 'environment.id']),
sa.ForeignKeyConstraint(
['parent_id'], [table_prefix + 'environment_hierarchy_level.id']),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('environment_id', 'name'),
sa.UniqueConstraint('environment_id', 'parent_id'),
)
op.create_table(
table_prefix + 'schema',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=True),
sa.Column('component_id', sa.Integer(), nullable=True),
sa.Column('namespace_id', sa.Integer(), nullable=True),
sa.Column('content', tuning_box.db.Json(), nullable=True),
sa.ForeignKeyConstraint(
['component_id'], [table_prefix + 'component.id']),
sa.ForeignKeyConstraint(
['namespace_id'], [table_prefix + 'namespace.id']),
sa.PrimaryKeyConstraint('id'),
)
op.create_table(
table_prefix + 'template',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=128), nullable=True),
sa.Column('component_id', sa.Integer(), nullable=True),
sa.Column('content', tuning_box.db.Json(), nullable=True),
sa.ForeignKeyConstraint(
['component_id'], [table_prefix + 'component.id']),
sa.PrimaryKeyConstraint('id'),
)
op.create_table(
table_prefix + 'environment_hierarchy_level_value',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('level_id', sa.Integer(), nullable=True),
sa.Column('parent_id', sa.Integer(), nullable=True),
sa.Column('value', sa.String(length=128), nullable=True),
sa.ForeignKeyConstraint(
['level_id'], [table_prefix + 'environment_hierarchy_level.id']),
sa.ForeignKeyConstraint(
['parent_id'],
[table_prefix + 'environment_hierarchy_level_value.id']),
sa.PrimaryKeyConstraint('id'),
)
op.create_table(
table_prefix + 'environment_schema_values',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('environment_id', sa.Integer(), nullable=True),
sa.Column('schema_id', sa.Integer(), nullable=True),
sa.Column('level_value_id', sa.Integer(), nullable=True),
sa.Column('values', tuning_box.db.Json(), nullable=True),
sa.ForeignKeyConstraint(
['environment_id'], [table_prefix + 'environment.id']),
sa.ForeignKeyConstraint(
['level_value_id'],
[table_prefix + 'environment_hierarchy_level_value.id']),
sa.ForeignKeyConstraint(['schema_id'], [table_prefix + 'schema.id']),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('environment_id', 'schema_id', 'level_value_id'),
)
def downgrade():
table_prefix = context.config.get_main_option('table_prefix')
op.drop_table(table_prefix + 'environment_schema_values')
op.drop_table(table_prefix + 'environment_hierarchy_level_value')
op.drop_table(table_prefix + 'template')
op.drop_table(table_prefix + 'schema')
op.drop_table(table_prefix + 'environment_hierarchy_level')
op.drop_table(table_prefix + 'environment_components')
op.drop_table(table_prefix + 'namespace')
op.drop_table(table_prefix + 'environment')
op.drop_table(table_prefix + 'component')

View File

@ -12,6 +12,8 @@
from __future__ import absolute_import
import os
from nailgun import extensions
import tuning_box
@ -21,3 +23,7 @@ class Extension(extensions.BaseExtension):
name = 'tuning_box'
version = tuning_box.__version__
description = 'Plug tuning_box endpoints into Nailgun itself'
@classmethod
def alembic_migrations_path(cls):
return os.path.join(os.path.dirname(__file__), 'migrations')