# Copyright 2012 OpenStack Foundation
#
# 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 sqlalchemy as sql


def upgrade(migrate_engine):
    # Upgrade operations go here. Don't create your own engine; bind
    # migrate_engine to your metadata
    meta = sql.MetaData()
    meta.bind = migrate_engine

    # catalog

    service_table = sql.Table(
        'service',
        meta,
        sql.Column('id', sql.String(64), primary_key=True),
        sql.Column('type', sql.String(255)),
        sql.Column('extra', sql.Text()))
    service_table.create(migrate_engine, checkfirst=True)

    endpoint_table = sql.Table(
        'endpoint',
        meta,
        sql.Column('id', sql.String(64), primary_key=True),
        sql.Column('region', sql.String(255)),
        sql.Column('service_id',
                   sql.String(64),
                   sql.ForeignKey('service.id'),
                   nullable=False),
        sql.Column('extra', sql.Text()))
    endpoint_table.create(migrate_engine, checkfirst=True)

    # identity

    role_table = sql.Table(
        'role',
        meta,
        sql.Column('id', sql.String(64), primary_key=True),
        sql.Column('name', sql.String(255), unique=True, nullable=False))
    role_table.create(migrate_engine, checkfirst=True)

    if migrate_engine.name == 'ibm_db_sa':
        # NOTE(blk-u): SQLAlchemy for PostgreSQL picks the name tenant_name_key
        # for the unique constraint, but for DB2 doesn't give the UC a name
        # unless we tell it to and there is no DDL to alter a column to drop
        # an unnamed unique constraint, so this code creates a named unique
        # constraint on the name column rather than an unnamed one.
        # (This is used in migration 16.)
        tenant_table = sql.Table(
            'tenant',
            meta,
            sql.Column('id', sql.String(64), primary_key=True),
            sql.Column('name', sql.String(64), nullable=False),
            sql.Column('extra', sql.Text()),
            sql.UniqueConstraint('name', name='tenant_name_key'))
    else:
        tenant_table = sql.Table(
            'tenant',
            meta,
            sql.Column('id', sql.String(64), primary_key=True),
            sql.Column('name', sql.String(64), unique=True, nullable=False),
            sql.Column('extra', sql.Text()))

    tenant_table.create(migrate_engine, checkfirst=True)

    metadata_table = sql.Table(
        'metadata',
        meta,
        sql.Column('user_id', sql.String(64), primary_key=True),
        sql.Column('tenant_id', sql.String(64), primary_key=True),
        sql.Column('data', sql.Text()))
    metadata_table.create(migrate_engine, checkfirst=True)

    ec2_credential_table = sql.Table(
        'ec2_credential',
        meta,
        sql.Column('access', sql.String(64), primary_key=True),
        sql.Column('secret', sql.String(64)),
        sql.Column('user_id', sql.String(64)),
        sql.Column('tenant_id', sql.String(64)))
    ec2_credential_table.create(migrate_engine, checkfirst=True)

    if migrate_engine.name == 'ibm_db_sa':
        # NOTE(blk-u): SQLAlchemy for PostgreSQL picks the name user_name_key
        # for the unique constraint, but for DB2 doesn't give the UC a name
        # unless we tell it to and there is no DDL to alter a column to drop
        # an unnamed unique constraint, so this code creates a named unique
        # constraint on the name column rather than an unnamed one.
        # (This is used in migration 16.)
        user_table = sql.Table(
            'user',
            meta,
            sql.Column('id', sql.String(64), primary_key=True),
            sql.Column('name', sql.String(64), nullable=False),
            sql.Column('extra', sql.Text()),
            sql.UniqueConstraint('name', name='user_name_key'))
    else:
        user_table = sql.Table(
            'user',
            meta,
            sql.Column('id', sql.String(64), primary_key=True),
            sql.Column('name', sql.String(64), unique=True, nullable=False),
            sql.Column('extra', sql.Text()))

    user_table.create(migrate_engine, checkfirst=True)

    user_tenant_membership_table = sql.Table(
        'user_tenant_membership',
        meta,
        sql.Column(
            'user_id',
            sql.String(64),
            sql.ForeignKey('user.id'),
            primary_key=True),
        sql.Column(
            'tenant_id',
            sql.String(64),
            sql.ForeignKey('tenant.id'),
            primary_key=True))
    user_tenant_membership_table.create(migrate_engine, checkfirst=True)

    # token

    token_table = sql.Table(
        'token',
        meta,
        sql.Column('id', sql.String(64), primary_key=True),
        sql.Column('expires', sql.DateTime()),
        sql.Column('extra', sql.Text()))
    token_table.create(migrate_engine, checkfirst=True)


def downgrade(migrate_engine):
    # Operations to reverse the above upgrade go here.
    meta = sql.MetaData()
    meta.bind = migrate_engine

    tables = ['user_tenant_membership', 'token', 'user', 'tenant', 'role',
              'metadata', 'ec2_credential', 'endpoint', 'service']
    for t in tables:
        table = sql.Table(t, meta, autoload=True)
        table.drop(migrate_engine, checkfirst=True)

[(21, 'sqlalchemy.MetaData', 'sql.MetaData', ([], {}), True, 'import sqlalchemy as sql\n'), (148, 'sqlalchemy.MetaData', 'sql.MetaData', ([], {}), True, 'import sqlalchemy as sql\n'), (154, 'sqlalchemy.Table', 'sql.Table', (['t', 'meta'], {'autoload': '(True)'}), True, 'import sqlalchemy as sql\n'), (29, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (30, 'sqlalchemy.String', 'sql.String', (['(255)'], {}), True, 'import sqlalchemy as sql\n'), (31, 'sqlalchemy.Text', 'sql.Text', ([], {}), True, 'import sqlalchemy as sql\n'), (37, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (38, 'sqlalchemy.String', 'sql.String', (['(255)'], {}), True, 'import sqlalchemy as sql\n'), (40, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (41, 'sqlalchemy.ForeignKey', 'sql.ForeignKey', (['"""service.id"""'], {}), True, 'import sqlalchemy as sql\n'), (43, 'sqlalchemy.Text', 'sql.Text', ([], {}), True, 'import sqlalchemy as sql\n'), (51, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (52, 'sqlalchemy.String', 'sql.String', (['(255)'], {}), True, 'import sqlalchemy as sql\n'), (68, 'sqlalchemy.UniqueConstraint', 'sql.UniqueConstraint', (['"""name"""'], {'name': '"""tenant_name_key"""'}), True, 'import sqlalchemy as sql\n'), (82, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (83, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (84, 'sqlalchemy.Text', 'sql.Text', ([], {}), True, 'import sqlalchemy as sql\n'), (90, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (91, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (92, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (93, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (109, 'sqlalchemy.UniqueConstraint', 'sql.UniqueConstraint', (['"""name"""'], {'name': '"""user_name_key"""'}), True, 'import sqlalchemy as sql\n'), (125, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (126, 'sqlalchemy.ForeignKey', 'sql.ForeignKey', (['"""user.id"""'], {}), True, 'import sqlalchemy as sql\n'), (130, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (131, 'sqlalchemy.ForeignKey', 'sql.ForeignKey', (['"""tenant.id"""'], {}), True, 'import sqlalchemy as sql\n'), (140, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (141, 'sqlalchemy.DateTime', 'sql.DateTime', ([], {}), True, 'import sqlalchemy as sql\n'), (142, 'sqlalchemy.Text', 'sql.Text', ([], {}), True, 'import sqlalchemy as sql\n'), (65, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (66, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (67, 'sqlalchemy.Text', 'sql.Text', ([], {}), True, 'import sqlalchemy as sql\n'), (73, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (74, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (75, 'sqlalchemy.Text', 'sql.Text', ([], {}), True, 'import sqlalchemy as sql\n'), (106, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (107, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (108, 'sqlalchemy.Text', 'sql.Text', ([], {}), True, 'import sqlalchemy as sql\n'), (114, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (115, 'sqlalchemy.String', 'sql.String', (['(64)'], {}), True, 'import sqlalchemy as sql\n'), (116, 'sqlalchemy.Text', 'sql.Text', ([], {}), True, 'import sqlalchemy as sql\n')]