diff options
author | Stephen Finucane <stephenfin@redhat.com> | 2022-01-07 17:00:23 +0000 |
---|---|---|
committer | Stephen Finucane <stephenfin@redhat.com> | 2022-01-19 16:58:16 +0000 |
commit | 6525ae297bd33ece99a91ef859dca7619aebb4a8 (patch) | |
tree | f427767c85732f01f25b959e1a6f11d5594ad270 /keystone | |
parent | 4fe0f10b6e21f48a131b8660d610d0bbb877ec64 (diff) | |
download | keystone-6525ae297bd33ece99a91ef859dca7619aebb4a8.tar.gz |
sql: Squash ocata migrations
Make the following changes to the new "initial" migrations.
- Add four additional indexes to 'revocation_event' table (010)
- Add unique constraint to 'user_id' column of 'nonlocal_user' table
(011)
- Add 'domain_id' column to 'identity_provider' table, and a foreign
key constraint on the 'id' column of the 'project' table (012)
- Add 'ondelete=CASCADE' to foreignkey constraint on 'protocol_id' and
'idp_id' columns of 'federated_user' table (013)
- Add 'domain_id' column to the 'user' table (014)
- Replace foreign key constraints covering 'user_id' columns of
'local_user' and 'nonlocal_user' tables with constraints covering
'user_id' and 'domain_id' columns (014)
- Add unique constraint covering 'id' and 'domain_id' columns of 'user'
table (014)
- Alter 'domain_id' column of 'user' table to be non-nullable (015)
- Add 'user_option' table (016)
Change-Id: I96cab42cfcfd3e86b53f25abf4cf4043af3b5667
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
Diffstat (limited to 'keystone')
41 files changed, 113 insertions, 1558 deletions
diff --git a/keystone/common/sql/contract_repo/versions/005_placeholder.py b/keystone/common/sql/contract_repo/versions/005_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/contract_repo/versions/005_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/contract_repo/versions/006_placeholder.py b/keystone/common/sql/contract_repo/versions/006_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/contract_repo/versions/006_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/contract_repo/versions/007_placeholder.py b/keystone/common/sql/contract_repo/versions/007_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/contract_repo/versions/007_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/contract_repo/versions/008_placeholder.py b/keystone/common/sql/contract_repo/versions/008_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/contract_repo/versions/008_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/contract_repo/versions/009_placeholder.py b/keystone/common/sql/contract_repo/versions/009_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/contract_repo/versions/009_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/contract_repo/versions/010_contract_add_revocation_event_index.py b/keystone/common/sql/contract_repo/versions/010_contract_add_revocation_event_index.py deleted file mode 100644 index 8aa15c1ef..000000000 --- a/keystone/common/sql/contract_repo/versions/010_contract_add_revocation_event_index.py +++ /dev/null @@ -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 diff --git a/keystone/common/sql/contract_repo/versions/011_contract_user_id_unique_for_nonlocal_user.py b/keystone/common/sql/contract_repo/versions/011_contract_user_id_unique_for_nonlocal_user.py deleted file mode 100644 index 5c397c575..000000000 --- a/keystone/common/sql/contract_repo/versions/011_contract_user_id_unique_for_nonlocal_user.py +++ /dev/null @@ -1,23 +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 - - nonlocal_user = sql.Table('nonlocal_user', meta, autoload=True) - migrate.UniqueConstraint(nonlocal_user.c.user_id, - name='ixu_nonlocal_user_user_id').create() diff --git a/keystone/common/sql/contract_repo/versions/012_contract_add_domain_id_to_idp.py b/keystone/common/sql/contract_repo/versions/012_contract_add_domain_id_to_idp.py deleted file mode 100644 index b919f93dc..000000000 --- a/keystone/common/sql/contract_repo/versions/012_contract_add_domain_id_to_idp.py +++ /dev/null @@ -1,38 +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 - -from keystone.common.sql import upgrades - - -def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - - idp_table = sql.Table('identity_provider', meta, autoload=True) - idp_table.c.domain_id.alter(nullable=False, unique=True) - - if upgrades.USE_TRIGGERS: - if migrate_engine.name == 'postgresql': - drop_idp_insert_trigger = ( - 'DROP TRIGGER idp_insert_read_only on identity_provider;' - ) - elif migrate_engine.name == 'mysql': - drop_idp_insert_trigger = ( - 'DROP TRIGGER idp_insert_read_only;' - ) - else: - drop_idp_insert_trigger = ( - 'DROP TRIGGER IF EXISTS idp_insert_read_only;' - ) - migrate_engine.execute(drop_idp_insert_trigger) diff --git a/keystone/common/sql/contract_repo/versions/013_contract_protocol_cascade_delete_for_federated_user.py b/keystone/common/sql/contract_repo/versions/013_contract_protocol_cascade_delete_for_federated_user.py deleted file mode 100644 index 9c6c9bc2d..000000000 --- a/keystone/common/sql/contract_repo/versions/013_contract_protocol_cascade_delete_for_federated_user.py +++ /dev/null @@ -1,31 +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 - - federated_table = sql.Table('federated_user', meta, autoload=True) - protocol_table = sql.Table('federation_protocol', meta, autoload=True) - - migrate.ForeignKeyConstraint( - columns=[federated_table.c.protocol_id, federated_table.c.idp_id], - refcolumns=[protocol_table.c.id, protocol_table.c.idp_id]).drop() - - migrate.ForeignKeyConstraint( - columns=[federated_table.c.protocol_id, federated_table.c.idp_id], - refcolumns=[protocol_table.c.id, protocol_table.c.idp_id], - ondelete='CASCADE').create() diff --git a/keystone/common/sql/contract_repo/versions/014_contract_add_domain_id_to_user_table.py b/keystone/common/sql/contract_repo/versions/014_contract_add_domain_id_to_user_table.py deleted file mode 100644 index 86eaeae3f..000000000 --- a/keystone/common/sql/contract_repo/versions/014_contract_add_domain_id_to_user_table.py +++ /dev/null @@ -1,94 +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 - -from keystone.common.sql import upgrades - - -def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - inspector = sql.inspect(migrate_engine) - - user = sql.Table('user', meta, autoload=True) - local_user = sql.Table('local_user', meta, autoload=True) - nonlocal_user = sql.Table('nonlocal_user', meta, autoload=True) - - # drop previous fk constraints - fk_name = _get_fk_name(inspector, 'local_user', 'user_id') - if fk_name: - migrate.ForeignKeyConstraint(columns=[local_user.c.user_id], - refcolumns=[user.c.id], - name=fk_name).drop() - - fk_name = _get_fk_name(inspector, 'nonlocal_user', 'user_id') - if fk_name: - migrate.ForeignKeyConstraint(columns=[nonlocal_user.c.user_id], - refcolumns=[user.c.id], - name=fk_name).drop() - - # create user unique constraint needed for the new composite fk constraint - migrate.UniqueConstraint(user.c.id, user.c.domain_id, - name='ixu_user_id_domain_id').create() - # create new composite fk constraints - migrate.ForeignKeyConstraint( - columns=[local_user.c.user_id, local_user.c.domain_id], - refcolumns=[user.c.id, user.c.domain_id], - onupdate='CASCADE', ondelete='CASCADE').create() - migrate.ForeignKeyConstraint( - columns=[nonlocal_user.c.user_id, nonlocal_user.c.domain_id], - refcolumns=[user.c.id, user.c.domain_id], - onupdate='CASCADE', ondelete='CASCADE').create() - - # drop triggers - if upgrades.USE_TRIGGERS: - if migrate_engine.name == 'postgresql': - drop_local_user_insert_trigger = ( - 'DROP TRIGGER local_user_after_insert_trigger on local_user;') - drop_local_user_update_trigger = ( - 'DROP TRIGGER local_user_after_update_trigger on local_user;') - drop_nonlocal_user_insert_trigger = ( - 'DROP TRIGGER nonlocal_user_after_insert_trigger ' - 'on nonlocal_user;') - drop_nonlocal_user_update_trigger = ( - 'DROP TRIGGER nonlocal_user_after_update_trigger ' - 'on nonlocal_user;') - elif migrate_engine.name == 'mysql': - drop_local_user_insert_trigger = ( - 'DROP TRIGGER local_user_after_insert_trigger;') - drop_local_user_update_trigger = ( - 'DROP TRIGGER local_user_after_update_trigger;') - drop_nonlocal_user_insert_trigger = ( - 'DROP TRIGGER nonlocal_user_after_insert_trigger;') - drop_nonlocal_user_update_trigger = ( - 'DROP TRIGGER nonlocal_user_after_update_trigger;') - else: - drop_local_user_insert_trigger = ( - 'DROP TRIGGER IF EXISTS local_user_after_insert_trigger;') - drop_local_user_update_trigger = ( - 'DROP TRIGGER IF EXISTS local_user_after_update_trigger;') - drop_nonlocal_user_insert_trigger = ( - 'DROP TRIGGER IF EXISTS nonlocal_user_after_insert_trigger;') - drop_nonlocal_user_update_trigger = ( - 'DROP TRIGGER IF EXISTS nonlocal_user_after_update_trigger;') - migrate_engine.execute(drop_local_user_insert_trigger) - migrate_engine.execute(drop_local_user_update_trigger) - migrate_engine.execute(drop_nonlocal_user_insert_trigger) - migrate_engine.execute(drop_nonlocal_user_update_trigger) - - -def _get_fk_name(inspector, table, fk_column): - for fk in inspector.get_foreign_keys(table): - if fk_column in fk['constrained_columns']: - return fk['name'] diff --git a/keystone/common/sql/contract_repo/versions/015_contract_update_federated_user_domain.py b/keystone/common/sql/contract_repo/versions/015_contract_update_federated_user_domain.py deleted file mode 100644 index 8dd77c60a..000000000 --- a/keystone/common/sql/contract_repo/versions/015_contract_update_federated_user_domain.py +++ /dev/null @@ -1,34 +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 - -from keystone.common.sql import upgrades - - -def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - - user_table = sql.Table('user', meta, autoload=True) - user_table.c.domain_id.alter(nullable=False) - - if upgrades.USE_TRIGGERS: - if migrate_engine.name == 'postgresql': - drop_trigger_stmt = 'DROP TRIGGER federated_user_insert_trigger ' - drop_trigger_stmt += 'on federated_user;' - elif migrate_engine.name == 'mysql': - drop_trigger_stmt = 'DROP TRIGGER federated_user_insert_trigger;' - else: - drop_trigger_stmt = ( - 'DROP TRIGGER IF EXISTS federated_user_insert_trigger;') - migrate_engine.execute(drop_trigger_stmt) diff --git a/keystone/common/sql/contract_repo/versions/016_contract_add_user_options.py b/keystone/common/sql/contract_repo/versions/016_contract_add_user_options.py deleted file mode 100644 index 9b6593fe6..000000000 --- a/keystone/common/sql/contract_repo/versions/016_contract_add_user_options.py +++ /dev/null @@ -1,16 +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): - # NOTE(notmorgan): This is a no-op, no data-migration needed. - pass diff --git a/keystone/common/sql/contract_repo/versions/004_contract_initial_migration.py b/keystone/common/sql/contract_repo/versions/016_contract_initial_migration.py index 1cd34e617..1cd34e617 100644 --- a/keystone/common/sql/contract_repo/versions/004_contract_initial_migration.py +++ b/keystone/common/sql/contract_repo/versions/016_contract_initial_migration.py diff --git a/keystone/common/sql/data_migration_repo/versions/005_placeholder.py b/keystone/common/sql/data_migration_repo/versions/005_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/data_migration_repo/versions/005_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/data_migration_repo/versions/006_placeholder.py b/keystone/common/sql/data_migration_repo/versions/006_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/data_migration_repo/versions/006_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/data_migration_repo/versions/007_placeholder.py b/keystone/common/sql/data_migration_repo/versions/007_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/data_migration_repo/versions/007_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/data_migration_repo/versions/008_placeholder.py b/keystone/common/sql/data_migration_repo/versions/008_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/data_migration_repo/versions/008_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/data_migration_repo/versions/009_placeholder.py b/keystone/common/sql/data_migration_repo/versions/009_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/data_migration_repo/versions/009_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/data_migration_repo/versions/010_migrate_add_revocation_event_index.py b/keystone/common/sql/data_migration_repo/versions/010_migrate_add_revocation_event_index.py deleted file mode 100644 index 8aa15c1ef..000000000 --- a/keystone/common/sql/data_migration_repo/versions/010_migrate_add_revocation_event_index.py +++ /dev/null @@ -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 diff --git a/keystone/common/sql/data_migration_repo/versions/011_expand_user_id_unique_for_nonlocal_user.py b/keystone/common/sql/data_migration_repo/versions/011_expand_user_id_unique_for_nonlocal_user.py deleted file mode 100644 index 8aa15c1ef..000000000 --- a/keystone/common/sql/data_migration_repo/versions/011_expand_user_id_unique_for_nonlocal_user.py +++ /dev/null @@ -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 diff --git a/keystone/common/sql/data_migration_repo/versions/012_migrate_add_domain_id_to_idp.py b/keystone/common/sql/data_migration_repo/versions/012_migrate_add_domain_id_to_idp.py deleted file mode 100644 index d8b931aed..000000000 --- a/keystone/common/sql/data_migration_repo/versions/012_migrate_add_domain_id_to_idp.py +++ /dev/null @@ -1,55 +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 uuid - -import sqlalchemy as sql -from sqlalchemy.orm import sessionmaker - -from keystone.resource.backends import base - - -def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - maker = sessionmaker(bind=migrate_engine) - session = maker() - - idp_table = sql.Table('identity_provider', meta, autoload=True) - - for idp_row in idp_table.select().execute(): - domain_id = _create_federated_domain(meta, session, idp_row['id']) - # update idp with the new federated domain_id - values = {'domain_id': domain_id} - stmt = idp_table.update().where( - idp_table.c.id == idp_row['id']).values(values) - stmt.execute() - - -def _create_federated_domain(meta, session, idp_id): - domain_id = uuid.uuid4().hex - desc = 'Auto generated federated domain for Identity Provider: ' + idp_id - federated_domain = { - 'id': domain_id, - 'name': domain_id, - 'enabled': True, - 'description': desc, - 'domain_id': base.NULL_DOMAIN_ID, - 'is_domain': True, - 'parent_id': None, - 'extra': '{}' - } - project_table = sql.Table('project', meta, autoload=True) - new_row = project_table.insert().values(**federated_domain) - session.execute(new_row) - session.commit() - return domain_id diff --git a/keystone/common/sql/data_migration_repo/versions/013_migrate_protocol_cascade_delete_for_federated_user.py b/keystone/common/sql/data_migration_repo/versions/013_migrate_protocol_cascade_delete_for_federated_user.py deleted file mode 100644 index 9cb40b454..000000000 --- a/keystone/common/sql/data_migration_repo/versions/013_migrate_protocol_cascade_delete_for_federated_user.py +++ /dev/null @@ -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 diff --git a/keystone/common/sql/data_migration_repo/versions/014_migrate_add_domain_id_to_user_table.py b/keystone/common/sql/data_migration_repo/versions/014_migrate_add_domain_id_to_user_table.py deleted file mode 100644 index b4437fe59..000000000 --- a/keystone/common/sql/data_migration_repo/versions/014_migrate_add_domain_id_to_user_table.py +++ /dev/null @@ -1,45 +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 - - user_table = sql.Table('user', meta, autoload=True) - - # update user domain_id from local_user - local_table = sql.Table('local_user', meta, autoload=True) - _update_user_domain_id(migrate_engine, user_table, local_table) - - # update user domain_id from nonlocal_user - nonlocal_table = sql.Table('nonlocal_user', meta, autoload=True) - _update_user_domain_id(migrate_engine, user_table, nonlocal_table) - - -def _update_user_domain_id(migrate_engine, user_table, child_user_table): - join = sql.join(user_table, child_user_table, - user_table.c.id == child_user_table.c.user_id) - where = user_table.c.domain_id == expression.null() - sel = ( - sql.select([user_table.c.id, child_user_table.c.domain_id]) - .select_from(join).where(where) - ) - with migrate_engine.begin() as conn: - for user in conn.execute(sel): - values = {'domain_id': user['domain_id']} - stmt = user_table.update().where( - user_table.c.id == user['id']).values(values) - conn.execute(stmt) diff --git a/keystone/common/sql/data_migration_repo/versions/015_migrate_update_federated_user_domain.py b/keystone/common/sql/data_migration_repo/versions/015_migrate_update_federated_user_domain.py deleted file mode 100644 index 83ac4d36e..000000000 --- a/keystone/common/sql/data_migration_repo/versions/015_migrate_update_federated_user_domain.py +++ /dev/null @@ -1,36 +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 - - user_table = sql.Table('user', meta, autoload=True) - federated_table = sql.Table('federated_user', meta, autoload=True) - idp_table = sql.Table('identity_provider', meta, autoload=True) - - join = sql.join(federated_table, idp_table, - federated_table.c.idp_id == idp_table.c.id) - sel = sql.select( - [federated_table.c.user_id, idp_table.c.domain_id]).select_from(join) - with migrate_engine.begin() as conn: - for user in conn.execute(sel): - values = {'domain_id': user['domain_id']} - stmt = user_table.update().where( - sql.and_( - user_table.c.domain_id == expression.null(), - user_table.c.id == user['user_id'])).values(values) - conn.execute(stmt) diff --git a/keystone/common/sql/data_migration_repo/versions/016_migrate_add_user_options.py b/keystone/common/sql/data_migration_repo/versions/016_migrate_add_user_options.py deleted file mode 100644 index 9b6593fe6..000000000 --- a/keystone/common/sql/data_migration_repo/versions/016_migrate_add_user_options.py +++ /dev/null @@ -1,16 +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): - # NOTE(notmorgan): This is a no-op, no data-migration needed. - pass diff --git a/keystone/common/sql/data_migration_repo/versions/004_data_initial_migration.py b/keystone/common/sql/data_migration_repo/versions/016_migrate_initial_migration.py index d05b151b8..d05b151b8 100644 --- a/keystone/common/sql/data_migration_repo/versions/004_data_initial_migration.py +++ b/keystone/common/sql/data_migration_repo/versions/016_migrate_initial_migration.py diff --git a/keystone/common/sql/expand_repo/versions/005_placeholder.py b/keystone/common/sql/expand_repo/versions/005_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/expand_repo/versions/005_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/expand_repo/versions/006_placeholder.py b/keystone/common/sql/expand_repo/versions/006_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/expand_repo/versions/006_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/expand_repo/versions/007_placeholder.py b/keystone/common/sql/expand_repo/versions/007_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/expand_repo/versions/007_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/expand_repo/versions/008_placeholder.py b/keystone/common/sql/expand_repo/versions/008_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/expand_repo/versions/008_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/expand_repo/versions/009_placeholder.py b/keystone/common/sql/expand_repo/versions/009_placeholder.py deleted file mode 100644 index b259427e4..000000000 --- a/keystone/common/sql/expand_repo/versions/009_placeholder.py +++ /dev/null @@ -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 Newton backports. Do not use this number for new -# Ocata work. New Ocata work starts after all the placeholders. - - -def upgrade(migrate_engine): - pass diff --git a/keystone/common/sql/expand_repo/versions/010_expand_add_revocation_event_index.py b/keystone/common/sql/expand_repo/versions/010_expand_add_revocation_event_index.py deleted file mode 100644 index 1eee406f8..000000000 --- a/keystone/common/sql/expand_repo/versions/010_expand_add_revocation_event_index.py +++ /dev/null @@ -1,31 +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 - - revocation_event = sql.Table('revocation_event', meta, autoload=True) - sql.Index('ix_revocation_event_issued_before', - revocation_event.c.issued_before).create() - sql.Index('ix_revocation_event_project_id_issued_before', - revocation_event.c.project_id, - revocation_event.c.issued_before).create() - sql.Index('ix_revocation_event_user_id_issued_before', - revocation_event.c.user_id, - revocation_event.c.issued_before).create() - sql.Index('ix_revocation_event_audit_id_issued_before', - revocation_event.c.audit_id, - revocation_event.c.issued_before).create() diff --git a/keystone/common/sql/expand_repo/versions/011_expand_user_id_unique_for_nonlocal_user.py b/keystone/common/sql/expand_repo/versions/011_expand_user_id_unique_for_nonlocal_user.py deleted file mode 100644 index 9cb40b454..000000000 --- a/keystone/common/sql/expand_repo/versions/011_expand_user_id_unique_for_nonlocal_user.py +++ /dev/null @@ -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 diff --git a/keystone/common/sql/expand_repo/versions/012_expand_add_domain_id_to_idp.py b/keystone/common/sql/expand_repo/versions/012_expand_add_domain_id_to_idp.py deleted file mode 100644 index ef4522f59..000000000 --- a/keystone/common/sql/expand_repo/versions/012_expand_add_domain_id_to_idp.py +++ /dev/null @@ -1,73 +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 - -from keystone.common.sql import upgrades - - -MYSQL_INSERT_TRIGGER = """ -CREATE TRIGGER idp_insert_read_only BEFORE INSERT ON identity_provider -FOR EACH ROW -BEGIN - SIGNAL SQLSTATE '45000' - SET MESSAGE_TEXT = '%s'; -END; -""" - -SQLITE_INSERT_TRIGGER = """ -CREATE TRIGGER idp_insert_read_only BEFORE INSERT ON identity_provider -BEGIN - SELECT RAISE (ABORT, '%s'); -END; -""" - -POSTGRESQL_INSERT_TRIGGER = """ -CREATE OR REPLACE FUNCTION keystone_read_only_insert() - RETURNS trigger AS -$BODY$ -BEGIN - RAISE EXCEPTION '%s'; -END -$BODY$ LANGUAGE plpgsql; - -CREATE TRIGGER idp_insert_read_only BEFORE INSERT ON identity_provider -FOR EACH ROW -EXECUTE PROCEDURE keystone_read_only_insert(); -""" - - -def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - - idp = sql.Table('identity_provider', meta, autoload=True) - project = sql.Table('project', meta, autoload=True) - domain_id = sql.Column('domain_id', sql.String(64), - sql.ForeignKey(project.c.id), nullable=True) - idp.create_column(domain_id) - - if upgrades.USE_TRIGGERS: - # Setting idp to be read-only to prevent old code from creating an idp - # without a domain_id during an upgrade. This should be okay as it is - # highly unlikely that an idp would be created during the migration and - # the impact from preventing creations is minor. - error_message = ('Identity provider migration in progress. Cannot ' - 'insert new rows into the identity_provider table at ' - 'this time.') - if migrate_engine.name == 'postgresql': - idp_insert_trigger = POSTGRESQL_INSERT_TRIGGER % error_message - elif migrate_engine.name == 'sqlite': - idp_insert_trigger = SQLITE_INSERT_TRIGGER % error_message - else: - idp_insert_trigger = MYSQL_INSERT_TRIGGER % error_message - migrate_engine.execute(idp_insert_trigger) diff --git a/keystone/common/sql/expand_repo/versions/013_expand_protocol_cascade_delete_for_federated_user.py b/keystone/common/sql/expand_repo/versions/013_expand_protocol_cascade_delete_for_federated_user.py deleted file mode 100644 index 9cb40b454..000000000 --- a/keystone/common/sql/expand_repo/versions/013_expand_protocol_cascade_delete_for_federated_user.py +++ /dev/null @@ -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 diff --git a/keystone/common/sql/expand_repo/versions/014_expand_add_domain_id_to_user_table.py b/keystone/common/sql/expand_repo/versions/014_expand_add_domain_id_to_user_table.py deleted file mode 100644 index 27ae96487..000000000 --- a/keystone/common/sql/expand_repo/versions/014_expand_add_domain_id_to_user_table.py +++ /dev/null @@ -1,165 +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 - -from keystone.common.sql import upgrades - -# define the local_user triggers for insert and update -MYSQL_LOCAL_USER_INSERT_TRIGGER = """ -CREATE TRIGGER local_user_after_insert_trigger -AFTER INSERT - ON local_user FOR EACH ROW -BEGIN - UPDATE user SET domain_id = NEW.domain_id - WHERE id = NEW.user_id and domain_id IS NULL; -END; -""" - -MYSQL_LOCAL_USER_UPDATE_TRIGGER = """ -CREATE TRIGGER local_user_after_update_trigger -AFTER UPDATE - ON local_user FOR EACH ROW -BEGIN - UPDATE user SET domain_id = NEW.domain_id - WHERE id = NEW.user_id and domain_id <> NEW.domain_id; -END; -""" - -SQLITE_LOCAL_USER_INSERT_TRIGGER = """ -CREATE TRIGGER local_user_after_insert_trigger -AFTER INSERT - ON local_user -BEGIN - UPDATE user SET domain_id = NEW.domain_id - WHERE id = NEW.user_id and domain_id IS NULL; -END; -""" - -SQLITE_LOCAL_USER_UPDATE_TRIGGER = """ -CREATE TRIGGER local_user_after_update_trigger -AFTER UPDATE - ON local_user -BEGIN - UPDATE user SET domain_id = NEW.domain_id - WHERE id = NEW.user_id and domain_id <> NEW.domain_id; -END; -""" - -POSTGRESQL_LOCAL_USER_INSERT_TRIGGER = """ -CREATE OR REPLACE FUNCTION update_user_domain_id() - RETURNS trigger AS -$BODY$ -BEGIN - UPDATE "user" SET domain_id = NEW.domain_id - WHERE id = NEW.user_id; - RETURN NULL; -END -$BODY$ LANGUAGE plpgsql; - -CREATE TRIGGER local_user_after_insert_trigger AFTER INSERT ON local_user -FOR EACH ROW -EXECUTE PROCEDURE update_user_domain_id(); -""" - -POSTGRESQL_LOCAL_USER_UPDATE_TRIGGER = """ -CREATE TRIGGER local_user_after_update_trigger AFTER UPDATE ON local_user -FOR EACH ROW -EXECUTE PROCEDURE update_user_domain_id(); -""" - -MYSQL_NONLOCAL_USER_INSERT_TRIGGER = """ -CREATE TRIGGER nonlocal_user_after_insert_trigger -AFTER INSERT - ON nonlocal_user FOR EACH ROW -BEGIN - UPDATE user SET domain_id = NEW.domain_id - WHERE id = NEW.user_id and domain_id IS NULL; -END; -""" - -# define the nonlocal_user triggers for insert and update -MYSQL_NONLOCAL_USER_UPDATE_TRIGGER = """ -CREATE TRIGGER nonlocal_user_after_update_trigger -AFTER UPDATE - ON nonlocal_user FOR EACH ROW -BEGIN - UPDATE user SET domain_id = NEW.domain_id - WHERE id = NEW.user_id and domain_id <> NEW.domain_id; -END; -""" - -SQLITE_NONLOCAL_USER_INSERT_TRIGGER = """ -CREATE TRIGGER nonlocal_user_after_insert_trigger -AFTER INSERT - ON nonlocal_user -BEGIN - UPDATE user SET domain_id = NEW.domain_id - WHERE id = NEW.user_id and domain_id IS NULL; -END; -""" - -SQLITE_NONLOCAL_USER_UPDATE_TRIGGER = """ -CREATE TRIGGER nonlocal_user_after_update_trigger -AFTER UPDATE - ON nonlocal_user -BEGIN - UPDATE user SET domain_id = NEW.domain_id - WHERE id = NEW.user_id and domain_id <> NEW.domain_id; -END; -""" - -POSTGRESQL_NONLOCAL_USER_INSERT_TRIGGER = """ -CREATE TRIGGER nonlocal_user_after_insert_trigger AFTER INSERT ON nonlocal_user -FOR EACH ROW -EXECUTE PROCEDURE update_user_domain_id(); -""" - -POSTGRESQL_NONLOCAL_USER_UPDATE_TRIGGER = """ -CREATE TRIGGER nonlocal_user_after_update_trigger AFTER UPDATE ON nonlocal_user -FOR EACH ROW -EXECUTE PROCEDURE update_user_domain_id(); -""" - - -def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - - user = sql.Table('user', meta, autoload=True) - project = sql.Table('project', meta, autoload=True) - domain_id = sql.Column('domain_id', sql.String(64), - sql.ForeignKey(project.c.id), nullable=True) - user.create_column(domain_id) - - if upgrades.USE_TRIGGERS: - if migrate_engine.name == 'postgresql': - local_user_insert_trigger = POSTGRESQL_LOCAL_USER_INSERT_TRIGGER - local_user_update_trigger = POSTGRESQL_LOCAL_USER_UPDATE_TRIGGER - nonlocal_user_insert_trigger = ( - POSTGRESQL_NONLOCAL_USER_INSERT_TRIGGER) - nonlocal_user_update_trigger = ( - POSTGRESQL_NONLOCAL_USER_UPDATE_TRIGGER) - elif migrate_engine.name == 'sqlite': - local_user_insert_trigger = SQLITE_LOCAL_USER_INSERT_TRIGGER - local_user_update_trigger = SQLITE_LOCAL_USER_UPDATE_TRIGGER - nonlocal_user_insert_trigger = SQLITE_NONLOCAL_USER_INSERT_TRIGGER - nonlocal_user_update_trigger = SQLITE_NONLOCAL_USER_UPDATE_TRIGGER - else: - local_user_insert_trigger = MYSQL_LOCAL_USER_INSERT_TRIGGER - local_user_update_trigger = MYSQL_LOCAL_USER_UPDATE_TRIGGER - nonlocal_user_insert_trigger = MYSQL_NONLOCAL_USER_INSERT_TRIGGER - nonlocal_user_update_trigger = MYSQL_NONLOCAL_USER_UPDATE_TRIGGER - migrate_engine.execute(local_user_insert_trigger) - migrate_engine.execute(local_user_update_trigger) - migrate_engine.execute(nonlocal_user_insert_trigger) - migrate_engine.execute(nonlocal_user_update_trigger) diff --git a/keystone/common/sql/expand_repo/versions/015_expand_update_federated_user_domain.py b/keystone/common/sql/expand_repo/versions/015_expand_update_federated_user_domain.py deleted file mode 100644 index 5a078aef4..000000000 --- a/keystone/common/sql/expand_repo/versions/015_expand_update_federated_user_domain.py +++ /dev/null @@ -1,69 +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 - -from keystone.common.sql import upgrades - - -MYSQL_INSERT_TRIGGER = """ -CREATE TRIGGER federated_user_insert_trigger -AFTER INSERT - ON federated_user FOR EACH ROW -BEGIN - UPDATE user SET domain_id = ( - SELECT domain_id FROM identity_provider WHERE id = NEW.idp_id) - WHERE id = NEW.user_id and domain_id IS NULL; -END; -""" - -SQLITE_INSERT_TRIGGER = """ -CREATE TRIGGER federated_user_insert_trigger -AFTER INSERT - ON federated_user -BEGIN - UPDATE user SET domain_id = ( - SELECT domain_id FROM identity_provider WHERE id = NEW.idp_id) - WHERE id = NEW.user_id and domain_id IS NULL; -END; -""" - -POSTGRESQL_INSERT_TRIGGER = """ -CREATE OR REPLACE FUNCTION update_federated_user_domain_id() - RETURNS trigger AS -$BODY$ -BEGIN - UPDATE "user" SET domain_id = ( - SELECT domain_id FROM identity_provider WHERE id = NEW.idp_id) - WHERE id = NEW.user_id and domain_id IS NULL; - RETURN NULL; -END -$BODY$ LANGUAGE plpgsql; - -CREATE TRIGGER federated_user_insert_trigger AFTER INSERT ON federated_user -FOR EACH ROW -EXECUTE PROCEDURE update_federated_user_domain_id(); -""" - - -def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - - if upgrades.USE_TRIGGERS: - if migrate_engine.name == 'postgresql': - insert_trigger = POSTGRESQL_INSERT_TRIGGER - elif migrate_engine.name == 'sqlite': - insert_trigger = SQLITE_INSERT_TRIGGER - else: - insert_trigger = MYSQL_INSERT_TRIGGER - migrate_engine.execute(insert_trigger) diff --git a/keystone/common/sql/expand_repo/versions/016_expand_add_user_options.py b/keystone/common/sql/expand_repo/versions/016_expand_add_user_options.py deleted file mode 100644 index eec3378c7..000000000 --- a/keystone/common/sql/expand_repo/versions/016_expand_add_user_options.py +++ /dev/null @@ -1,34 +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 - -from keystone.common import sql as ks_sql - - -def upgrade(migrate_engine): - meta = sql.MetaData() - meta.bind = migrate_engine - user_table = sql.Table('user', meta, autoload=True) - - user_option = sql.Table( - 'user_option', - meta, - sql.Column('user_id', sql.String(64), sql.ForeignKey(user_table.c.id, - ondelete='CASCADE'), nullable=False, primary_key=True), - sql.Column('option_id', sql.String(4), nullable=False, - primary_key=True), - sql.Column('option_value', ks_sql.JsonBlob, nullable=True), - mysql_engine='InnoDB', - mysql_charset='utf8') - - user_option.create(migrate_engine, checkfirst=True) diff --git a/keystone/common/sql/expand_repo/versions/004_expand_initial_migration.py b/keystone/common/sql/expand_repo/versions/016_expand_initial_migration.py index a20a423e5..77e2ae452 100644 --- a/keystone/common/sql/expand_repo/versions/004_expand_initial_migration.py +++ b/keystone/common/sql/expand_repo/versions/016_expand_initial_migration.py @@ -192,6 +192,7 @@ def upgrade(migrate_engine): sql.Column('id', sql.String(64), primary_key=True), sql.Column('enabled', sql.Boolean, nullable=False), sql.Column('description', sql.Text(), nullable=True), + sql.Column('domain_id', sql.String(64), nullable=False), mysql_engine='InnoDB', mysql_charset='utf8', ) @@ -225,7 +226,6 @@ def upgrade(migrate_engine): sql.Column( 'user_id', sql.String(64), - sql.ForeignKey('user.id', ondelete='CASCADE'), nullable=False, unique=True, ), @@ -401,6 +401,22 @@ def upgrade(migrate_engine): # was 'revocation_event_new' so the index got that name. We may wish to # rename this eventually. sql.Index('ix_revocation_event_new_revoked_at', 'revoked_at'), + sql.Index('ix_revocation_event_issued_before', 'issued_before'), + sql.Index( + 'ix_revocation_event_project_id_issued_before', + 'project_id', + 'issued_before', + ), + sql.Index( + 'ix_revocation_event_user_id_issued_before', + 'user_id', + 'issued_before', + ), + sql.Index( + 'ix_revocation_event_audit_id_issued_before', + 'audit_id', + 'issued_before', + ), ) role = sql.Table( @@ -469,9 +485,7 @@ def upgrade(migrate_engine): sql.Column('trust_id', sql.String(length=64)), sql.Column('user_id', sql.String(length=64)), sql.Index('ix_token_expires', 'expires'), - sql.Index( - 'ix_token_expires_valid', 'expires', 'valid' - ), + sql.Index('ix_token_expires_valid', 'expires', 'valid'), sql.Index('ix_token_user_id', 'user_id'), sql.Index('ix_token_trust_id', 'trust_id'), mysql_engine='InnoDB', @@ -524,6 +538,31 @@ def upgrade(migrate_engine): sql.Column('default_project_id', sql.String(length=64)), sql.Column('created_at', sql.DateTime(), nullable=True), sql.Column('last_active_at', sql.Date(), nullable=True), + sql.Column( + 'domain_id', + sql.String(64), + sql.ForeignKey(project.c.id), + nullable=False, + ), + sql.UniqueConstraint('id', 'domain_id', name='ixu_user_id_domain_id'), + mysql_engine='InnoDB', + mysql_charset='utf8', + ) + + user_option = sql.Table( + 'user_option', + meta, + sql.Column( + 'user_id', + sql.String(64), + sql.ForeignKey(user.c.id, ondelete='CASCADE'), + nullable=False, + primary_key=True, + ), + sql.Column( + 'option_id', sql.String(4), nullable=False, primary_key=True + ), + sql.Column('option_value', ks_sql.JsonBlob, nullable=True), mysql_engine='InnoDB', mysql_charset='utf8', ) @@ -536,9 +575,9 @@ def upgrade(migrate_engine): sql.Column( 'user_id', sql.String(64), - sql.ForeignKey(user.c.id, ondelete='CASCADE'), nullable=False, ), + sql.UniqueConstraint('user_id', name='ixu_nonlocal_user_user_id'), mysql_engine='InnoDB', mysql_charset='utf8', ) @@ -656,6 +695,7 @@ def upgrade(migrate_engine): trust, trust_role, user, + user_option, user_group_membership, region, assignment, @@ -738,6 +778,24 @@ def upgrade(migrate_engine): federation_protocol.c.id, federation_protocol.c.idp_id, ], + 'ondelete': 'CASCADE', + }, + { + 'columns': [identity_provider.c.domain_id], + 'references': [project.c.id], + 'name': 'domain_id', + }, + { + 'columns': [local_user.c.user_id, local_user.c.domain_id], + 'references': [user.c.id, user.c.domain_id], + 'onupdate': 'CASCADE', + 'ondelete': 'CASCADE', + }, + { + 'columns': [nonlocal_user.c.user_id, nonlocal_user.c.domain_id], + 'references': [user.c.id, user.c.domain_id], + 'onupdate': 'CASCADE', + 'ondelete': 'CASCADE', }, ] @@ -758,6 +816,7 @@ def upgrade(migrate_engine): refcolumns=fkey['references'], name=fkey.get('name'), ondelete=fkey.get('ondelete'), + onupdate=fkey.get('onupdate'), ).create() # TODO(stephenfin): Remove these procedures in a future contract migration @@ -783,3 +842,46 @@ def upgrade(migrate_engine): $BODY$ LANGUAGE plpgsql; """) migrate_engine.execute(credential_update_trigger) + + error_message = ( + 'Identity provider migration in progress. Cannot ' + 'insert new rows into the identity_provider table at ' + 'this time.' + ) + identity_provider_insert_trigger = textwrap.dedent(f""" + CREATE OR REPLACE FUNCTION keystone_read_only_insert() + RETURNS trigger AS + $BODY$ + BEGIN + RAISE EXCEPTION '{error_message}'; + END + $BODY$ LANGUAGE plpgsql; + """) + migrate_engine.execute(identity_provider_insert_trigger) + + federated_user_insert_trigger = textwrap.dedent(""" + CREATE OR REPLACE FUNCTION update_federated_user_domain_id() + RETURNS trigger AS + $BODY$ + BEGIN + UPDATE "user" SET domain_id = ( + SELECT domain_id FROM identity_provider WHERE id = NEW.idp_id) + WHERE id = NEW.user_id and domain_id IS NULL; + RETURN NULL; + END + $BODY$ LANGUAGE plpgsql; + """) + migrate_engine.execute(federated_user_insert_trigger) + + local_user_insert_trigger = textwrap.dedent(""" + CREATE OR REPLACE FUNCTION update_user_domain_id() + RETURNS trigger AS + $BODY$ + BEGIN + UPDATE "user" SET domain_id = NEW.domain_id + WHERE id = NEW.user_id; + RETURN NULL; + END + $BODY$ LANGUAGE plpgsql; + """) + migrate_engine.execute(local_user_insert_trigger) diff --git a/keystone/common/sql/upgrades.py b/keystone/common/sql/upgrades.py index 2085e0a16..acdd08d86 100644 --- a/keystone/common/sql/upgrades.py +++ b/keystone/common/sql/upgrades.py @@ -29,7 +29,7 @@ from keystone.i18n import _ USE_TRIGGERS = True -INITIAL_VERSION = 3 +INITIAL_VERSION = 15 EXPAND_REPO = 'expand_repo' DATA_MIGRATION_REPO = 'data_migration_repo' CONTRACT_REPO = 'contract_repo' diff --git a/keystone/tests/unit/test_sql_upgrade.py b/keystone/tests/unit/test_sql_upgrade.py index f593aea88..8e3b822cb 100644 --- a/keystone/tests/unit/test_sql_upgrade.py +++ b/keystone/tests/unit/test_sql_upgrade.py @@ -41,7 +41,6 @@ For further information, see `oslo.db documentation import datetime import glob -import json import os import uuid @@ -112,7 +111,10 @@ INITIAL_TABLE_STRUCTURE = { ], 'user': [ 'id', 'extra', 'enabled', 'default_project_id', 'created_at', - 'last_active_at', + 'last_active_at', 'domain_id', + ], + 'user_option': [ + 'user_id', 'option_id', 'option_value', ], 'user_group_membership': [ 'user_id', 'group_id', @@ -136,7 +138,7 @@ INITIAL_TABLE_STRUCTURE = { 'id', 'policy_id', 'endpoint_id', 'service_id', 'region_id', ], 'identity_provider': [ - 'id', 'enabled', 'description', + 'id', 'enabled', 'description', 'domain_id', ], 'federation_protocol': [ 'id', 'idp_id', 'mapping_id', @@ -603,431 +605,6 @@ class FullMigration(MigrateBase, unit.TestCase): upgrades.INITIAL_VERSION + 2, ) - def test_migration_010_add_revocation_event_indexes(self): - self.expand(9) - self.migrate(9) - self.contract(9) - self.assertFalse(self.does_index_exist( - 'revocation_event', - 'ix_revocation_event_issued_before')) - self.assertFalse(self.does_index_exist( - 'revocation_event', - 'ix_revocation_event_project_id_issued_before')) - self.assertFalse(self.does_index_exist( - 'revocation_event', - 'ix_revocation_event_user_id_issued_before')) - self.assertFalse(self.does_index_exist( - 'revocation_event', - 'ix_revocation_event_audit_id_issued_before')) - self.expand(10) - self.migrate(10) - self.contract(10) - self.assertTrue(self.does_index_exist( - 'revocation_event', - 'ix_revocation_event_issued_before')) - self.assertTrue(self.does_index_exist( - 'revocation_event', - 'ix_revocation_event_project_id_issued_before')) - self.assertTrue(self.does_index_exist( - 'revocation_event', - 'ix_revocation_event_user_id_issued_before')) - self.assertTrue(self.does_index_exist( - 'revocation_event', - 'ix_revocation_event_audit_id_issued_before')) - - def test_migration_011_user_id_unique_for_nonlocal_user(self): - table_name = 'nonlocal_user' - column = 'user_id' - self.expand(10) - self.migrate(10) - self.contract(10) - self.assertFalse(self.does_unique_constraint_exist(table_name, column)) - self.expand(11) - self.migrate(11) - self.contract(11) - self.assertTrue(self.does_unique_constraint_exist(table_name, column)) - - def test_migration_012_add_domain_id_to_idp(self): - def _create_domain(): - domain_id = uuid.uuid4().hex - domain = { - 'id': domain_id, - 'name': domain_id, - 'enabled': True, - 'description': uuid.uuid4().hex, - 'domain_id': resource_base.NULL_DOMAIN_ID, - 'is_domain': True, - 'parent_id': None, - 'extra': '{}' - } - self.insert_dict(session, 'project', domain) - return domain_id - - def _get_new_idp(domain_id): - new_idp = {'id': uuid.uuid4().hex, - 'domain_id': domain_id, - 'enabled': True, - 'description': uuid.uuid4().hex} - return new_idp - - session = self.sessionmaker() - idp_name = 'identity_provider' - self.expand(11) - self.migrate(11) - self.contract(11) - self.assertTableColumns(idp_name, - ['id', - 'enabled', - 'description']) - # add some data - for i in range(5): - idp = {'id': uuid.uuid4().hex, - 'enabled': True, - 'description': uuid.uuid4().hex} - self.insert_dict(session, idp_name, idp) - - # upgrade - self.expand(12) - self.assertTableColumns(idp_name, - ['id', - 'domain_id', - 'enabled', - 'description']) - - # confirm we cannot insert an idp during expand - domain_id = _create_domain() - new_idp = _get_new_idp(domain_id) - self.assertRaises(db_exception.DBError, self.insert_dict, session, - idp_name, new_idp) - - # confirm we cannot insert an idp during migrate - self.migrate(12) - self.assertRaises(db_exception.DBError, self.insert_dict, session, - idp_name, new_idp) - - # confirm we can insert a new idp after contract - self.contract(12) - self.insert_dict(session, idp_name, new_idp) - - # confirm domain_id column is not null - idp_table = sqlalchemy.Table(idp_name, self.metadata, autoload=True) - self.assertFalse(idp_table.c.domain_id.nullable) - - def test_migration_013_protocol_cascade_delete_for_federated_user(self): - if self.engine.name == 'sqlite': - self.skipTest('sqlite backend does not support foreign keys') - - self.expand(12) - self.migrate(12) - self.contract(12) - - # This test requires a bit of setup to properly work, first we create - # an identity provider, mapping and a protocol. Then, we create a - # federated user and delete the protocol. We expect the federated user - # to be deleted as well. - - session = self.sessionmaker() - - def _create_protocol(): - domain = { - 'id': uuid.uuid4().hex, - 'name': uuid.uuid4().hex, - 'domain_id': resource_base.NULL_DOMAIN_ID, - 'is_domain': True, - 'parent_id': None - } - self.insert_dict(session, 'project', domain) - - idp = {'id': uuid.uuid4().hex, 'enabled': True, - 'domain_id': domain['id']} - self.insert_dict(session, 'identity_provider', idp) - - mapping = {'id': uuid.uuid4().hex, 'rules': json.dumps([])} - self.insert_dict(session, 'mapping', mapping) - - protocol = {'id': uuid.uuid4().hex, 'idp_id': idp['id'], - 'mapping_id': mapping['id']} - protocol_table = sqlalchemy.Table( - 'federation_protocol', self.metadata, autoload=True) - self.insert_dict(session, 'federation_protocol', protocol, - table=protocol_table) - - return protocol, protocol_table - - def _create_federated_user(idp_id, protocol_id): - user = {'id': uuid.uuid4().hex} - self.insert_dict(session, 'user', user) - - # NOTE(rodrigods): do not set the ID, the engine will do that - # for us and we won't need it later. - federated_user = { - 'user_id': user['id'], 'idp_id': idp_id, - 'protocol_id': protocol_id, 'unique_id': uuid.uuid4().hex} - federated_table = sqlalchemy.Table( - 'federated_user', self.metadata, autoload=True) - self.insert_dict(session, 'federated_user', federated_user, - table=federated_table) - - return federated_user, federated_table - - protocol, protocol_table = _create_protocol() - federated_user, federated_table = _create_federated_user( - protocol['idp_id'], protocol['id']) - - # before updating the foreign key, we won't be able to delete the - # protocol - self.assertRaises(db_exception.DBError, - session.execute, - protocol_table.delete().where( - protocol_table.c.id == protocol['id'])) - - self.expand(13) - self.migrate(13) - self.contract(13) - - # now we are able to delete the protocol - session.execute( - protocol_table.delete().where( - protocol_table.c.id == protocol['id'])) - - # assert the cascade deletion worked - federated_users = session.query(federated_table).filter_by( - protocol_id=federated_user['protocol_id']).all() - self.assertThat(federated_users, matchers.HasLength(0)) - - def test_migration_014_add_domain_id_to_user_table(self): - def create_domain(): - table = sqlalchemy.Table('project', self.metadata, autoload=True) - domain_id = uuid.uuid4().hex - domain = { - 'id': domain_id, - 'name': domain_id, - 'enabled': True, - 'description': uuid.uuid4().hex, - 'domain_id': resource_base.NULL_DOMAIN_ID, - 'is_domain': True, - 'parent_id': None, - 'extra': '{}' - } - table.insert().values(domain).execute() - return domain_id - - def create_user(table): - user_id = uuid.uuid4().hex - user = {'id': user_id, 'enabled': True} - table.insert().values(user).execute() - return user_id - - # insert local_user or nonlocal_user - def create_child_user(table, user_id, domain_id): - child_user = { - 'user_id': user_id, - 'domain_id': domain_id, - 'name': uuid.uuid4().hex - } - table.insert().values(child_user).execute() - - # update local_user or nonlocal_user - def update_child_user(table, user_id, new_domain_id): - table.update().where(table.c.user_id == user_id).values( - domain_id=new_domain_id).execute() - - def assertUserDomain(user_id, domain_id): - user = sqlalchemy.Table('user', self.metadata, autoload=True) - cols = [user.c.domain_id] - filter = user.c.id == user_id - sel = sqlalchemy.select(cols).where(filter) - domains = sel.execute().fetchone() - self.assertEqual(domain_id, domains[0]) - - user_table_name = 'user' - self.expand(13) - self.migrate(13) - self.contract(13) - self.assertTableColumns( - user_table_name, ['id', 'extra', 'enabled', 'default_project_id', - 'created_at', 'last_active_at']) - self.expand(14) - self.assertTableColumns( - user_table_name, ['id', 'extra', 'enabled', 'default_project_id', - 'created_at', 'last_active_at', 'domain_id']) - user_table = sqlalchemy.Table(user_table_name, self.metadata, - autoload=True) - local_user_table = sqlalchemy.Table('local_user', self.metadata, - autoload=True) - nonlocal_user_table = sqlalchemy.Table('nonlocal_user', self.metadata, - autoload=True) - - # add users before migrate to test that the user.domain_id gets updated - # after migrate - user_ids = [] - expected_domain_id = create_domain() - user_id = create_user(user_table) - create_child_user(local_user_table, user_id, expected_domain_id) - user_ids.append(user_id) - user_id = create_user(user_table) - create_child_user(nonlocal_user_table, user_id, expected_domain_id) - user_ids.append(user_id) - - self.migrate(14) - # test local_user insert trigger updates user.domain_id - user_id = create_user(user_table) - domain_id = create_domain() - create_child_user(local_user_table, user_id, domain_id) - assertUserDomain(user_id, domain_id) - - # test local_user update trigger updates user.domain_id - new_domain_id = create_domain() - update_child_user(local_user_table, user_id, new_domain_id) - assertUserDomain(user_id, new_domain_id) - - # test nonlocal_user insert trigger updates user.domain_id - user_id = create_user(user_table) - create_child_user(nonlocal_user_table, user_id, domain_id) - assertUserDomain(user_id, domain_id) - - # test nonlocal_user update trigger updates user.domain_id - update_child_user(nonlocal_user_table, user_id, new_domain_id) - assertUserDomain(user_id, new_domain_id) - - self.contract(14) - # test migrate updated the user.domain_id - for user_id in user_ids: - assertUserDomain(user_id, expected_domain_id) - - # test unique and fk constraints - if self.engine.name == 'mysql': - self.assertTrue( - self.does_index_exist('user', 'ixu_user_id_domain_id')) - else: - self.assertTrue( - self.does_constraint_exist('user', 'ixu_user_id_domain_id')) - self.assertTrue(self.does_fk_exist('local_user', 'user_id')) - self.assertTrue(self.does_fk_exist('local_user', 'domain_id')) - self.assertTrue(self.does_fk_exist('nonlocal_user', 'user_id')) - self.assertTrue(self.does_fk_exist('nonlocal_user', 'domain_id')) - - def test_migration_015_update_federated_user_domain(self): - def create_domain(): - table = sqlalchemy.Table('project', self.metadata, autoload=True) - domain_id = uuid.uuid4().hex - domain = { - 'id': domain_id, - 'name': domain_id, - 'enabled': True, - 'description': uuid.uuid4().hex, - 'domain_id': resource_base.NULL_DOMAIN_ID, - 'is_domain': True, - 'parent_id': None, - 'extra': '{}' - } - table.insert().values(domain).execute() - return domain_id - - def create_idp(domain_id): - table = sqlalchemy.Table('identity_provider', self.metadata, - autoload=True) - idp_id = uuid.uuid4().hex - idp = { - 'id': idp_id, - 'domain_id': domain_id, - 'enabled': True, - 'description': uuid.uuid4().hex - } - table.insert().values(idp).execute() - return idp_id - - def create_protocol(idp_id): - table = sqlalchemy.Table('federation_protocol', self.metadata, - autoload=True) - protocol_id = uuid.uuid4().hex - protocol = { - 'id': protocol_id, - 'idp_id': idp_id, - 'mapping_id': uuid.uuid4().hex - } - table.insert().values(protocol).execute() - return protocol_id - - def create_user(): - table = sqlalchemy.Table('user', self.metadata, autoload=True) - user_id = uuid.uuid4().hex - user = {'id': user_id, 'enabled': True} - table.insert().values(user).execute() - return user_id - - def create_federated_user(user_id, idp_id, protocol_id): - table = sqlalchemy.Table('federated_user', self.metadata, - autoload=True) - federated_user = { - 'user_id': user_id, - 'idp_id': idp_id, - 'protocol_id': protocol_id, - 'unique_id': uuid.uuid4().hex, - 'display_name': uuid.uuid4().hex - } - table.insert().values(federated_user).execute() - - def assertUserDomain(user_id, domain_id): - table = sqlalchemy.Table('user', self.metadata, autoload=True) - where = table.c.id == user_id - stmt = sqlalchemy.select([table.c.domain_id]).where(where) - domains = stmt.execute().fetchone() - self.assertEqual(domain_id, domains[0]) - - def assertUserDomainIsNone(user_id): - table = sqlalchemy.Table('user', self.metadata, autoload=True) - where = table.c.id == user_id - stmt = sqlalchemy.select([table.c.domain_id]).where(where) - domains = stmt.execute().fetchone() - self.assertIsNone(domains[0]) - - self.expand(14) - self.migrate(14) - self.contract(14) - - domain_id = create_domain() - idp_id = create_idp(domain_id) - protocol_id = create_protocol(idp_id) - - # create user before expand to test data migration - user_id_before_expand = create_user() - create_federated_user(user_id_before_expand, idp_id, protocol_id) - assertUserDomainIsNone(user_id_before_expand) - - self.expand(15) - # create user before migrate to test insert trigger - user_id_before_migrate = create_user() - create_federated_user(user_id_before_migrate, idp_id, protocol_id) - assertUserDomain(user_id_before_migrate, domain_id) - - self.migrate(15) - # test insert trigger after migrate - user_id = create_user() - create_federated_user(user_id, idp_id, protocol_id) - assertUserDomain(user_id, domain_id) - - self.contract(15) - # test migrate updated the user.domain_id - assertUserDomain(user_id_before_expand, domain_id) - - # verify that the user.domain_id is now not nullable - user_table = sqlalchemy.Table('user', self.metadata, autoload=True) - self.assertFalse(user_table.c.domain_id.nullable) - - def test_migration_016_add_user_options(self): - self.expand(15) - self.migrate(15) - self.contract(15) - - user_option = 'user_option' - self.assertTableDoesNotExist(user_option) - self.expand(16) - self.migrate(16) - self.contract(16) - self.assertTableColumns(user_option, - ['user_id', 'option_id', 'option_value']) - def test_migration_024_add_created_expires_at_int_columns_password(self): self.expand(23) @@ -2181,10 +1758,6 @@ class FullMigration(MigrateBase, unit.TestCase): class MySQLOpportunisticFullMigration(FullMigration): FIXTURE = db_fixtures.MySQLOpportunisticFixture - def test_migration_012_add_domain_id_to_idp(self): - self.skip_test_overrides('skipped to update u-c for PyMySql version' - 'to 0.10.0') - class PostgreSQLOpportunisticFullMigration(FullMigration): FIXTURE = db_fixtures.PostgresqlOpportunisticFixture |