Merge "sql: Squash rocky migrations"

This commit is contained in:
Zuul 2022-02-08 13:52:48 +00:00 committed by Gerrit Code Review
commit ee13ca342b
38 changed files with 30 additions and 999 deletions

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,15 +0,0 @@
# 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.
def upgrade(migrate_engine):
pass

View File

@ -1,15 +0,0 @@
# 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.
def upgrade(migrate_engine):
pass

View File

@ -1,63 +0,0 @@
# 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 migrate
import sqlalchemy as sql
def upgrade(migrate_engine):
meta = sql.MetaData()
meta.bind = migrate_engine
# For Mysql and PostgreSQL, drop the FK in limit table, drop the unique
# constraint in registered limit and limit tables.
#
# For SQLite, drop the old tables, then rename the new tables.
limit_table = sql.Table('limit', meta, autoload=True)
registered_limit_table = sql.Table('registered_limit', meta, autoload=True)
if migrate_engine.name != 'sqlite':
project_table = sql.Table('project', meta, autoload=True)
inspector = sql.inspect(migrate_engine)
for fk in inspector.get_foreign_keys('limit'):
fkey = migrate.ForeignKeyConstraint(
[limit_table.c.project_id],
[project_table.c.id],
name=fk['name'])
fkey.drop()
for uc in inspector.get_unique_constraints('limit'):
if set(uc['column_names']) == set(['project_id', 'service_id',
'region_id', 'resource_name']):
uc = migrate.UniqueConstraint(limit_table.c.project_id,
limit_table.c.service_id,
limit_table.c.region_id,
limit_table.c.resource_name,
name=uc['name'])
uc.drop()
for uc in inspector.get_unique_constraints('registered_limit'):
if set(uc['column_names']) == set(['service_id', 'region_id',
'resource_name']):
uc = migrate.UniqueConstraint(
registered_limit_table.c.service_id,
registered_limit_table.c.region_id,
registered_limit_table.c.resource_name,
name=uc['name'])
uc.drop()
else:
registered_limit_table_new = sql.Table('registered_limit_new', meta,
autoload=True)
limit_table_new = sql.Table('limit_new', meta, autoload=True)
limit_table.drop()
limit_table_new.rename('limit')
registered_limit_table.drop()
registered_limit_table_new.rename('registered_limit')

View File

@ -1,15 +0,0 @@
# 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.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,15 +0,0 @@
# 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.
def upgrade(migrate_engine):
pass

View File

@ -1,26 +0,0 @@
# 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
import sqlalchemy.sql.expression as expression
def upgrade(migrate_engine):
meta = sql.MetaData()
meta.bind = migrate_engine
password_table = sql.Table('password', meta, autoload=True)
with migrate_engine.begin() as conn:
stmt = password_table.update().where(
password_table.c.password_hash == expression.null()).values(
{'password_hash': password_table.c.password})
conn.execute(stmt)

View File

@ -1,37 +0,0 @@
# 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):
meta = sql.MetaData()
meta.bind = migrate_engine
# For SQLite, migrate the data from old tables to new ones.
if migrate_engine == 'sqlite':
registered_limit_table = sql.Table('registered_limit', meta,
autoload=True)
registered_limit_table_new = sql.Table('registered_limit_new', meta,
autoload=True)
limit_table = sql.Table('limit', meta, autoload=True)
limit_table_new = sql.Table('limit_new', meta, autoload=True)
registered_limit_table_new.insert().from_select(
['id', 'service_id', 'region_id', 'resource_name', 'default_limit',
'description'],
registered_limit_table.select()).execute()
limit_table_new.insert().from_select(
['id', 'project_id', 'service_id', 'region_id', 'resource_name',
'resource_limit', 'description'],
limit_table.select()).execute()

View File

@ -1,15 +0,0 @@
# 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.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# 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.
# This is a placeholder for Queens backports. Do not use this number for new
# Rocky work. New Rocky work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,29 +0,0 @@
# 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):
meta = sql.MetaData()
meta.bind = migrate_engine
registered_limit_table = sql.Table(
'registered_limit', meta, autoload=True
)
description = sql.Column('description', sql.Text)
registered_limit_table.create_column(description)
limit_table = sql.Table('limit', meta, autoload=True)
description = sql.Column('description', sql.Text)
limit_table.create_column(description)

View File

@ -1,15 +0,0 @@
# 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.
def upgrade(migrate_engine):
pass

View File

@ -1,103 +0,0 @@
# 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 migrate
import sqlalchemy as sql
MYSQL_CREATE_ID_PRIMARY_KEY_COLUMN = """
ALTER TABLE `%s` ADD `internal_id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY;
"""
POSTGRESQL_CREATE_ID_PRIMARY_KEY_COLUMN = """
ALTER TABLE "%s" ADD COLUMN "internal_id" SERIAL PRIMARY KEY;
"""
def upgrade(migrate_engine):
# For both registered_limit and limit tables in MySQL and PostgreSQL:
#
# 1. drop the primary key on `id` column.
# 2. create a auto increment `internal_id` column with primary key.
# 3. add unique constraint on `id` column.
#
# But SQLite doesn't support add primary key to a existed table, so for
# SQLite, we'll follow the steps, take the registered_limit as an example:
#
# 1. Add a new table `registered_limit_new` which contains `internal_id`
# column.
# 2. migrate the data from `registered_limit` to `registered_limit_new`
# 3. drop the `registered_limit`, rename `registered_limit_new` to
# `registered_limit`.
meta = sql.MetaData()
meta.bind = migrate_engine
registered_limit_table = sql.Table('registered_limit', meta, autoload=True)
limit_table = sql.Table('limit', meta, autoload=True)
if migrate_engine.name != 'sqlite':
pk = migrate.PrimaryKeyConstraint('id', table=registered_limit_table)
pk.drop()
if migrate_engine.name == 'mysql':
migrate_engine.execute(
MYSQL_CREATE_ID_PRIMARY_KEY_COLUMN % 'registered_limit')
else:
migrate_engine.execute(
POSTGRESQL_CREATE_ID_PRIMARY_KEY_COLUMN % 'registered_limit')
unique_constraint = migrate.UniqueConstraint(
'id', table=registered_limit_table)
unique_constraint.create()
pk = migrate.PrimaryKeyConstraint('id', table=limit_table)
pk.drop()
if migrate_engine.name == 'mysql':
migrate_engine.execute(
MYSQL_CREATE_ID_PRIMARY_KEY_COLUMN % 'limit')
else:
migrate_engine.execute(
POSTGRESQL_CREATE_ID_PRIMARY_KEY_COLUMN % 'limit')
unique_constraint = migrate.UniqueConstraint('id', table=limit_table)
unique_constraint.create()
else:
# SQLite case
registered_limit_table_new = sql.Table(
'registered_limit_new',
meta,
sql.Column('internal_id', sql.Integer, primary_key=True),
sql.Column('id', sql.String(length=64), unique=True),
sql.Column('service_id',
sql.String(64)),
sql.Column('region_id',
sql.String(64),
nullable=True),
sql.Column('resource_name', sql.String(255)),
sql.Column('default_limit', sql.Integer, nullable=False),
sql.Column('description', sql.Text),
mysql_engine='InnoDB',
mysql_charset='utf8')
registered_limit_table_new.create(migrate_engine, checkfirst=True)
limit_table_new = sql.Table(
'limit_new',
meta,
sql.Column('internal_id', sql.Integer, primary_key=True),
sql.Column('id', sql.String(length=64), unique=True),
sql.Column('project_id', sql.String(64)),
sql.Column('service_id', sql.String(64)),
sql.Column('region_id', sql.String(64), nullable=True),
sql.Column('resource_name', sql.String(255)),
sql.Column('resource_limit', sql.Integer, nullable=False),
sql.Column('description', sql.Text),
mysql_engine='InnoDB',
mysql_charset='utf8')
limit_table_new.create(migrate_engine, checkfirst=True)

View File

@ -1,40 +0,0 @@
# 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):
meta = sql.MetaData()
meta.bind = migrate_engine
registered_limit_table = sql.Table('registered_limit', meta, autoload=True)
limit_table = sql.Table('limit', meta, autoload=True)
registered_limit_id = sql.Column(
'registered_limit_id', sql.String(64),
sql.ForeignKey(registered_limit_table.c.id))
limit_table.create_column(registered_limit_id)
if migrate_engine.name == 'sqlite':
meta = sql.MetaData()
meta.bind = migrate_engine
# "limit_new" is the table created in 047 expand script for SQLite
# case.
try:
limit_table_new = sql.Table('limit_new', meta, autoload=True)
registered_limit_id = sql.Column(
'registered_limit_id', sql.String(64),
sql.ForeignKey(registered_limit_table.c.id))
limit_table_new.create_column(registered_limit_id)
except sql.exc.NoSuchTableError:
pass

View File

@ -735,12 +735,16 @@ def upgrade(migrate_engine):
registered_limit = sql.Table(
'registered_limit',
meta,
sql.Column('id', sql.String(length=64), primary_key=True),
sql.Column('id', sql.String(length=64), nullable=False),
sql.Column('service_id', sql.String(255)),
sql.Column('region_id', sql.String(64), nullable=True),
sql.Column('resource_name', sql.String(255)),
sql.Column('default_limit', sql.Integer, nullable=False),
sql.UniqueConstraint('service_id', 'region_id', 'resource_name'),
sql.Column('description', sql.Text),
sql.Column('internal_id', sql.Integer, primary_key=True),
# NOTE(stephenfin): Name chosen to preserve backwards compatibility
# with names used for primary key unique constraints
sql.UniqueConstraint('id', name='registered_limit_id_key'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
@ -748,15 +752,24 @@ def upgrade(migrate_engine):
limit = sql.Table(
'limit',
meta,
sql.Column('id', sql.String(length=64), primary_key=True),
sql.Column('project_id', sql.String(64), sql.ForeignKey(project.c.id)),
sql.Column('id', sql.String(length=64), nullable=False),
sql.Column('project_id', sql.String(64)),
sql.Column('service_id', sql.String(255)),
sql.Column('region_id', sql.String(64), nullable=True),
sql.Column('resource_name', sql.String(255)),
sql.Column('resource_limit', sql.Integer, nullable=False),
sql.UniqueConstraint(
'project_id', 'service_id', 'region_id', 'resource_name'
sql.Column('description', sql.Text),
sql.Column('internal_id', sql.Integer, primary_key=True),
# FIXME(stephenfin): This should have a foreign key constraint on
# registered_limit.id, but sqlalchemy-migrate clearly didn't handle
# creating a column with embedded FK info as was attempted in 048
sql.Column(
'registered_limit_id',
sql.String(64),
),
# NOTE(stephenfin): Name chosen to preserve backwards compatibility
# with names used for primary key unique constraints
sql.UniqueConstraint('id', name='limit_id_key'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
@ -843,8 +856,8 @@ def upgrade(migrate_engine):
federated_user,
nonlocal_user,
system_assignment,
limit,
registered_limit,
limit,
application_credential,
application_credential_role,
]
@ -923,18 +936,6 @@ def upgrade(migrate_engine):
'onupdate': 'CASCADE',
'ondelete': 'CASCADE',
},
{
'columns': [
limit.c.service_id,
limit.c.region_id,
limit.c.resource_name,
],
'references': [
registered_limit.c.service_id,
registered_limit.c.region_id,
registered_limit.c.resource_name,
],
},
]
if migrate_engine.name == 'sqlite':
@ -1029,3 +1030,7 @@ def upgrade(migrate_engine):
# sqlalchemy-migrate didn't do the job fully and left behind indexes
if migrate_engine.name == 'mysql':
sql.Index('region_id', registered_limit.c.region_id).create()
# FIXME(stephenfin): This should be dropped when we add the FK
# constraint to this column
sql.Index('registered_limit_id', limit.c.registered_limit_id).create()

View File

@ -29,7 +29,7 @@ from keystone.i18n import _
USE_TRIGGERS = True
INITIAL_VERSION = 36
INITIAL_VERSION = 47
EXPAND_REPO = 'expand_repo'
DATA_MIGRATION_REPO = 'data_migration_repo'
CONTRACT_REPO = 'contract_repo'

View File

@ -201,11 +201,13 @@ INITIAL_TABLE_STRUCTURE = {
'type', 'actor_id', 'target_id', 'role_id', 'inherited',
],
'registered_limit': [
'id', 'service_id', 'region_id', 'resource_name', 'default_limit',
'internal_id', 'id', 'service_id', 'region_id', 'resource_name',
'default_limit', 'description',
],
'limit': [
'id', 'project_id', 'service_id', 'region_id', 'resource_name',
'resource_limit',
'internal_id', 'id', 'project_id', 'service_id', 'region_id',
'resource_name', 'resource_limit', 'description',
'registered_limit_id',
],
'application_credential': [
'internal_id', 'id', 'name', 'secret_hash', 'description', 'user_id',
@ -624,216 +626,6 @@ class FullMigration(MigrateBase, unit.TestCase):
upgrades.INITIAL_VERSION + 2,
)
def test_migration_045_add_description_to_limit(self):
self.expand(44)
self.migrate(44)
self.contract(44)
registered_limit_table_name = 'registered_limit'
limit_table_name = 'limit'
self.assertTableExists(registered_limit_table_name)
self.assertTableExists(limit_table_name)
self.assertTableColumns(
registered_limit_table_name,
['id', 'service_id', 'region_id', 'resource_name', 'default_limit']
)
self.assertTableColumns(
limit_table_name,
['id', 'project_id', 'service_id', 'region_id', 'resource_name',
'resource_limit']
)
self.expand(45)
self.migrate(45)
self.contract(45)
registered_limit_table = sqlalchemy.Table(registered_limit_table_name,
self.metadata, autoload=True)
limit_table = sqlalchemy.Table(limit_table_name,
self.metadata, autoload=True)
self.assertTableColumns(
registered_limit_table_name,
['id', 'service_id', 'region_id', 'resource_name', 'default_limit',
'description']
)
self.assertTableColumns(
limit_table_name,
['id', 'project_id', 'service_id', 'region_id', 'resource_name',
'resource_limit', 'description']
)
session = self.sessionmaker()
service_id = uuid.uuid4().hex
service = {
'id': service_id,
'type': 'compute',
'enabled': True
}
region = {
'id': 'RegionOne',
'description': 'test'
}
project_id = uuid.uuid4().hex
project = {
'id': project_id,
'name': 'nova',
'enabled': True,
'domain_id': resource_base.NULL_DOMAIN_ID,
'is_domain': False
}
self.insert_dict(session, 'service', service)
self.insert_dict(session, 'region', region)
self.insert_dict(session, 'project', project)
# with description
registered_limit = {
'id': uuid.uuid4().hex,
'service_id': service_id,
'region_id': 'RegionOne',
'resource_name': 'cores',
'default_limit': 10,
'description': 'this is a description'
}
registered_limit_table.insert().values(registered_limit).execute()
# without description
limit = {
'id': uuid.uuid4().hex,
'project_id': project_id,
'service_id': service_id,
'region_id': 'RegionOne',
'resource_name': 'cores',
'resource_limit': 5
}
limit_table.insert().values(limit).execute()
def test_migration_046_copies_data_from_password_to_password_hash(self):
self.expand(46)
self.migrate(45)
self.contract(45)
# Create User and Local User
project_table = sqlalchemy.Table('project', self.metadata,
autoload=True)
domain_data = {'id': '_domain', 'domain_id': '_domain',
'enabled': True, 'name': '_domain', 'is_domain': True}
project_table.insert().values(domain_data).execute()
user_table = sqlalchemy.Table('user', self.metadata, autoload=True)
user_id = uuid.uuid4().hex
user = {'id': user_id, 'enabled': True, 'domain_id': domain_data['id']}
user_table.insert().values(user).execute()
local_user_table = sqlalchemy.Table('local_user', self.metadata,
autoload=True)
local_user = {
'id': 1, 'user_id': user_id, 'domain_id': user['domain_id'],
'name': 'name'}
local_user_table.insert().values(local_user).execute()
password_table = sqlalchemy.Table('password',
self.metadata, autoload=True)
password_data = {
'local_user_id': local_user['id'],
'created_at': datetime.datetime.utcnow(),
'expires_at': datetime.datetime.utcnow(),
'password': uuid.uuid4().hex}
password_data1 = {
'local_user_id': local_user['id'],
'created_at': datetime.datetime.utcnow(),
'expires_at': datetime.datetime.utcnow(),
'password_hash': uuid.uuid4().hex}
password_data2 = {
'local_user_id': local_user['id'],
'created_at': datetime.datetime.utcnow(),
'expires_at': datetime.datetime.utcnow(),
'password': uuid.uuid4().hex,
'password_hash': uuid.uuid4().hex}
password_table.insert().values(password_data).execute()
password_table.insert().values(password_data1).execute()
password_table.insert().values(password_data2).execute()
self.migrate(46)
passwords = list(password_table.select().execute())
for p in passwords:
if p.password == password_data['password']:
self.assertEqual(p.password_hash, p.password)
self.assertIsNotNone(p.password)
self.assertIsNotNone(p.password_hash)
elif p.password_hash == password_data1['password_hash']:
self.assertIsNone(p.password)
self.assertIsNotNone(p.password_hash)
elif p.password_hash == password_data2['password_hash']:
self.assertIsNotNone(p.password)
self.assertIsNotNone(p.password_hash)
self.assertNotEqual(p.password, p.password_hash)
else:
raise ValueError('Too Many Passwords Found')
def test_migration_047_add_auto_increment_pk_column_to_unified_limit(self):
self.expand(46)
self.migrate(46)
self.contract(46)
registered_limit_table_name = 'registered_limit'
limit_table_name = 'limit'
self.assertTableColumns(
registered_limit_table_name,
['id', 'service_id', 'region_id', 'resource_name', 'default_limit',
'description']
)
self.assertTableColumns(
limit_table_name,
['id', 'project_id', 'service_id', 'region_id', 'resource_name',
'resource_limit', 'description']
)
self.assertTrue(self.does_pk_exist('registered_limit', 'id'))
self.assertTrue(self.does_pk_exist('limit', 'id'))
self.assertTrue(self.does_fk_exist('limit', 'project_id'))
self.expand(47)
self.migrate(47)
self.contract(47)
self.assertTableColumns(
registered_limit_table_name,
['id', 'service_id', 'region_id', 'resource_name', 'default_limit',
'description', 'internal_id']
)
self.assertTableColumns(
limit_table_name,
['id', 'project_id', 'service_id', 'region_id', 'resource_name',
'resource_limit', 'description', 'internal_id']
)
self.assertFalse(self.does_pk_exist('registered_limit', 'id'))
self.assertTrue(self.does_pk_exist('registered_limit', 'internal_id'))
self.assertFalse(self.does_pk_exist('limit', 'id'))
self.assertTrue(self.does_pk_exist('limit', 'internal_id'))
limit_table = sqlalchemy.Table(limit_table_name,
self.metadata, autoload=True)
self.assertEqual(set([]), limit_table.foreign_keys)
def test_migration_048_add_registered_limit_id_column_for_limit(self):
self.expand(47)
self.migrate(47)
self.contract(47)
limit_table_name = 'limit'
self.assertTableColumns(
limit_table_name,
['id', 'project_id', 'service_id', 'region_id', 'resource_name',
'resource_limit', 'description', 'internal_id']
)
self.expand(48)
self.migrate(48)
self.contract(48)
self.assertTableColumns(
limit_table_name,
['id', 'project_id', 'service_id', 'region_id', 'resource_name',
'resource_limit', 'description', 'internal_id',
'registered_limit_id']
)
self.assertTrue(self.does_fk_exist('limit', 'registered_limit_id'))
def test_migration_053_adds_description_to_role(self):
self.expand(52)
self.migrate(52)