summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/admin/bootstrap.rst10
-rw-r--r--doc/source/admin/unified-limits.rst2
-rw-r--r--doc/source/conf.py26
-rw-r--r--doc/source/contributor/api_change_tutorial.rst13
-rw-r--r--doc/source/contributor/database-migrations.rst21
-rw-r--r--doc/source/contributor/programming-exercises.rst6
-rw-r--r--doc/source/contributor/testing-keystone.rst12
-rw-r--r--keystone/cmd/cli.py178
-rw-r--r--keystone/common/sql/alembic.ini100
-rw-r--r--keystone/common/sql/contract_repo/README4
-rw-r--r--keystone/common/sql/contract_repo/versions/002_password_created_at_not_nullable.py39
-rw-r--r--keystone/common/sql/contract_repo/versions/003_remove_unencrypted_blob_column_from_credential.py60
-rw-r--r--keystone/common/sql/contract_repo/versions/004_reset_password_created_at.py37
-rw-r--r--keystone/common/sql/contract_repo/versions/005_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/006_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/007_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/008_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/009_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/010_contract_add_revocation_event_index.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/011_contract_user_id_unique_for_nonlocal_user.py23
-rw-r--r--keystone/common/sql/contract_repo/versions/012_contract_add_domain_id_to_idp.py38
-rw-r--r--keystone/common/sql/contract_repo/versions/013_contract_protocol_cascade_delete_for_federated_user.py31
-rw-r--r--keystone/common/sql/contract_repo/versions/014_contract_add_domain_id_to_user_table.py94
-rw-r--r--keystone/common/sql/contract_repo/versions/015_contract_update_federated_user_domain.py34
-rw-r--r--keystone/common/sql/contract_repo/versions/016_contract_add_user_options.py16
-rw-r--r--keystone/common/sql/contract_repo/versions/017_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/018_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/019_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/020_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/021_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/022_contract_add_default_project_id_index.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/023_contract_add_second_password_column_for_expanded_hash_sizes.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/024_contract_create_created_at_int_columns.py61
-rw-r--r--keystone/common/sql/contract_repo/versions/025_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/026_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/027_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/028_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/029_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/030_contract_add_project_tags_table.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/031_contract_system_assignment_table.py16
-rw-r--r--keystone/common/sql/contract_repo/versions/032_contract_add_expired_at_int_to_trust.py51
-rw-r--r--keystone/common/sql/contract_repo/versions/033_contract_add_limits_tables.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/034_contract_add_application_credentials_table.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/035_contract_add_system_column_to_application_credential_table.py23
-rw-r--r--keystone/common/sql/contract_repo/versions/036_contract_rename_application_credential_restriction_column.py40
-rw-r--r--keystone/common/sql/contract_repo/versions/037_contract_remove_service_and_region_fk_for_registered_limit.py36
-rw-r--r--keystone/common/sql/contract_repo/versions/038_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/039_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/040_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/041_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/042_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/043_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/044_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/045_contract_add_description_to_limit.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/046_contract_old_password_data_to_password_hash_column.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/047_contract_expand_update_pk_for_unified_limit.py63
-rw-r--r--keystone/common/sql/contract_repo/versions/048_contract_add_registered_limit_id_column_for_limit.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/049_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/050_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/051_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/052_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/053_contract_add_role_description_to_role_table.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/054_contract_drop_old_passoword_column.py21
-rw-r--r--keystone/common/sql/contract_repo/versions/055_contract_add_domain_to_limit.py21
-rw-r--r--keystone/common/sql/contract_repo/versions/056_contract_add_application_credential_access_rules.py17
-rw-r--r--keystone/common/sql/contract_repo/versions/057_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/058_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/059_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/060_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/061_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/062_contract_extract_redelegation_data_from_extras.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/063_contract_drop_limit_columns.py23
-rw-r--r--keystone/common/sql/contract_repo/versions/064_contract_add_remote_id_attribute_to_federation_protocol_table.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/065_contract_add_user_external_id_to_access_rule.py15
-rw-r--r--keystone/common/sql/contract_repo/versions/066_contract_add_resource_options_table.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/067_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/068_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/069_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/070_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/071_placeholder.py18
-rw-r--r--keystone/common/sql/contract_repo/versions/072_contract_drop_domain_id_fk.py47
-rw-r--r--keystone/common/sql/contract_repo/versions/073_contract_expiring_group_membership.py15
-rw-r--r--keystone/common/sql/data_migration_repo/README4
-rw-r--r--keystone/common/sql/data_migration_repo/versions/002_password_created_at_not_nullable.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/003_migrate_unencrypted_credentials.py39
-rw-r--r--keystone/common/sql/data_migration_repo/versions/004_reset_password_created_at.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/005_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/006_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/007_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/008_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/009_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/010_migrate_add_revocation_event_index.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/011_expand_user_id_unique_for_nonlocal_user.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/012_migrate_add_domain_id_to_idp.py55
-rw-r--r--keystone/common/sql/data_migration_repo/versions/013_migrate_protocol_cascade_delete_for_federated_user.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/014_migrate_add_domain_id_to_user_table.py45
-rw-r--r--keystone/common/sql/data_migration_repo/versions/015_migrate_update_federated_user_domain.py36
-rw-r--r--keystone/common/sql/data_migration_repo/versions/016_migrate_add_user_options.py16
-rw-r--r--keystone/common/sql/data_migration_repo/versions/017_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/018_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/019_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/020_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/021_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/022_migrate_add_default_project_id_index.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/023_migrate_add_second_password_column_for_expanded_hash_sizes.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/024_migrate_create_created_at_int_columns.py22
-rw-r--r--keystone/common/sql/data_migration_repo/versions/025_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/026_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/027_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/028_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/029_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/030_migrate_add_project_tags_table.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/031_migrate_system_assignment_table.py17
-rw-r--r--keystone/common/sql/data_migration_repo/versions/032_migrate_add_expired_at_int_to_trust.py22
-rw-r--r--keystone/common/sql/data_migration_repo/versions/033_migrate_add_limits_tables.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/034_migrate_add_application_credentials_table.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/035_migrate_add_system_column_to_application_credential_table.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/036_migrate_rename_application_credential_restriction_column.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/037_migrate_remove_service_and_region_fk_for_registered_limit.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/038_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/039_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/040_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/041_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/042_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/043_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/044_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/045_migrate_add_description_to_limit.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/046_migrate_old_password_data_to_password_hash_column.py26
-rw-r--r--keystone/common/sql/data_migration_repo/versions/047_migrate_update_pk_for_unified_limit.py37
-rw-r--r--keystone/common/sql/data_migration_repo/versions/048_migrate_add_registered_limit_id_column_for_limit.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/049_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/050_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/051_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/052_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/053_migrate_add_role_description_to_role_table.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/054_migrate_drop_old_passoword_column.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/055_migrate_add_domain_to_limit.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/056_migrate_add_application_credential_access_rules.py17
-rw-r--r--keystone/common/sql/data_migration_repo/versions/057_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/058_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/059_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/060_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/061_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/062_migrate_extract_redelegation_data_from_extras.py43
-rw-r--r--keystone/common/sql/data_migration_repo/versions/063_migrate_drop_limit_columns.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/064_migrate_add_remote_id_attribute_to_federation_protocol_table.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/065_migrate_add_user_external_id_to_access_rule.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/066_migrate_add_resource_options_table.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/067_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/068_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/069_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/070_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/071_placeholder.py18
-rw-r--r--keystone/common/sql/data_migration_repo/versions/072_migrate_drop_domain_id_fk.py20
-rw-r--r--keystone/common/sql/data_migration_repo/versions/073_migrate_expiring_group_membership.py15
-rw-r--r--keystone/common/sql/expand_repo/README4
-rw-r--r--keystone/common/sql/expand_repo/versions/002_password_created_at_not_nullable.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/003_add_key_hash_and_encrypted_blob_to_credential.py129
-rw-r--r--keystone/common/sql/expand_repo/versions/004_reset_password_created_at.py15
-rw-r--r--keystone/common/sql/expand_repo/versions/005_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/006_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/007_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/008_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/009_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/010_expand_add_revocation_event_index.py31
-rw-r--r--keystone/common/sql/expand_repo/versions/011_expand_user_id_unique_for_nonlocal_user.py15
-rw-r--r--keystone/common/sql/expand_repo/versions/012_expand_add_domain_id_to_idp.py73
-rw-r--r--keystone/common/sql/expand_repo/versions/013_expand_protocol_cascade_delete_for_federated_user.py15
-rw-r--r--keystone/common/sql/expand_repo/versions/014_expand_add_domain_id_to_user_table.py165
-rw-r--r--keystone/common/sql/expand_repo/versions/015_expand_update_federated_user_domain.py69
-rw-r--r--keystone/common/sql/expand_repo/versions/016_expand_add_user_options.py34
-rw-r--r--keystone/common/sql/expand_repo/versions/017_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/018_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/019_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/020_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/021_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/022_expand_add_default_project_id_index.py21
-rw-r--r--keystone/common/sql/expand_repo/versions/023_expand_add_second_password_column_for_expanded_hash_sizes.py25
-rw-r--r--keystone/common/sql/expand_repo/versions/024_expand_create_created_at_int_columns.py33
-rw-r--r--keystone/common/sql/expand_repo/versions/025_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/026_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/027_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/028_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/029_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/030_expand_add_project_tags_table.py44
-rw-r--r--keystone/common/sql/expand_repo/versions/031_expand_system_assignment_table.py33
-rw-r--r--keystone/common/sql/expand_repo/versions/032_expand_add_expired_at_int_to_trust.py35
-rw-r--r--keystone/common/sql/expand_repo/versions/033_expand_add_limits_tables.py68
-rw-r--r--keystone/common/sql/expand_repo/versions/034_expand_add_application_credential_table.py52
-rw-r--r--keystone/common/sql/expand_repo/versions/036_expand_rename_application_credential_restriction_column.py44
-rw-r--r--keystone/common/sql/expand_repo/versions/037_expand_remove_service_and_region_fk_for_registered_limit.py15
-rw-r--r--keystone/common/sql/expand_repo/versions/038_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/039_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/040_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/041_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/042_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/043_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/044_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/045_expand_add_description_to_limit.py29
-rw-r--r--keystone/common/sql/expand_repo/versions/046_expand_old_password_data_to_password_hash_column.py15
-rw-r--r--keystone/common/sql/expand_repo/versions/047_expand_update_pk_for_unified_limit.py103
-rw-r--r--keystone/common/sql/expand_repo/versions/048_expand_add_registered_limit_id_column_for_limit.py40
-rw-r--r--keystone/common/sql/expand_repo/versions/049_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/050_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/051_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/052_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/053_expand_add_role_description_to_role_table.py23
-rw-r--r--keystone/common/sql/expand_repo/versions/054_expand_drop_old_passoword_column.py15
-rw-r--r--keystone/common/sql/expand_repo/versions/055_expand_add_domain_to_limit.py34
-rw-r--r--keystone/common/sql/expand_repo/versions/056_expand_add_application_credential_access_rules.py45
-rw-r--r--keystone/common/sql/expand_repo/versions/057_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/058_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/059_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/060_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/061_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/062_expand_extract_redelegation_data_from_extras.py31
-rw-r--r--keystone/common/sql/expand_repo/versions/063_expand_drop_limit_columns.py15
-rw-r--r--keystone/common/sql/expand_repo/versions/064_expand_add_remote_id_attribute_to_federation_protocol_table.py23
-rw-r--r--keystone/common/sql/expand_repo/versions/065_expand_add_user_external_id_to_access_rule.py39
-rw-r--r--keystone/common/sql/expand_repo/versions/066_expand_add_role_and_project_option_tables.py51
-rw-r--r--keystone/common/sql/expand_repo/versions/067_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/068_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/069_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/070_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/071_placeholder.py18
-rw-r--r--keystone/common/sql/expand_repo/versions/072_expand_drop_domain_id_fk.py20
-rw-r--r--keystone/common/sql/expand_repo/versions/073_expand_expiring_group_membership.py47
-rw-r--r--keystone/common/sql/legacy_migrations/__init__.py (renamed from keystone/common/sql/contract_repo/__init__.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/README.rst13
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/__init__.py (renamed from keystone/common/sql/contract_repo/versions/__init__.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/manage.py (renamed from keystone/common/sql/contract_repo/manage.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/migrate.cfg (renamed from keystone/common/sql/contract_repo/migrate.cfg)0
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/versions/073_contract_initial_migration.py (renamed from keystone/common/sql/contract_repo/versions/001_contract_initial_null_migration.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/versions/074_placeholder.py (renamed from keystone/common/sql/contract_repo/versions/074_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/versions/075_placeholder.py (renamed from keystone/common/sql/contract_repo/versions/075_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/versions/076_placeholder.py (renamed from keystone/common/sql/contract_repo/versions/076_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/versions/077_placeholder.py (renamed from keystone/common/sql/contract_repo/versions/077_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/versions/078_placeholder.py (renamed from keystone/common/sql/contract_repo/versions/078_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/versions/079_contract_update_local_id_limit.py (renamed from keystone/common/sql/contract_repo/versions/079_contract_update_local_id_limit.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/contract_repo/versions/__init__.py (renamed from keystone/common/sql/data_migration_repo/__init__.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/README.rst13
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/__init__.py (renamed from keystone/common/sql/data_migration_repo/versions/__init__.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/manage.py (renamed from keystone/common/sql/data_migration_repo/manage.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/migrate.cfg (renamed from keystone/common/sql/data_migration_repo/migrate.cfg)0
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/versions/073_migrate_initial_migration.py (renamed from keystone/common/sql/migrate_repo/versions/089_add_root_of_all_domains.py)34
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/versions/074_placeholder.py (renamed from keystone/common/sql/data_migration_repo/versions/074_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/versions/075_placeholder.py (renamed from keystone/common/sql/data_migration_repo/versions/075_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/versions/076_placeholder.py (renamed from keystone/common/sql/data_migration_repo/versions/076_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/versions/077_placeholder.py (renamed from keystone/common/sql/data_migration_repo/versions/077_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/versions/078_placeholder.py (renamed from keystone/common/sql/data_migration_repo/versions/078_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/versions/079_migrate_update_local_id_limit.py (renamed from keystone/common/sql/data_migration_repo/versions/079_migrate_update_local_id_limit.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/data_migration_repo/versions/__init__.py (renamed from keystone/common/sql/migrate_repo/__init__.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/README.rst13
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/__init__.py (renamed from keystone/common/sql/expand_repo/__init__.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/manage.py (renamed from keystone/common/sql/expand_repo/manage.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/migrate.cfg (renamed from keystone/common/sql/expand_repo/migrate.cfg)0
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/versions/073_expand_initial_migration.py1183
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/versions/074_placeholder.py (renamed from keystone/common/sql/expand_repo/versions/074_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/versions/075_placeholder.py (renamed from keystone/common/sql/expand_repo/versions/075_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/versions/076_placeholder.py (renamed from keystone/common/sql/expand_repo/versions/076_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/versions/077_placeholder.py (renamed from keystone/common/sql/expand_repo/versions/077_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/versions/078_placeholder.py (renamed from keystone/common/sql/expand_repo/versions/078_placeholder.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/versions/079_expand_update_local_id_limit.py (renamed from keystone/common/sql/expand_repo/versions/079_expand_update_local_id_limit.py)0
-rw-r--r--keystone/common/sql/legacy_migrations/expand_repo/versions/__init__.py (renamed from keystone/common/sql/expand_repo/versions/__init__.py)0
-rw-r--r--keystone/common/sql/migrate_repo/README4
-rw-r--r--keystone/common/sql/migrate_repo/manage.py18
-rw-r--r--keystone/common/sql/migrate_repo/migrate.cfg25
-rw-r--r--keystone/common/sql/migrate_repo/versions/067_kilo.py317
-rw-r--r--keystone/common/sql/migrate_repo/versions/068_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/069_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/070_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/071_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/072_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/073_insert_assignment_inherited_pk.py113
-rw-r--r--keystone/common/sql/migrate_repo/versions/074_add_is_domain_project.py27
-rw-r--r--keystone/common/sql/migrate_repo/versions/075_confirm_config_registration.py29
-rw-r--r--keystone/common/sql/migrate_repo/versions/076_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/077_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/078_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/079_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/080_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/081_add_endpoint_policy_table.py54
-rw-r--r--keystone/common/sql/migrate_repo/versions/082_add_federation_tables.py97
-rw-r--r--keystone/common/sql/migrate_repo/versions/083_add_oauth1_tables.py75
-rw-r--r--keystone/common/sql/migrate_repo/versions/084_add_revoke_tables.py55
-rw-r--r--keystone/common/sql/migrate_repo/versions/085_add_endpoint_filtering_table.py70
-rw-r--r--keystone/common/sql/migrate_repo/versions/086_add_duplicate_constraint_trusts.py26
-rw-r--r--keystone/common/sql/migrate_repo/versions/087_implied_roles.py43
-rw-r--r--keystone/common/sql/migrate_repo/versions/088_domain_specific_roles.py60
-rw-r--r--keystone/common/sql/migrate_repo/versions/090_add_local_user_and_password_tables.py42
-rw-r--r--keystone/common/sql/migrate_repo/versions/091_migrate_data_to_local_user_and_password_tables.py84
-rw-r--r--keystone/common/sql/migrate_repo/versions/092_make_implied_roles_fks_cascaded.py46
-rw-r--r--keystone/common/sql/migrate_repo/versions/093_migrate_domains_to_projects.py125
-rw-r--r--keystone/common/sql/migrate_repo/versions/094_add_federated_user_table.py45
-rw-r--r--keystone/common/sql/migrate_repo/versions/095_add_integer_pkey_to_revocation_event_table.py62
-rw-r--r--keystone/common/sql/migrate_repo/versions/096_drop_role_name_constraint.py50
-rw-r--r--keystone/common/sql/migrate_repo/versions/097_drop_user_name_domainid_constraint.py67
-rw-r--r--keystone/common/sql/migrate_repo/versions/098_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/099_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/100_placeholder.py18
-rw-r--r--keystone/common/sql/migrate_repo/versions/101_drop_role_name_constraint.py53
-rw-r--r--keystone/common/sql/migrate_repo/versions/102_drop_domain_table.py21
-rw-r--r--keystone/common/sql/migrate_repo/versions/103_add_nonlocal_user_table.py32
-rw-r--r--keystone/common/sql/migrate_repo/versions/104_drop_user_name_domainid_constraint.py71
-rw-r--r--keystone/common/sql/migrate_repo/versions/105_add_password_date_columns.py30
-rw-r--r--keystone/common/sql/migrate_repo/versions/106_allow_password_column_to_be_nullable.py21
-rw-r--r--keystone/common/sql/migrate_repo/versions/107_add_user_date_columns.py30
-rw-r--r--keystone/common/sql/migrate_repo/versions/108_add_failed_auth_columns.py26
-rw-r--r--keystone/common/sql/migrate_repo/versions/109_add_password_self_service_column.py24
-rw-r--r--keystone/common/sql/migrate_repo/versions/__init__.py0
-rw-r--r--keystone/common/sql/migrations/README.rst15
-rw-r--r--keystone/common/sql/migrations/env.py80
-rw-r--r--keystone/common/sql/migrations/script.py.mako (renamed from keystone/common/sql/expand_repo/versions/035_expand_add_system_column_to_application_credential_table.py)27
-rw-r--r--keystone/common/sql/migrations/versions/27e647c0fad4_initial_version.py1106
-rw-r--r--keystone/common/sql/migrations/versions/CONTRACT_HEAD1
-rw-r--r--keystone/common/sql/migrations/versions/EXPAND_HEAD1
-rw-r--r--keystone/common/sql/migrations/versions/yoga/contract/e25ffa003242_initial.py (renamed from keystone/common/sql/expand_repo/versions/001_expand_initial_null_migration.py)17
-rw-r--r--keystone/common/sql/migrations/versions/yoga/expand/29e87d24a316_initial.py (renamed from keystone/common/sql/data_migration_repo/versions/001_data_initial_null_migration.py)17
-rw-r--r--keystone/common/sql/upgrades.py372
-rw-r--r--keystone/common/utils.py7
-rw-r--r--keystone/conf/ldap.py8
-rw-r--r--keystone/federation/idp.py12
-rw-r--r--keystone/identity/backends/ldap/common.py19
-rw-r--r--keystone/tests/unit/common/sql/test_upgrades.py252
-rw-r--r--keystone/tests/unit/core.py15
-rw-r--r--keystone/tests/unit/ksfixtures/__init__.py2
-rw-r--r--keystone/tests/unit/ksfixtures/logging.py114
-rw-r--r--keystone/tests/unit/ksfixtures/warnings.py62
-rw-r--r--keystone/tests/unit/test_cli.py12
-rw-r--r--keystone/tests/unit/test_policy.py6
-rw-r--r--keystone/tests/unit/test_sql_banned_operations.py96
-rw-r--r--keystone/tests/unit/test_sql_upgrade.py3408
-rw-r--r--lower-constraints.txt2
-rw-r--r--releasenotes/notes/change_min_pool_retry_max-f5e7c8d315401426.yaml6
-rw-r--r--releasenotes/notes/remove-db_sync-extension-opt-2ab1f29340281215.yaml6
-rw-r--r--releasenotes/notes/remove-legacy-migrations-647f60019c8dd9e8.yaml7
-rw-r--r--requirements.txt2
-rwxr-xr-xtools/generate-schemas134
-rw-r--r--tox.ini44
339 files changed, 3800 insertions, 10932 deletions
diff --git a/doc/source/admin/bootstrap.rst b/doc/source/admin/bootstrap.rst
index 51142b370..888ab6112 100644
--- a/doc/source/admin/bootstrap.rst
+++ b/doc/source/admin/bootstrap.rst
@@ -73,10 +73,12 @@ Verbosely, keystone can be bootstrapped with:
--bootstrap-internal-url http://localhost:5000
This will create an ``admin`` user with the ``admin`` role on the ``admin``
-project. The user will have the password specified in the command. Note that
-both the user and the project will be created in the ``default`` domain. By not
-creating an endpoint in the catalog users will need to provide endpoint
-overrides to perform additional identity operations.
+project and the system. This allows the user to generate project-scoped and
+system-scoped tokens which ensures they have full RBAC authorization. The user
+will have the password specified in the command. Note that both the user and
+the project will be created in the ``default`` domain. By not creating an
+endpoint in the catalog users will need to provide endpoint overrides to
+perform additional identity operations.
This command will also create ``member`` and ``reader`` roles. The ``admin``
role implies the ``member`` role and ``member`` role implies the ``reader``
diff --git a/doc/source/admin/unified-limits.rst b/doc/source/admin/unified-limits.rst
index 1a37a4c5a..1d4498647 100644
--- a/doc/source/admin/unified-limits.rst
+++ b/doc/source/admin/unified-limits.rst
@@ -154,7 +154,7 @@ recommend extremely careful planning and understanding of various enforcement
models if you're planning on switching from one model to another in a
deployment.
-Keystone exposes a ``GET /limits-model`` endpoint that returns the enforcement
+Keystone exposes a ``GET /limits/model`` endpoint that returns the enforcement
model selected by the deployment. This allows limit information to be
discoverable and preserves interoperability between OpenStack deployments with
different enforcement models.
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 45cd82f0e..41a245632 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -32,18 +32,20 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
-extensions = ['sphinx.ext.coverage',
- 'sphinx.ext.viewcode',
- 'oslo_config.sphinxconfiggen',
- 'oslo_config.sphinxext',
- 'oslo_policy.sphinxpolicygen',
- 'openstackdocstheme',
- 'oslo_policy.sphinxext',
- 'sphinxcontrib.apidoc',
- 'sphinxcontrib.seqdiag',
- 'sphinx_feature_classification.support_matrix',
- 'sphinxcontrib.blockdiag'
- ]
+extensions = [
+ 'sphinx.ext.coverage',
+ 'sphinx.ext.viewcode',
+ 'sphinx.ext.todo',
+ 'oslo_config.sphinxconfiggen',
+ 'oslo_config.sphinxext',
+ 'oslo_policy.sphinxpolicygen',
+ 'openstackdocstheme',
+ 'oslo_policy.sphinxext',
+ 'sphinxcontrib.apidoc',
+ 'sphinxcontrib.seqdiag',
+ 'sphinx_feature_classification.support_matrix',
+ 'sphinxcontrib.blockdiag'
+]
blockdiag_html_image_format = 'SVG'
diff --git a/doc/source/contributor/api_change_tutorial.rst b/doc/source/contributor/api_change_tutorial.rst
index 90ef8a33b..dc63de433 100644
--- a/doc/source/contributor/api_change_tutorial.rst
+++ b/doc/source/contributor/api_change_tutorial.rst
@@ -87,6 +87,19 @@ files, respectively (currently only the SQL driver is supported).
Changing the SQL Model and Driver
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. note::
+
+ The below guidance is out-of-date and refers to the legacy ``migrate_repo``
+ migration repository, which was removed in 21.0.0 (Yoga). Nowadays, for a
+ change like this, you would create an additive or "expand" migration in the
+ ``expand_repo`` repository along with null migrations in the
+ ``contract_repo`` and ``data_migration_repo`` repositories. For more
+ information, refer to :doc:`/contributor/database-migrations`.
+
+.. todo::
+
+ Update this section to reflect the new migration model.
+
First, you need to change the role model to include the description attribute.
Go to `keystone/assignment/role_backends/sql.py` and update it like::
diff --git a/doc/source/contributor/database-migrations.rst b/doc/source/contributor/database-migrations.rst
index 09b1e8e3d..3827ea8e6 100644
--- a/doc/source/contributor/database-migrations.rst
+++ b/doc/source/contributor/database-migrations.rst
@@ -17,10 +17,17 @@
Database Migrations
===================
+.. note::
+
+ The framework being used is currently being migrated from
+ SQLAlchemy-Migrate to Alembic, meaning this information will change in the
+ near-term.
+
Starting with Newton, keystone supports upgrading both with and without
downtime. In order to support this, there are three separate migration
-repositories (all under ``keystone/common/sql/``) that match the three phases
-of an upgrade (schema expansion, data migration, and schema contraction):
+repositories (all under ``keystone/common/sql/legacy_migrations``) that match
+the three phases of an upgrade (schema expansion, data migration, and schema
+contraction):
``expand_repo``
For additive schema modifications and triggers to ensure data is kept in
@@ -43,14 +50,6 @@ do in a specific phase, then include a no-op migration to simply ``pass`` (in
fact the ``001`` migration in each of these repositories is a no-op migration,
so that can be used as a template).
-.. NOTE::
-
- Since rolling upgrade support was added part way through the Newton cycle,
- some migrations had already been added to the legacy repository
- (``keystone/common/sql/migrate_repo``). This repository is now closed and
- no new migrations should be added (except for backporting of previous
- placeholders).
-
In order to support rolling upgrades, where two releases of keystone briefly
operate side-by-side using the same database without downtime, each phase of
the migration must adhere to following constraints:
@@ -79,7 +78,7 @@ Data Migration phase:
No schema changes are allowed.
Contract phase:
- Only contractive schema changes are allowed, such as dropping or altering
+ Only destructive schema changes are allowed, such as dropping or altering
columns, tables, indices, and triggers.
Data insertion, modification, and removal is not allowed.
diff --git a/doc/source/contributor/programming-exercises.rst b/doc/source/contributor/programming-exercises.rst
index 5af344467..b51725d08 100644
--- a/doc/source/contributor/programming-exercises.rst
+++ b/doc/source/contributor/programming-exercises.rst
@@ -53,9 +53,9 @@ Refer to the :doc:`API Change tutorial <api_change_tutorial>`. In short, you wil
steps:
#. Create a SQL migration to add the parameter to the database table
- (:py:mod:`keystone.common.sql.expand_repo.versions`,
- :py:mod:`keystone.common.sql.data_migration_repo.versions`,
- :py:mod:`keystone.common.sql.contract_repo.versions`)
+ (:py:mod:`keystone.common.sql.legacy_migration.expand_repo.versions`,
+ :py:mod:`keystone.common.sql.legacy_migration.data_migration_repo.versions`,
+ :py:mod:`keystone.common.sql.legacy_migration.contract_repo.versions`)
#. Add a SQL migration unit test (`keystone/tests/unit/test_sql_upgrade.py`)
diff --git a/doc/source/contributor/testing-keystone.rst b/doc/source/contributor/testing-keystone.rst
index 4f4bbd226..72575fbcb 100644
--- a/doc/source/contributor/testing-keystone.rst
+++ b/doc/source/contributor/testing-keystone.rst
@@ -138,6 +138,12 @@ Identity module.
Testing Schema Migrations
-------------------------
+.. note::
+
+ The framework being used is currently being migrated from
+ SQLAlchemy-Migrate to Alembic, meaning this information will change in the
+ near-term.
+
The application of schema migrations can be tested using SQLAlchemy Migrate's
built-in test runner, one migration at a time.
@@ -151,9 +157,9 @@ version control:
.. code-block:: bash
- $ python keystone/common/sql/migrate_repo/manage.py test \
- --url=sqlite:///test.db \
- --repository=keystone/common/sql/migrate_repo/
+ $ python keystone/common/sql/legacy_migrations/expand_repo/manage.py test \
+ --url=sqlite:///test.db \
+ --repository=keystone/common/sql/legacy_migrations/expand_repo/
This command references to a SQLite database (test.db) to be used. Depending on
the migration, this command alone does not make assertions as to the integrity
diff --git a/keystone/cmd/cli.py b/keystone/cmd/cli.py
index 6cd10cfb6..1e866d76a 100644
--- a/keystone/cmd/cli.py
+++ b/keystone/cmd/cli.py
@@ -18,9 +18,8 @@ import os
import sys
import uuid
-import migrate
from oslo_config import cfg
-from oslo_db.sqlalchemy import migration
+from oslo_db import exception as db_exception
from oslo_log import log
from oslo_serialization import jsonutils
import pbr.version
@@ -211,15 +210,6 @@ class Doctor(BaseApp):
raise SystemExit(doctor.diagnose())
-def assert_not_extension(extension):
- if extension:
- print(_("All extensions have been moved into keystone core and as "
- "such its migrations are maintained by the main keystone "
- "database control. Use the command: keystone-manage "
- "db_sync"))
- raise RuntimeError
-
-
class DbSync(BaseApp):
"""Sync the database."""
@@ -228,73 +218,91 @@ class DbSync(BaseApp):
@classmethod
def add_argument_parser(cls, subparsers):
parser = super(DbSync, cls).add_argument_parser(subparsers)
- parser.add_argument('version', default=None, nargs='?',
- help=('Migrate the database up to a specified '
- 'version. If not provided, db_sync will '
- 'migrate the database to the latest known '
- 'version. Schema downgrades are not '
- 'supported.'))
- parser.add_argument('--extension', default=None,
- help=('This is a deprecated option to migrate a '
- 'specified extension. Since extensions are '
- 'now part of the main repository, '
- 'specifying db_sync without this option '
- 'will cause all extensions to be migrated.'))
+ parser.add_argument(
+ 'version',
+ default=None,
+ nargs='?',
+ help=(
+ 'Migrate the database up to a specified version. '
+ 'If not provided, db_sync will migrate the database to the '
+ 'latest known version. '
+ 'Schema downgrades are not supported.'
+ ),
+ )
group = parser.add_mutually_exclusive_group()
- group.add_argument('--expand', default=False, action='store_true',
- help=('Expand the database schema in preparation '
- 'for data migration.'))
- group.add_argument('--migrate', default=False,
- action='store_true',
- help=('Copy all data that needs to be migrated '
- 'within the database ahead of starting the '
- 'first keystone node upgraded to the new '
- 'release. This command should be run '
- 'after the --expand command. Once the '
- '--migrate command has completed, you can '
- 'upgrade all your keystone nodes to the new '
- 'release and restart them.'))
-
- group.add_argument('--contract', default=False, action='store_true',
- help=('Remove any database tables and columns '
- 'that are no longer required. This command '
- 'should be run after all keystone nodes are '
- 'running the new release.'))
-
- group.add_argument('--check', default=False, action='store_true',
- help=('Check for outstanding database actions that '
- 'still need to be executed. This command can '
- 'be used to verify the condition of the '
- 'current database state.'))
+ group.add_argument(
+ '--expand',
+ default=False,
+ action='store_true',
+ help=(
+ 'Expand the database schema in preparation for data migration.'
+ ),
+ )
+ group.add_argument(
+ '--migrate',
+ default=False,
+ action='store_true',
+ help=(
+ 'Copy all data that needs to be migrated within the database '
+ 'ahead of starting the first keystone node upgraded to the '
+ 'new release. '
+ 'This command should be run after the --expand command. '
+ 'Once the --migrate command has completed, you can upgrade '
+ 'all your keystone nodes to the new release and restart them.'
+ ),
+ )
+ group.add_argument(
+ '--contract',
+ default=False,
+ action='store_true',
+ help=(
+ 'Remove any database tables and columns that are no longer '
+ 'required. This command should be run after all keystone '
+ 'nodes are running the new release.'
+ ),
+ )
+ group.add_argument(
+ '--check',
+ default=False,
+ action='store_true',
+ help=(
+ 'Check for outstanding database actions that still need to be '
+ 'executed. This command can be used to verify the condition '
+ 'of the current database state.'
+ ),
+ )
return parser
@classmethod
def check_db_sync_status(cls):
status = 0
try:
- expand_version = upgrades.get_db_version(repo='expand_repo')
- except migration.exception.DBMigrationError:
- LOG.info('Your database is not currently under version '
- 'control or the database is already controlled. Your '
- 'first step is to run `keystone-manage db_sync '
- '--expand`.')
+ expand_version = upgrades.get_db_version(branch='expand')
+ except db_exception.DBMigrationError:
+ LOG.info(
+ 'Your database is not currently under version '
+ 'control or the database is already controlled. Your '
+ 'first step is to run `keystone-manage db_sync --expand`.'
+ )
return 2
+
try:
migrate_version = upgrades.get_db_version(
- repo='data_migration_repo')
- except migration.exception.DBMigrationError:
+ branch='data_migration')
+ except db_exception.DBMigrationError:
migrate_version = 0
+
try:
- contract_version = upgrades.get_db_version(repo='contract_repo')
- except migration.exception.DBMigrationError:
+ contract_version = upgrades.get_db_version(branch='contract')
+ except db_exception.DBMigrationError:
contract_version = 0
- repo = migrate.versioning.repository.Repository(
- upgrades.find_repo('expand_repo'))
- migration_script_version = int(max(repo.versions.versions))
+ migration_script_version = upgrades.LATEST_VERSION
- if (contract_version > migrate_version or migrate_version >
- expand_version):
+ if (
+ contract_version > migrate_version or
+ migrate_version > expand_version
+ ):
LOG.info('Your database is out of sync. For more information '
'refer to https://docs.openstack.org/keystone/'
'latest/admin/identity-upgrading.html')
@@ -311,29 +319,31 @@ class DbSync(BaseApp):
LOG.info('Migrate version is ahead of contract. Your next '
'step is to run `keystone-manage db_sync --contract`.')
status = 4
- elif (migration_script_version == expand_version == migrate_version ==
- contract_version):
+ elif (
+ migration_script_version == expand_version == migrate_version ==
+ contract_version
+ ):
LOG.info('All db_sync commands are upgraded to the same '
'version and up-to-date.')
- LOG.info('The latest installed migration script version is: '
- '%(script)d.\nCurrent repository versions:\nExpand: '
- '%(expand)d \nMigrate: %(migrate)d\nContract: '
- '%(contract)d', {'script': migration_script_version,
- 'expand': expand_version,
- 'migrate': migrate_version,
- 'contract': contract_version})
+ LOG.info(
+ 'The latest installed migration script version is: %(script)d.\n'
+ 'Current repository versions:\n'
+ 'Expand: %(expand)d\n'
+ 'Migrate: %(migrate)d\n'
+ 'Contract: %(contract)d',
+ {
+ 'script': migration_script_version,
+ 'expand': expand_version,
+ 'migrate': migrate_version,
+ 'contract': contract_version,
+ },
+ )
return status
@staticmethod
def main():
- assert_not_extension(CONF.command.extension)
- # It is possible to run expand and migrate at the same time,
- # expand needs to run first however.
if CONF.command.check:
sys.exit(DbSync.check_db_sync_status())
- elif CONF.command.expand and CONF.command.migrate:
- upgrades.expand_schema()
- upgrades.migrate_data()
elif CONF.command.expand:
upgrades.expand_schema()
elif CONF.command.migrate:
@@ -350,20 +360,8 @@ class DbVersion(BaseApp):
name = 'db_version'
- @classmethod
- def add_argument_parser(cls, subparsers):
- parser = super(DbVersion, cls).add_argument_parser(subparsers)
- parser.add_argument('--extension', default=None,
- help=('This is a deprecated option to print the '
- 'version of a specified extension. Since '
- 'extensions are now part of the main '
- 'repository, the version of an extension is '
- 'implicit in the version of the main '
- 'repository.'))
-
@staticmethod
def main():
- assert_not_extension(CONF.command.extension)
print(upgrades.get_db_version())
diff --git a/keystone/common/sql/alembic.ini b/keystone/common/sql/alembic.ini
new file mode 100644
index 000000000..6818c4db7
--- /dev/null
+++ b/keystone/common/sql/alembic.ini
@@ -0,0 +1,100 @@
+# A generic, single database configuration.
+
+[alembic]
+# path to migration scripts
+script_location = %(here)s/migrations
+
+# template used to generate migration files
+# file_template = %%(rev)s_%%(slug)s
+
+# sys.path path, will be prepended to sys.path if present.
+# defaults to the current working directory.
+prepend_sys_path = .
+
+# timezone to use when rendering the date within the migration file
+# as well as the filename.
+# If specified, requires the python-dateutil library that can be
+# installed by adding `alembic[tz]` to the pip requirements
+# string value is passed to dateutil.tz.gettz()
+# leave blank for localtime
+# timezone =
+
+# max length of characters to apply to the
+# "slug" field
+# truncate_slug_length = 40
+
+# set to 'true' to run the environment during
+# the 'revision' command, regardless of autogenerate
+# revision_environment = false
+
+# set to 'true' to allow .pyc and .pyo files without
+# a source .py file to be detected as revisions in the
+# versions/ directory
+# sourceless = false
+
+# version location specification; This defaults
+# to keystone/common/sql/migrations/versions. When using multiple version
+# directories, initial revisions must be specified with --version-path.
+# The path separator used here should be the separator specified by "version_path_separator"
+# version_locations = %(here)s/bar:%(here)s/bat:keystone/common/sql/migrations/versions
+
+# version path separator; As mentioned above, this is the character used to split
+# version_locations. Valid values are:
+#
+# version_path_separator = :
+# version_path_separator = ;
+# version_path_separator = space
+# version_path_separator = os
+
+# the output encoding used when revision files
+# are written from script.py.mako
+# output_encoding = utf-8
+
+sqlalchemy.url = sqlite:///keystone.db
+
+
+[post_write_hooks]
+# post_write_hooks defines scripts or Python functions that are run
+# on newly generated revision scripts. See the documentation for further
+# detail and examples
+
+# format using "black" - use the console_scripts runner, against the "black" entrypoint
+# hooks = black
+# black.type = console_scripts
+# black.entrypoint = black
+# black.options = -l 79 REVISION_SCRIPT_FILENAME
+
+# Logging configuration
+[loggers]
+keys = root,sqlalchemy,alembic
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+qualname =
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+
+[logger_alembic]
+level = INFO
+handlers =
+qualname = alembic
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(levelname)-5.5s [%(name)s] %(message)s
+datefmt = %H:%M:%S
diff --git a/keystone/common/sql/contract_repo/README b/keystone/common/sql/contract_repo/README
deleted file mode 100644
index 131117104..000000000
--- a/keystone/common/sql/contract_repo/README
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a database migration repository.
-
-More information at
-https://opendev.org/openstack/sqlalchemy-migrate
diff --git a/keystone/common/sql/contract_repo/versions/002_password_created_at_not_nullable.py b/keystone/common/sql/contract_repo/versions/002_password_created_at_not_nullable.py
deleted file mode 100644
index da2981e0d..000000000
--- a/keystone/common/sql/contract_repo/versions/002_password_created_at_not_nullable.py
+++ /dev/null
@@ -1,39 +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 datetime
-
-import sqlalchemy as sql
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- password = sql.Table('password', meta, autoload=True)
- # Because it's difficult to get a timestamp server default working among
- # all of the supported databases and versions, I'm choosing to drop and
- # then recreate the column as I think this is a more cleaner option. This
- # will only impact operators that have already deployed the 105 migration;
- # resetting the password created_at for security compliance features, if
- # enabled.
- password.c.created_at.drop()
- # sqlite doesn't support server_default=sql.func.now(), so skipping.
- if migrate_engine.name == 'sqlite':
- created_at = sql.Column('created_at', sql.TIMESTAMP, nullable=True)
- else:
- # Changing type to timestamp as mysql 5.5 and older doesn't support
- # datetime defaults.
- created_at = sql.Column('created_at', sql.TIMESTAMP, nullable=False,
- default=datetime.datetime.utcnow,
- server_default=sql.func.now())
- password.create_column(created_at)
diff --git a/keystone/common/sql/contract_repo/versions/003_remove_unencrypted_blob_column_from_credential.py b/keystone/common/sql/contract_repo/versions/003_remove_unencrypted_blob_column_from_credential.py
deleted file mode 100644
index 3c169e644..000000000
--- a/keystone/common/sql/contract_repo/versions/003_remove_unencrypted_blob_column_from_credential.py
+++ /dev/null
@@ -1,60 +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.
-
-from keystone.common.sql import upgrades
-
-import sqlalchemy as sql
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- credential_table = sql.Table('credential', meta, autoload=True)
- credential_table.c.blob.drop()
-
- if upgrades.USE_TRIGGERS:
- if migrate_engine.name == 'postgresql':
- drop_credential_update_trigger = (
- 'DROP TRIGGER credential_update_read_only on credential;'
- )
- drop_credential_insert_trigger = (
- 'DROP TRIGGER credential_insert_read_only on credential;'
- )
- elif migrate_engine.name == 'mysql':
- drop_credential_update_trigger = (
- 'DROP TRIGGER credential_update_read_only;'
- )
- drop_credential_insert_trigger = (
- 'DROP TRIGGER credential_insert_read_only;'
- )
- else:
- # NOTE(lbragstad, henry-nash): Apparently sqlalchemy and sqlite
- # behave weird when using triggers, which is why we use the `IF
- # EXISTS` conditional here. I think what is happening is that the
- # credential_table.c.blob.drop() causes sqlalchemy to create a new
- # credential table - but it doesn't copy the triggers over, which
- # causes the DROP TRIGGER statement to fail without `IF EXISTS`
- # because the trigger doesn't exist in the new table(?!).
- drop_credential_update_trigger = (
- 'DROP TRIGGER IF EXISTS credential_update_read_only;'
- )
- drop_credential_insert_trigger = (
- 'DROP TRIGGER IF EXISTS credential_insert_read_only;'
- )
- migrate_engine.execute(drop_credential_update_trigger)
- migrate_engine.execute(drop_credential_insert_trigger)
-
- # NOTE(lbragstad): We close these so that they are not nullable because
- # Newton code (and anything after) would always populate these values.
- credential_table.c.encrypted_blob.alter(nullable=False)
- credential_table.c.key_hash.alter(nullable=False)
diff --git a/keystone/common/sql/contract_repo/versions/004_reset_password_created_at.py b/keystone/common/sql/contract_repo/versions/004_reset_password_created_at.py
deleted file mode 100644
index f453d135d..000000000
--- a/keystone/common/sql/contract_repo/versions/004_reset_password_created_at.py
+++ /dev/null
@@ -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 datetime
-
-import sqlalchemy as sql
-import sqlalchemy.sql.expression as expression
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- password = sql.Table('password', meta, autoload=True)
- # reset created_at column
- password.c.created_at.drop()
- created_at = sql.Column('created_at', sql.DateTime(),
- nullable=True,
- default=datetime.datetime.utcnow)
- password.create_column(created_at)
- # update created_at value
- now = datetime.datetime.utcnow()
- values = {'created_at': now}
- stmt = password.update().where(
- password.c.created_at == expression.null()).values(values)
- stmt.execute()
- # set not nullable
- password.c.created_at.alter(nullable=False)
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/017_placeholder.py b/keystone/common/sql/contract_repo/versions/017_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/contract_repo/versions/017_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/018_placeholder.py b/keystone/common/sql/contract_repo/versions/018_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/contract_repo/versions/018_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/019_placeholder.py b/keystone/common/sql/contract_repo/versions/019_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/contract_repo/versions/019_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/020_placeholder.py b/keystone/common/sql/contract_repo/versions/020_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/contract_repo/versions/020_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/021_placeholder.py b/keystone/common/sql/contract_repo/versions/021_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/contract_repo/versions/021_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/022_contract_add_default_project_id_index.py b/keystone/common/sql/contract_repo/versions/022_contract_add_default_project_id_index.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/contract_repo/versions/022_contract_add_default_project_id_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/023_contract_add_second_password_column_for_expanded_hash_sizes.py b/keystone/common/sql/contract_repo/versions/023_contract_add_second_password_column_for_expanded_hash_sizes.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/contract_repo/versions/023_contract_add_second_password_column_for_expanded_hash_sizes.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/024_contract_create_created_at_int_columns.py b/keystone/common/sql/contract_repo/versions/024_contract_create_created_at_int_columns.py
deleted file mode 100644
index 986e19d0c..000000000
--- a/keystone/common/sql/contract_repo/versions/024_contract_create_created_at_int_columns.py
+++ /dev/null
@@ -1,61 +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 datetime
-
-import pytz
-import sqlalchemy as sql
-from sqlalchemy.orm import sessionmaker
-
-
-_epoch = datetime.datetime.fromtimestamp(0, tz=pytz.UTC)
-
-
-def _convert_value_datetime_to_int(dt):
- dt = dt.replace(tzinfo=pytz.utc)
- return int((dt - _epoch).total_seconds() * 1000000)
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
- maker = sessionmaker(bind=migrate_engine)
- session = maker()
-
- password_table = sql.Table('password', meta, autoload=True)
- passwords = list(password_table.select().execute())
-
- for passwd in passwords:
- values = {
- 'created_at_int': _convert_value_datetime_to_int(passwd.created_at)
- }
-
- if passwd.expires_at is not None:
- values['expires_at_int'] = _convert_value_datetime_to_int(
- passwd.expires_at)
-
- update = password_table.update().where(
- password_table.c.id == passwd.id).values(values)
- session.execute(update)
- session.commit()
-
- password_table = sql.Table('password', meta, autoload=True)
- # The created_at_int data cannot really be nullable long term. This
- # corrects the data to be not nullable, but must be done in the contract
- # phase for two reasons. The first is due to "additive only" requirements.
- # The second is because we need to ensure all nodes in the deployment are
- # running the Pike code-base before we migrate all password entries. This
- # avoids locking the password table or having a partial outage while doing
- # the migration.
- password_table.c.created_at_int.alter(nullable=False, default=0,
- server_default='0')
- session.close()
diff --git a/keystone/common/sql/contract_repo/versions/025_placeholder.py b/keystone/common/sql/contract_repo/versions/025_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/contract_repo/versions/025_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/026_placeholder.py b/keystone/common/sql/contract_repo/versions/026_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/contract_repo/versions/026_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/027_placeholder.py b/keystone/common/sql/contract_repo/versions/027_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/contract_repo/versions/027_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/028_placeholder.py b/keystone/common/sql/contract_repo/versions/028_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/contract_repo/versions/028_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/029_placeholder.py b/keystone/common/sql/contract_repo/versions/029_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/contract_repo/versions/029_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/030_contract_add_project_tags_table.py b/keystone/common/sql/contract_repo/versions/030_contract_add_project_tags_table.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/contract_repo/versions/030_contract_add_project_tags_table.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/031_contract_system_assignment_table.py b/keystone/common/sql/contract_repo/versions/031_contract_system_assignment_table.py
deleted file mode 100644
index 18a28170c..000000000
--- a/keystone/common/sql/contract_repo/versions/031_contract_system_assignment_table.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(lbragstad): System assignments only require additive changes.
- pass
diff --git a/keystone/common/sql/contract_repo/versions/032_contract_add_expired_at_int_to_trust.py b/keystone/common/sql/contract_repo/versions/032_contract_add_expired_at_int_to_trust.py
deleted file mode 100644
index 5839b8caa..000000000
--- a/keystone/common/sql/contract_repo/versions/032_contract_add_expired_at_int_to_trust.py
+++ /dev/null
@@ -1,51 +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 datetime
-
-from migrate import UniqueConstraint
-import pytz
-import sqlalchemy as sql
-from sqlalchemy.orm import sessionmaker
-
-
-_epoch = datetime.datetime.fromtimestamp(0, tz=pytz.UTC)
-
-
-def _convert_value_datetime_to_int(dt):
- dt = dt.replace(tzinfo=pytz.utc)
- return int((dt - _epoch).total_seconds() * 1000000)
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
- maker = sessionmaker(bind=migrate_engine)
- session = maker()
-
- trust_table = sql.Table('trust', meta, autoload=True)
- trusts = list(trust_table.select().execute())
-
- for trust in trusts:
- values = {}
- if trust.expires_at is not None:
- values['expires_at_int'] = _convert_value_datetime_to_int(
- trust.expires_at)
-
- update = trust_table.update().where(
- trust_table.c.id == trust.id).values(values)
- session.execute(update)
- session.commit()
-
- UniqueConstraint(table=trust_table,
- name='duplicate_trust_constraint').drop()
- session.close()
diff --git a/keystone/common/sql/contract_repo/versions/033_contract_add_limits_tables.py b/keystone/common/sql/contract_repo/versions/033_contract_add_limits_tables.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/contract_repo/versions/033_contract_add_limits_tables.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/034_contract_add_application_credentials_table.py b/keystone/common/sql/contract_repo/versions/034_contract_add_application_credentials_table.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/contract_repo/versions/034_contract_add_application_credentials_table.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/035_contract_add_system_column_to_application_credential_table.py b/keystone/common/sql/contract_repo/versions/035_contract_add_system_column_to_application_credential_table.py
deleted file mode 100644
index 192391a54..000000000
--- a/keystone/common/sql/contract_repo/versions/035_contract_add_system_column_to_application_credential_table.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 sqlalchemy as sql
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- application_credential_table = sql.Table(
- 'application_credential', meta, autoload=True
- )
- application_credential_table.c.project_id.alter(nullable=True)
diff --git a/keystone/common/sql/contract_repo/versions/036_contract_rename_application_credential_restriction_column.py b/keystone/common/sql/contract_repo/versions/036_contract_rename_application_credential_restriction_column.py
deleted file mode 100644
index f8ef7e1a7..000000000
--- a/keystone/common/sql/contract_repo/versions/036_contract_rename_application_credential_restriction_column.py
+++ /dev/null
@@ -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
-
- application_credential_table = sql.Table(
- 'application_credential', meta, autoload=True
- )
- if migrate_engine.name == 'sqlite':
- old_table = sql.Table('application_credential', meta, autoload=True)
- new_table = sql.Table('application_credential_temp', meta,
- autoload=True)
- old_table.drop()
- new_table.rename('application_credential')
- else:
- table = application_credential_table
- # NOTE(cmurphy) because of lb#1744948, some deployments could already
- # have made it past the expand step and be stuck on the contract step.
- # If necessary, do the expand step here.
- # At this point this API is not yet exposed and there should be no data
- # in this table.
- if 'unrestricted' not in table.columns:
- unrestricted = sql.Column('unrestricted', sql.Boolean())
- table.create_column(unrestricted)
- column = table.c.allow_application_credential_creation
- column.drop()
diff --git a/keystone/common/sql/contract_repo/versions/037_contract_remove_service_and_region_fk_for_registered_limit.py b/keystone/common/sql/contract_repo/versions/037_contract_remove_service_and_region_fk_for_registered_limit.py
deleted file mode 100644
index 72a3f315f..000000000
--- a/keystone/common/sql/contract_repo/versions/037_contract_remove_service_and_region_fk_for_registered_limit.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.
-
-from migrate import ForeignKeyConstraint
-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)
- service_table = sql.Table('service', meta, autoload=True)
- region_table = sql.Table('region', meta, autoload=True)
-
- inspector = sql.inspect(migrate_engine)
- for fk in inspector.get_foreign_keys('registered_limit'):
- if fk['referred_table'] == 'service':
- fkey = ForeignKeyConstraint([registered_limit_table.c.service_id],
- [service_table.c.id],
- name=fk['name'])
- fkey.drop()
- else:
- fkey = ForeignKeyConstraint([registered_limit_table.c.region_id],
- [region_table.c.id],
- name=fk['name'])
- fkey.drop()
diff --git a/keystone/common/sql/contract_repo/versions/038_placeholder.py b/keystone/common/sql/contract_repo/versions/038_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/contract_repo/versions/038_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/039_placeholder.py b/keystone/common/sql/contract_repo/versions/039_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/contract_repo/versions/039_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/040_placeholder.py b/keystone/common/sql/contract_repo/versions/040_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/contract_repo/versions/040_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/041_placeholder.py b/keystone/common/sql/contract_repo/versions/041_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/contract_repo/versions/041_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/042_placeholder.py b/keystone/common/sql/contract_repo/versions/042_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/contract_repo/versions/042_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/043_placeholder.py b/keystone/common/sql/contract_repo/versions/043_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/contract_repo/versions/043_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/044_placeholder.py b/keystone/common/sql/contract_repo/versions/044_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/contract_repo/versions/044_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/045_contract_add_description_to_limit.py b/keystone/common/sql/contract_repo/versions/045_contract_add_description_to_limit.py
deleted file mode 100644
index 9cb40b454..000000000
--- a/keystone/common/sql/contract_repo/versions/045_contract_add_description_to_limit.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/046_contract_old_password_data_to_password_hash_column.py b/keystone/common/sql/contract_repo/versions/046_contract_old_password_data_to_password_hash_column.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/contract_repo/versions/046_contract_old_password_data_to_password_hash_column.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/047_contract_expand_update_pk_for_unified_limit.py b/keystone/common/sql/contract_repo/versions/047_contract_expand_update_pk_for_unified_limit.py
deleted file mode 100644
index d750bde53..000000000
--- a/keystone/common/sql/contract_repo/versions/047_contract_expand_update_pk_for_unified_limit.py
+++ /dev/null
@@ -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')
diff --git a/keystone/common/sql/contract_repo/versions/048_contract_add_registered_limit_id_column_for_limit.py b/keystone/common/sql/contract_repo/versions/048_contract_add_registered_limit_id_column_for_limit.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/contract_repo/versions/048_contract_add_registered_limit_id_column_for_limit.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/049_placeholder.py b/keystone/common/sql/contract_repo/versions/049_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/contract_repo/versions/049_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/050_placeholder.py b/keystone/common/sql/contract_repo/versions/050_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/contract_repo/versions/050_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/051_placeholder.py b/keystone/common/sql/contract_repo/versions/051_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/contract_repo/versions/051_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/052_placeholder.py b/keystone/common/sql/contract_repo/versions/052_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/contract_repo/versions/052_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/053_contract_add_role_description_to_role_table.py b/keystone/common/sql/contract_repo/versions/053_contract_add_role_description_to_role_table.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/contract_repo/versions/053_contract_add_role_description_to_role_table.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/054_contract_drop_old_passoword_column.py b/keystone/common/sql/contract_repo/versions/054_contract_drop_old_passoword_column.py
deleted file mode 100644
index 1b33173c6..000000000
--- a/keystone/common/sql/contract_repo/versions/054_contract_drop_old_passoword_column.py
+++ /dev/null
@@ -1,21 +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
-
- password_table = sql.Table('password', meta, autoload=True)
- password_table.c.password.drop()
diff --git a/keystone/common/sql/contract_repo/versions/055_contract_add_domain_to_limit.py b/keystone/common/sql/contract_repo/versions/055_contract_add_domain_to_limit.py
deleted file mode 100644
index 36d641768..000000000
--- a/keystone/common/sql/contract_repo/versions/055_contract_add_domain_to_limit.py
+++ /dev/null
@@ -1,21 +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
-
- limit_table = sql.Table('limit', meta, autoload=True)
- limit_table.c.project_id.alter(nullable=True)
diff --git a/keystone/common/sql/contract_repo/versions/056_contract_add_application_credential_access_rules.py b/keystone/common/sql/contract_repo/versions/056_contract_add_application_credential_access_rules.py
deleted file mode 100644
index 8066b50bb..000000000
--- a/keystone/common/sql/contract_repo/versions/056_contract_add_application_credential_access_rules.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2019 SUSE Linux GmbH
-#
-# 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/057_placeholder.py b/keystone/common/sql/contract_repo/versions/057_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/contract_repo/versions/057_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/058_placeholder.py b/keystone/common/sql/contract_repo/versions/058_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/contract_repo/versions/058_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/059_placeholder.py b/keystone/common/sql/contract_repo/versions/059_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/contract_repo/versions/059_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/060_placeholder.py b/keystone/common/sql/contract_repo/versions/060_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/contract_repo/versions/060_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/061_placeholder.py b/keystone/common/sql/contract_repo/versions/061_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/contract_repo/versions/061_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/062_contract_extract_redelegation_data_from_extras.py b/keystone/common/sql/contract_repo/versions/062_contract_extract_redelegation_data_from_extras.py
deleted file mode 100644
index 9cb40b454..000000000
--- a/keystone/common/sql/contract_repo/versions/062_contract_extract_redelegation_data_from_extras.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/063_contract_drop_limit_columns.py b/keystone/common/sql/contract_repo/versions/063_contract_drop_limit_columns.py
deleted file mode 100644
index 8858ba916..000000000
--- a/keystone/common/sql/contract_repo/versions/063_contract_drop_limit_columns.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 sqlalchemy as sql
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- limit_table = sql.Table('limit', meta, autoload=True)
- limit_table.c.service_id.drop()
- limit_table.c.region_id.drop()
- limit_table.c.resource_name.drop()
diff --git a/keystone/common/sql/contract_repo/versions/064_contract_add_remote_id_attribute_to_federation_protocol_table.py b/keystone/common/sql/contract_repo/versions/064_contract_add_remote_id_attribute_to_federation_protocol_table.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/contract_repo/versions/064_contract_add_remote_id_attribute_to_federation_protocol_table.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/065_contract_add_user_external_id_to_access_rule.py b/keystone/common/sql/contract_repo/versions/065_contract_add_user_external_id_to_access_rule.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/contract_repo/versions/065_contract_add_user_external_id_to_access_rule.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/066_contract_add_resource_options_table.py b/keystone/common/sql/contract_repo/versions/066_contract_add_resource_options_table.py
deleted file mode 100644
index d1f20e252..000000000
--- a/keystone/common/sql/contract_repo/versions/066_contract_add_resource_options_table.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.
-
-# NOTE(morgan): there is nothing to do here, no contract action to take
-# at this time
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/067_placeholder.py b/keystone/common/sql/contract_repo/versions/067_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/contract_repo/versions/067_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/068_placeholder.py b/keystone/common/sql/contract_repo/versions/068_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/contract_repo/versions/068_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/069_placeholder.py b/keystone/common/sql/contract_repo/versions/069_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/contract_repo/versions/069_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/070_placeholder.py b/keystone/common/sql/contract_repo/versions/070_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/contract_repo/versions/070_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/071_placeholder.py b/keystone/common/sql/contract_repo/versions/071_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/contract_repo/versions/071_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/contract_repo/versions/072_contract_drop_domain_id_fk.py b/keystone/common/sql/contract_repo/versions/072_contract_drop_domain_id_fk.py
deleted file mode 100644
index 7e00c1e9f..000000000
--- a/keystone/common/sql/contract_repo/versions/072_contract_drop_domain_id_fk.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright 2019 SUSE LLC
-#
-# 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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-import migrate
-import sqlalchemy as sql
-
-
-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)
-
- fk_name = [
- c for c in user.constraints
- if isinstance(c, sql.ForeignKeyConstraint)
- and c.column_keys == ['domain_id']
- ][0].name
- fk_constraint = migrate.ForeignKeyConstraint(
- columns=[user.c.domain_id], refcolumns=[project.c.id])
- fk_constraint.name = fk_name
- fk_constraint.drop()
-
- identity_provider = sql.Table('identity_provider', meta, autoload=True)
- fk_name = [
- c for c in identity_provider.constraints
- if isinstance(c, sql.ForeignKeyConstraint)
- and c.column_keys == ['domain_id']
- ][0].name
- fk_constraint = migrate.ForeignKeyConstraint(
- columns=[identity_provider.c.domain_id], refcolumns=[project.c.id])
- fk_constraint.name = fk_name
- fk_constraint.drop()
diff --git a/keystone/common/sql/contract_repo/versions/073_contract_expiring_group_membership.py b/keystone/common/sql/contract_repo/versions/073_contract_expiring_group_membership.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/contract_repo/versions/073_contract_expiring_group_membership.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/README b/keystone/common/sql/data_migration_repo/README
deleted file mode 100644
index 131117104..000000000
--- a/keystone/common/sql/data_migration_repo/README
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a database migration repository.
-
-More information at
-https://opendev.org/openstack/sqlalchemy-migrate
diff --git a/keystone/common/sql/data_migration_repo/versions/002_password_created_at_not_nullable.py b/keystone/common/sql/data_migration_repo/versions/002_password_created_at_not_nullable.py
deleted file mode 100644
index 9cb40b454..000000000
--- a/keystone/common/sql/data_migration_repo/versions/002_password_created_at_not_nullable.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/003_migrate_unencrypted_credentials.py b/keystone/common/sql/data_migration_repo/versions/003_migrate_unencrypted_credentials.py
deleted file mode 100644
index 7f51b75e1..000000000
--- a/keystone/common/sql/data_migration_repo/versions/003_migrate_unencrypted_credentials.py
+++ /dev/null
@@ -1,39 +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.credential.providers import fernet as credential_fernet
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
- session = sql.orm.sessionmaker(bind=migrate_engine)()
-
- credential_table = sql.Table('credential', meta, autoload=True)
- credentials = list(credential_table.select().execute())
-
- for credential in credentials:
- crypto, keys = credential_fernet.get_multi_fernet_keys()
- primary_key_hash = credential_fernet.primary_key_hash(keys)
- encrypted_blob = crypto.encrypt(credential['blob'].encode('utf-8'))
- values = {
- 'encrypted_blob': encrypted_blob,
- 'key_hash': primary_key_hash
- }
- update = credential_table.update().where(
- credential_table.c.id == credential.id
- ).values(values)
- session.execute(update)
- session.commit()
- session.close()
diff --git a/keystone/common/sql/data_migration_repo/versions/004_reset_password_created_at.py b/keystone/common/sql/data_migration_repo/versions/004_reset_password_created_at.py
deleted file mode 100644
index 9cb40b454..000000000
--- a/keystone/common/sql/data_migration_repo/versions/004_reset_password_created_at.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/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/017_placeholder.py b/keystone/common/sql/data_migration_repo/versions/017_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/data_migration_repo/versions/017_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/018_placeholder.py b/keystone/common/sql/data_migration_repo/versions/018_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/data_migration_repo/versions/018_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/019_placeholder.py b/keystone/common/sql/data_migration_repo/versions/019_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/data_migration_repo/versions/019_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/020_placeholder.py b/keystone/common/sql/data_migration_repo/versions/020_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/data_migration_repo/versions/020_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/021_placeholder.py b/keystone/common/sql/data_migration_repo/versions/021_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/data_migration_repo/versions/021_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/022_migrate_add_default_project_id_index.py b/keystone/common/sql/data_migration_repo/versions/022_migrate_add_default_project_id_index.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/022_migrate_add_default_project_id_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/023_migrate_add_second_password_column_for_expanded_hash_sizes.py b/keystone/common/sql/data_migration_repo/versions/023_migrate_add_second_password_column_for_expanded_hash_sizes.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/023_migrate_add_second_password_column_for_expanded_hash_sizes.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/024_migrate_create_created_at_int_columns.py b/keystone/common/sql/data_migration_repo/versions/024_migrate_create_created_at_int_columns.py
deleted file mode 100644
index 5dcd05d82..000000000
--- a/keystone/common/sql/data_migration_repo/versions/024_migrate_create_created_at_int_columns.py
+++ /dev/null
@@ -1,22 +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):
- # A migration here is not needed because the actual marshalling of data
- # from the old column to the new column is done in the contract phase. This
- # is because using triggers to convert datetime objects to integers is
- # complex and error-prone. Instead, we'll migrate the data once all
- # keystone nodes are on the Pike code-base. From an operator perspective,
- # this shouldn't affect operability of a rolling upgrade since all nodes
- # must be running Pike before the contract takes place.
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/025_placeholder.py b/keystone/common/sql/data_migration_repo/versions/025_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/data_migration_repo/versions/025_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/026_placeholder.py b/keystone/common/sql/data_migration_repo/versions/026_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/data_migration_repo/versions/026_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/027_placeholder.py b/keystone/common/sql/data_migration_repo/versions/027_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/data_migration_repo/versions/027_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/028_placeholder.py b/keystone/common/sql/data_migration_repo/versions/028_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/data_migration_repo/versions/028_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/029_placeholder.py b/keystone/common/sql/data_migration_repo/versions/029_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/data_migration_repo/versions/029_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/030_migrate_add_project_tags_table.py b/keystone/common/sql/data_migration_repo/versions/030_migrate_add_project_tags_table.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/030_migrate_add_project_tags_table.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/031_migrate_system_assignment_table.py b/keystone/common/sql/data_migration_repo/versions/031_migrate_system_assignment_table.py
deleted file mode 100644
index c02f78c4e..000000000
--- a/keystone/common/sql/data_migration_repo/versions/031_migrate_system_assignment_table.py
+++ /dev/null
@@ -1,17 +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(lbragstad): A migration isn't required here since system assignments
- # are a new feature in Queens.
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/032_migrate_add_expired_at_int_to_trust.py b/keystone/common/sql/data_migration_repo/versions/032_migrate_add_expired_at_int_to_trust.py
deleted file mode 100644
index ce4496ee0..000000000
--- a/keystone/common/sql/data_migration_repo/versions/032_migrate_add_expired_at_int_to_trust.py
+++ /dev/null
@@ -1,22 +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):
- # A migration here is not needed because the actual marshalling of data
- # from the old column to the new column is done in the contract phase. This
- # is because using triggers to convert datetime objects to integers is
- # complex and error-prone. Instead, we'll migrate the data once all
- # keystone nodes are on the Queens code-base. From an operator perspective,
- # this shouldn't affect operability of a rolling upgrade since all nodes
- # must be running Queens before the contract takes place.
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/033_migrate_add_limits_tables.py b/keystone/common/sql/data_migration_repo/versions/033_migrate_add_limits_tables.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/033_migrate_add_limits_tables.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/034_migrate_add_application_credentials_table.py b/keystone/common/sql/data_migration_repo/versions/034_migrate_add_application_credentials_table.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/034_migrate_add_application_credentials_table.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/035_migrate_add_system_column_to_application_credential_table.py b/keystone/common/sql/data_migration_repo/versions/035_migrate_add_system_column_to_application_credential_table.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/035_migrate_add_system_column_to_application_credential_table.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/036_migrate_rename_application_credential_restriction_column.py b/keystone/common/sql/data_migration_repo/versions/036_migrate_rename_application_credential_restriction_column.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/036_migrate_rename_application_credential_restriction_column.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/037_migrate_remove_service_and_region_fk_for_registered_limit.py b/keystone/common/sql/data_migration_repo/versions/037_migrate_remove_service_and_region_fk_for_registered_limit.py
deleted file mode 100644
index 9cb40b454..000000000
--- a/keystone/common/sql/data_migration_repo/versions/037_migrate_remove_service_and_region_fk_for_registered_limit.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/038_placeholder.py b/keystone/common/sql/data_migration_repo/versions/038_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/data_migration_repo/versions/038_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/039_placeholder.py b/keystone/common/sql/data_migration_repo/versions/039_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/data_migration_repo/versions/039_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/040_placeholder.py b/keystone/common/sql/data_migration_repo/versions/040_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/data_migration_repo/versions/040_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/041_placeholder.py b/keystone/common/sql/data_migration_repo/versions/041_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/data_migration_repo/versions/041_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/042_placeholder.py b/keystone/common/sql/data_migration_repo/versions/042_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/data_migration_repo/versions/042_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/043_placeholder.py b/keystone/common/sql/data_migration_repo/versions/043_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/data_migration_repo/versions/043_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/044_placeholder.py b/keystone/common/sql/data_migration_repo/versions/044_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/data_migration_repo/versions/044_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/045_migrate_add_description_to_limit.py b/keystone/common/sql/data_migration_repo/versions/045_migrate_add_description_to_limit.py
deleted file mode 100644
index 9cb40b454..000000000
--- a/keystone/common/sql/data_migration_repo/versions/045_migrate_add_description_to_limit.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/046_migrate_old_password_data_to_password_hash_column.py b/keystone/common/sql/data_migration_repo/versions/046_migrate_old_password_data_to_password_hash_column.py
deleted file mode 100644
index 0a69f32e5..000000000
--- a/keystone/common/sql/data_migration_repo/versions/046_migrate_old_password_data_to_password_hash_column.py
+++ /dev/null
@@ -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)
diff --git a/keystone/common/sql/data_migration_repo/versions/047_migrate_update_pk_for_unified_limit.py b/keystone/common/sql/data_migration_repo/versions/047_migrate_update_pk_for_unified_limit.py
deleted file mode 100644
index e76298c15..000000000
--- a/keystone/common/sql/data_migration_repo/versions/047_migrate_update_pk_for_unified_limit.py
+++ /dev/null
@@ -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()
diff --git a/keystone/common/sql/data_migration_repo/versions/048_migrate_add_registered_limit_id_column_for_limit.py b/keystone/common/sql/data_migration_repo/versions/048_migrate_add_registered_limit_id_column_for_limit.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/048_migrate_add_registered_limit_id_column_for_limit.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/049_placeholder.py b/keystone/common/sql/data_migration_repo/versions/049_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/data_migration_repo/versions/049_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/050_placeholder.py b/keystone/common/sql/data_migration_repo/versions/050_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/data_migration_repo/versions/050_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/051_placeholder.py b/keystone/common/sql/data_migration_repo/versions/051_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/data_migration_repo/versions/051_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/052_placeholder.py b/keystone/common/sql/data_migration_repo/versions/052_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/data_migration_repo/versions/052_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/053_migrate_add_role_description_to_role_table.py b/keystone/common/sql/data_migration_repo/versions/053_migrate_add_role_description_to_role_table.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/053_migrate_add_role_description_to_role_table.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/054_migrate_drop_old_passoword_column.py b/keystone/common/sql/data_migration_repo/versions/054_migrate_drop_old_passoword_column.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/054_migrate_drop_old_passoword_column.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/055_migrate_add_domain_to_limit.py b/keystone/common/sql/data_migration_repo/versions/055_migrate_add_domain_to_limit.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/055_migrate_add_domain_to_limit.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/056_migrate_add_application_credential_access_rules.py b/keystone/common/sql/data_migration_repo/versions/056_migrate_add_application_credential_access_rules.py
deleted file mode 100644
index 8066b50bb..000000000
--- a/keystone/common/sql/data_migration_repo/versions/056_migrate_add_application_credential_access_rules.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2019 SUSE Linux GmbH
-#
-# 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/057_placeholder.py b/keystone/common/sql/data_migration_repo/versions/057_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/data_migration_repo/versions/057_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/058_placeholder.py b/keystone/common/sql/data_migration_repo/versions/058_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/data_migration_repo/versions/058_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/059_placeholder.py b/keystone/common/sql/data_migration_repo/versions/059_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/data_migration_repo/versions/059_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/060_placeholder.py b/keystone/common/sql/data_migration_repo/versions/060_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/data_migration_repo/versions/060_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/061_placeholder.py b/keystone/common/sql/data_migration_repo/versions/061_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/data_migration_repo/versions/061_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/062_migrate_extract_redelegation_data_from_extras.py b/keystone/common/sql/data_migration_repo/versions/062_migrate_extract_redelegation_data_from_extras.py
deleted file mode 100644
index ddb30368d..000000000
--- a/keystone/common/sql/data_migration_repo/versions/062_migrate_extract_redelegation_data_from_extras.py
+++ /dev/null
@@ -1,43 +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.
-
-from oslo_serialization import jsonutils
-import sqlalchemy as sql
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- trust_table = sql.Table('trust', meta, autoload=True)
- trust_list = list(trust_table.select().execute())
-
- # Loop through all the trusts and move the redelegeated trust id out of
- # extras.
- for trust in trust_list:
- if trust.extra is not None:
- extra_dict = jsonutils.loads(trust.extra)
- else:
- extra_dict = {}
-
- new_values = {}
-
- new_values['redelegated_trust_id'] = extra_dict.pop(
- 'redelegated_trust_id', None)
- new_values['redelegation_count'] = extra_dict.pop(
- 'redelegation_count', None)
-
- new_values['extra'] = jsonutils.dumps(extra_dict)
-
- clause = trust_table.c.id == trust.id
- update = trust_table.update().where(clause).values(new_values)
- migrate_engine.execute(update)
diff --git a/keystone/common/sql/data_migration_repo/versions/063_migrate_drop_limit_columns.py b/keystone/common/sql/data_migration_repo/versions/063_migrate_drop_limit_columns.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/063_migrate_drop_limit_columns.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/064_migrate_add_remote_id_attribute_to_federation_protocol_table.py b/keystone/common/sql/data_migration_repo/versions/064_migrate_add_remote_id_attribute_to_federation_protocol_table.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/064_migrate_add_remote_id_attribute_to_federation_protocol_table.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/065_migrate_add_user_external_id_to_access_rule.py b/keystone/common/sql/data_migration_repo/versions/065_migrate_add_user_external_id_to_access_rule.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/065_migrate_add_user_external_id_to_access_rule.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/066_migrate_add_resource_options_table.py b/keystone/common/sql/data_migration_repo/versions/066_migrate_add_resource_options_table.py
deleted file mode 100644
index b1e5fdddf..000000000
--- a/keystone/common/sql/data_migration_repo/versions/066_migrate_add_resource_options_table.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.
-
-# NOTE(morgan): there is nothing to do here, data migration for user
-# resource options will occur in a future change.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/067_placeholder.py b/keystone/common/sql/data_migration_repo/versions/067_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/data_migration_repo/versions/067_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/068_placeholder.py b/keystone/common/sql/data_migration_repo/versions/068_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/data_migration_repo/versions/068_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/069_placeholder.py b/keystone/common/sql/data_migration_repo/versions/069_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/data_migration_repo/versions/069_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/070_placeholder.py b/keystone/common/sql/data_migration_repo/versions/070_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/data_migration_repo/versions/070_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/071_placeholder.py b/keystone/common/sql/data_migration_repo/versions/071_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/data_migration_repo/versions/071_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/072_migrate_drop_domain_id_fk.py b/keystone/common/sql/data_migration_repo/versions/072_migrate_drop_domain_id_fk.py
deleted file mode 100644
index bb90c3de3..000000000
--- a/keystone/common/sql/data_migration_repo/versions/072_migrate_drop_domain_id_fk.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2019 SUSE LLC
-#
-# 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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/data_migration_repo/versions/073_migrate_expiring_group_membership.py b/keystone/common/sql/data_migration_repo/versions/073_migrate_expiring_group_membership.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/data_migration_repo/versions/073_migrate_expiring_group_membership.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/README b/keystone/common/sql/expand_repo/README
deleted file mode 100644
index 131117104..000000000
--- a/keystone/common/sql/expand_repo/README
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a database migration repository.
-
-More information at
-https://opendev.org/openstack/sqlalchemy-migrate
diff --git a/keystone/common/sql/expand_repo/versions/002_password_created_at_not_nullable.py b/keystone/common/sql/expand_repo/versions/002_password_created_at_not_nullable.py
deleted file mode 100644
index 1cd34e617..000000000
--- a/keystone/common/sql/expand_repo/versions/002_password_created_at_not_nullable.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.
-
-# A null initial migration to open this repo. Do not re-use replace this with
-# a real migration, add additional ones in subsequent version scripts.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/003_add_key_hash_and_encrypted_blob_to_credential.py b/keystone/common/sql/expand_repo/versions/003_add_key_hash_and_encrypted_blob_to_credential.py
deleted file mode 100644
index 3e9f25b03..000000000
--- a/keystone/common/sql/expand_repo/versions/003_add_key_hash_and_encrypted_blob_to_credential.py
+++ /dev/null
@@ -1,129 +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
-from keystone.common.sql import upgrades
-
-
-# NOTE(lbragstad): MySQL error state of 45000 is a generic unhandled exception.
-# Keystone will return a 500 in this case.
-MYSQL_INSERT_TRIGGER = """
-CREATE TRIGGER credential_insert_read_only BEFORE INSERT ON credential
-FOR EACH ROW
-BEGIN
- SIGNAL SQLSTATE '45000'
- SET MESSAGE_TEXT = '%s';
-END;
-"""
-
-MYSQL_UPDATE_TRIGGER = """
-CREATE TRIGGER credential_update_read_only BEFORE UPDATE ON credential
-FOR EACH ROW
-BEGIN
- IF NEW.encrypted_blob IS NULL THEN
- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '%s';
- END IF;
- IF NEW.encrypted_blob IS NOT NULL AND OLD.blob IS NULL THEN
- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '%s';
- END IF;
-END;
-"""
-
-SQLITE_INSERT_TRIGGER = """
-CREATE TRIGGER credential_insert_read_only BEFORE INSERT ON credential
-BEGIN
- SELECT RAISE (ABORT, '%s');
-END;
-"""
-
-SQLITE_UPDATE_TRIGGER = """
-CREATE TRIGGER credential_update_read_only BEFORE UPDATE ON credential
-WHEN NEW.encrypted_blob IS NULL
-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 credential_insert_read_only BEFORE INSERT ON credential
-FOR EACH ROW
-EXECUTE PROCEDURE keystone_read_only_insert();
-"""
-
-POSTGRESQL_UPDATE_TRIGGER = """
-CREATE OR REPLACE FUNCTION keystone_read_only_update()
- RETURNS trigger AS
-$BODY$
-BEGIN
- IF NEW.encrypted_blob IS NULL THEN
- RAISE EXCEPTION '%s';
- END IF;
- IF NEW.encrypted_blob IS NOT NULL AND OLD.blob IS NULL THEN
- RAISE EXCEPTION '%s';
- END IF;
- RETURN NEW;
-END
-$BODY$ LANGUAGE plpgsql;
-
-CREATE TRIGGER credential_update_read_only BEFORE UPDATE ON credential
-FOR EACH ROW
-EXECUTE PROCEDURE keystone_read_only_update();
-"""
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- key_hash = sql.Column('key_hash', sql.String(64), nullable=True)
- encrypted_blob = sql.Column(
- 'encrypted_blob',
- ks_sql.Text,
- nullable=True
- )
- credential_table = sql.Table('credential', meta, autoload=True)
- credential_table.create_column(key_hash)
- credential_table.create_column(encrypted_blob)
- credential_table.c.blob.alter(nullable=True)
-
- if not upgrades.USE_TRIGGERS:
- # Skip managing triggers if we're doing an offline upgrade.
- return
-
- error_message = ('Credential migration in progress. Cannot perform '
- 'writes to credential table.')
- if migrate_engine.name == 'postgresql':
- credential_insert_trigger = POSTGRESQL_INSERT_TRIGGER % error_message
- credential_update_trigger = POSTGRESQL_UPDATE_TRIGGER % (
- error_message, error_message
- )
- elif migrate_engine.name == 'sqlite':
- credential_insert_trigger = SQLITE_INSERT_TRIGGER % error_message
- credential_update_trigger = SQLITE_UPDATE_TRIGGER % error_message
- else:
- credential_insert_trigger = MYSQL_INSERT_TRIGGER % error_message
- credential_update_trigger = MYSQL_UPDATE_TRIGGER % (
- error_message, error_message
- )
-
- migrate_engine.execute(credential_insert_trigger)
- migrate_engine.execute(credential_update_trigger)
diff --git a/keystone/common/sql/expand_repo/versions/004_reset_password_created_at.py b/keystone/common/sql/expand_repo/versions/004_reset_password_created_at.py
deleted file mode 100644
index 9cb40b454..000000000
--- a/keystone/common/sql/expand_repo/versions/004_reset_password_created_at.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/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/017_placeholder.py b/keystone/common/sql/expand_repo/versions/017_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/expand_repo/versions/017_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/018_placeholder.py b/keystone/common/sql/expand_repo/versions/018_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/expand_repo/versions/018_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/019_placeholder.py b/keystone/common/sql/expand_repo/versions/019_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/expand_repo/versions/019_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/020_placeholder.py b/keystone/common/sql/expand_repo/versions/020_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/expand_repo/versions/020_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/021_placeholder.py b/keystone/common/sql/expand_repo/versions/021_placeholder.py
deleted file mode 100644
index cd0769c5e..000000000
--- a/keystone/common/sql/expand_repo/versions/021_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 Ocata backports. Do not use this number for new
-# Pike work. New Pike work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/022_expand_add_default_project_id_index.py b/keystone/common/sql/expand_repo/versions/022_expand_add_default_project_id_index.py
deleted file mode 100644
index 37413d0f9..000000000
--- a/keystone/common/sql/expand_repo/versions/022_expand_add_default_project_id_index.py
+++ /dev/null
@@ -1,21 +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
-
- user = sql.Table('user', meta, autoload=True)
- sql.Index('ix_default_project_id', user.c.default_project_id).create()
diff --git a/keystone/common/sql/expand_repo/versions/023_expand_add_second_password_column_for_expanded_hash_sizes.py b/keystone/common/sql/expand_repo/versions/023_expand_add_second_password_column_for_expanded_hash_sizes.py
deleted file mode 100644
index ebd2b8bbf..000000000
--- a/keystone/common/sql/expand_repo/versions/023_expand_add_second_password_column_for_expanded_hash_sizes.py
+++ /dev/null
@@ -1,25 +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
-
- # NOTE(notmorgan): To support the full range of scrypt and pbkfd password
- # hash lengths, this should be closer to varchar(1500) instead of
- # varchar(255).
- password_hash = sql.Column('password_hash', sql.String(255), nullable=True)
- password_table = sql.Table('password', meta, autoload=True)
- password_table.create_column(password_hash)
diff --git a/keystone/common/sql/expand_repo/versions/024_expand_create_created_at_int_columns.py b/keystone/common/sql/expand_repo/versions/024_expand_create_created_at_int_columns.py
deleted file mode 100644
index d836a861f..000000000
--- a/keystone/common/sql/expand_repo/versions/024_expand_create_created_at_int_columns.py
+++ /dev/null
@@ -1,33 +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
-
- # NOTE(morgan): column is nullable here for migration purposes
- # it is set to not-nullable in the contract phase to ensure we can handle
- # rolling upgrades in a sane way. This differs from the model in
- # keystone.identity.backends.sql_model by design.
- created_at = sql.Column('created_at_int', ks_sql.DateTimeInt(),
- nullable=True)
- expires_at = sql.Column('expires_at_int', ks_sql.DateTimeInt(),
- nullable=True)
- password_table = sql.Table('password', meta, autoload=True)
- password_table.create_column(created_at)
- password_table.create_column(expires_at)
diff --git a/keystone/common/sql/expand_repo/versions/025_placeholder.py b/keystone/common/sql/expand_repo/versions/025_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/expand_repo/versions/025_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/026_placeholder.py b/keystone/common/sql/expand_repo/versions/026_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/expand_repo/versions/026_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/027_placeholder.py b/keystone/common/sql/expand_repo/versions/027_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/expand_repo/versions/027_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/028_placeholder.py b/keystone/common/sql/expand_repo/versions/028_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/expand_repo/versions/028_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/029_placeholder.py b/keystone/common/sql/expand_repo/versions/029_placeholder.py
deleted file mode 100644
index a96cd6f36..000000000
--- a/keystone/common/sql/expand_repo/versions/029_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 Pike backports. Do not use this number for new
-# Queens work. New Queens work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/030_expand_add_project_tags_table.py b/keystone/common/sql/expand_repo/versions/030_expand_add_project_tags_table.py
deleted file mode 100644
index 71ff49d43..000000000
--- a/keystone/common/sql/expand_repo/versions/030_expand_add_project_tags_table.py
+++ /dev/null
@@ -1,44 +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
-
- project_table = sql.Table('project', meta, autoload=True)
-
- # NOTE(lamt) To allow tag name to be case sensitive for MySQL, the 'name'
- # column needs to use collation, which is incompatible with Postgresql.
- # Using unicode to mirror nova's server tag:
- # https://github.com/openstack/nova/blob/master/nova/db/sqlalchemy/models.py
- project_tags_table = sql.Table(
- 'project_tag',
- meta,
- sql.Column('project_id',
- sql.String(64),
- sql.ForeignKey(project_table.c.id, ondelete='CASCADE'),
- nullable=False,
- primary_key=True),
- sql.Column('name',
- sql.Unicode(255),
- nullable=False,
- primary_key=True),
- sql.UniqueConstraint('project_id', 'name'),
- mysql_engine='InnoDB',
- mysql_charset='utf8'
- )
-
- project_tags_table.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/expand_repo/versions/031_expand_system_assignment_table.py b/keystone/common/sql/expand_repo/versions/031_expand_system_assignment_table.py
deleted file mode 100644
index 45af9863b..000000000
--- a/keystone/common/sql/expand_repo/versions/031_expand_system_assignment_table.py
+++ /dev/null
@@ -1,33 +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
- system_assignment = sql.Table(
- 'system_assignment',
- meta,
- sql.Column('type', sql.String(64), nullable=False),
- sql.Column('actor_id', sql.String(64), nullable=False),
- sql.Column('target_id', sql.String(64), nullable=False),
- sql.Column('role_id', sql.String(64), nullable=False),
- sql.Column('inherited', sql.Boolean, default=False, nullable=False),
- sql.PrimaryKeyConstraint(
- 'type', 'actor_id', 'target_id', 'role_id', 'inherited'
- ),
- mysql_engine='InnoDB',
- mysql_charset='utf8'
- )
- system_assignment.create()
diff --git a/keystone/common/sql/expand_repo/versions/032_expand_add_expired_at_int_to_trust.py b/keystone/common/sql/expand_repo/versions/032_expand_add_expired_at_int_to_trust.py
deleted file mode 100644
index fd5d6ad65..000000000
--- a/keystone/common/sql/expand_repo/versions/032_expand_add_expired_at_int_to_trust.py
+++ /dev/null
@@ -1,35 +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.
-
-
-from migrate import UniqueConstraint
-import sqlalchemy as sql
-
-from keystone.common import sql as ks_sql
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- # NOTE(morgan): column is nullable here for migration purposes
- # it is set to not-nullable in the contract phase to ensure we can handle
- # rolling upgrades in a sane way. This differs from the model in
- # keystone.identity.backends.sql_model by design.
- expires_at = sql.Column('expires_at_int', ks_sql.DateTimeInt())
- trust_table = sql.Table('trust', meta, autoload=True)
- trust_table.create_column(expires_at)
-
- UniqueConstraint('trustor_user_id', 'trustee_user_id', 'project_id',
- 'impersonation', 'expires_at', 'expires_at_int',
- table=trust_table,
- name='duplicate_trust_constraint_expanded').create()
diff --git a/keystone/common/sql/expand_repo/versions/033_expand_add_limits_tables.py b/keystone/common/sql/expand_repo/versions/033_expand_add_limits_tables.py
deleted file mode 100644
index cd6149c14..000000000
--- a/keystone/common/sql/expand_repo/versions/033_expand_add_limits_tables.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright 2018 SUSE Linux Gmbh
-# Copyright 2018 Huawei
-#
-# 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
-
- service_table = sql.Table('service', meta, autoload=True)
- region_table = sql.Table('region', meta, autoload=True)
- project_table = sql.Table('project', meta, autoload=True)
-
- registered_limit_table = sql.Table(
- 'registered_limit',
- meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('service_id',
- sql.String(255),
- sql.ForeignKey(service_table.c.id)),
- sql.Column('region_id',
- sql.String(64),
- sql.ForeignKey(region_table.c.id), 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'),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
- registered_limit_table.create(migrate_engine, checkfirst=True)
-
- limit_table = sql.Table(
- 'limit',
- meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('project_id',
- sql.String(64),
- sql.ForeignKey(project_table.c.id)),
- 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'),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
- limit_table.create(migrate_engine, checkfirst=True)
-
- migrate.ForeignKeyConstraint(
- columns=[limit_table.c.service_id,
- limit_table.c.region_id,
- limit_table.c.resource_name],
- refcolumns=[registered_limit_table.c.service_id,
- registered_limit_table.c.region_id,
- registered_limit_table.c.resource_name]).create()
diff --git a/keystone/common/sql/expand_repo/versions/034_expand_add_application_credential_table.py b/keystone/common/sql/expand_repo/versions/034_expand_add_application_credential_table.py
deleted file mode 100644
index 3ddb812bb..000000000
--- a/keystone/common/sql/expand_repo/versions/034_expand_add_application_credential_table.py
+++ /dev/null
@@ -1,52 +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
-
- application_credential = sql.Table(
- 'application_credential', meta,
- sql.Column('internal_id', sql.Integer, primary_key=True,
- nullable=False),
- sql.Column('id', sql.String(length=64), nullable=False),
- sql.Column('name', sql.String(length=255), nullable=False),
- sql.Column('secret_hash', sql.String(length=255), nullable=False),
- sql.Column('description', sql.Text),
- sql.Column('user_id', sql.String(length=64), nullable=False),
- sql.Column('project_id', sql.String(64), nullable=False),
- sql.Column('expires_at', ks_sql.DateTimeInt()),
- sql.Column('allow_application_credential_creation', sql.Boolean),
- sql.UniqueConstraint('user_id', 'name',
- name='duplicate_app_cred_constraint'),
- mysql_engine='InnoDB',
- mysql_charset='utf8'
- )
-
- application_credential_role = sql.Table(
- 'application_credential_role', meta,
- sql.Column('application_credential_id', sql.Integer,
- sql.ForeignKey(application_credential.c.internal_id,
- ondelete='CASCADE'),
- primary_key=True, nullable=False),
- sql.Column('role_id', sql.String(length=64), primary_key=True,
- nullable=False),
- mysql_engine='InnoDB', mysql_charset='utf8')
-
- application_credential.create(migrate_engine, checkfirst=True)
- application_credential_role.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/expand_repo/versions/036_expand_rename_application_credential_restriction_column.py b/keystone/common/sql/expand_repo/versions/036_expand_rename_application_credential_restriction_column.py
deleted file mode 100644
index 5d5b3ef06..000000000
--- a/keystone/common/sql/expand_repo/versions/036_expand_rename_application_credential_restriction_column.py
+++ /dev/null
@@ -1,44 +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
-
- table = sql.Table(
- 'application_credential', meta, autoload=True
- )
- # MySQL and PostgreSQL can handle a column rename.
- # Only Sqlite is special. Since Sqlite can't support an online upgrade
- # anyway, just brute-force the migration by copying the table.
- if migrate_engine.name == 'sqlite':
- old_table = table
-
- args = []
- for column in old_table.columns:
- if column.name != 'allow_application_credential_creation':
- args.append(column.copy())
- unrestricted = sql.Column('unrestricted', sql.Boolean)
- args.append(unrestricted)
- constraint = sql.UniqueConstraint('user_id', 'name',
- name='duplicate_app_cred_constraint')
- args.append(constraint)
- new_table = sql.Table('application_credential_temp',
- old_table.metadata, *args)
- new_table.create(migrate_engine, checkfirst=True)
- else:
- unrestricted = sql.Column('unrestricted', sql.Boolean())
- table.create_column(unrestricted)
diff --git a/keystone/common/sql/expand_repo/versions/037_expand_remove_service_and_region_fk_for_registered_limit.py b/keystone/common/sql/expand_repo/versions/037_expand_remove_service_and_region_fk_for_registered_limit.py
deleted file mode 100644
index 9cb40b454..000000000
--- a/keystone/common/sql/expand_repo/versions/037_expand_remove_service_and_region_fk_for_registered_limit.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/038_placeholder.py b/keystone/common/sql/expand_repo/versions/038_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/expand_repo/versions/038_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/039_placeholder.py b/keystone/common/sql/expand_repo/versions/039_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/expand_repo/versions/039_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/040_placeholder.py b/keystone/common/sql/expand_repo/versions/040_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/expand_repo/versions/040_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/041_placeholder.py b/keystone/common/sql/expand_repo/versions/041_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/expand_repo/versions/041_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/042_placeholder.py b/keystone/common/sql/expand_repo/versions/042_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/expand_repo/versions/042_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/043_placeholder.py b/keystone/common/sql/expand_repo/versions/043_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/expand_repo/versions/043_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/044_placeholder.py b/keystone/common/sql/expand_repo/versions/044_placeholder.py
deleted file mode 100644
index 71faccf92..000000000
--- a/keystone/common/sql/expand_repo/versions/044_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 Queens backports. Do not use this number for new
-# Rocky work. New Rocky work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/045_expand_add_description_to_limit.py b/keystone/common/sql/expand_repo/versions/045_expand_add_description_to_limit.py
deleted file mode 100644
index 76ea72d54..000000000
--- a/keystone/common/sql/expand_repo/versions/045_expand_add_description_to_limit.py
+++ /dev/null
@@ -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)
diff --git a/keystone/common/sql/expand_repo/versions/046_expand_old_password_data_to_password_hash_column.py b/keystone/common/sql/expand_repo/versions/046_expand_old_password_data_to_password_hash_column.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/expand_repo/versions/046_expand_old_password_data_to_password_hash_column.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/047_expand_update_pk_for_unified_limit.py b/keystone/common/sql/expand_repo/versions/047_expand_update_pk_for_unified_limit.py
deleted file mode 100644
index 13ed1b635..000000000
--- a/keystone/common/sql/expand_repo/versions/047_expand_update_pk_for_unified_limit.py
+++ /dev/null
@@ -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)
diff --git a/keystone/common/sql/expand_repo/versions/048_expand_add_registered_limit_id_column_for_limit.py b/keystone/common/sql/expand_repo/versions/048_expand_add_registered_limit_id_column_for_limit.py
deleted file mode 100644
index 05ee9c826..000000000
--- a/keystone/common/sql/expand_repo/versions/048_expand_add_registered_limit_id_column_for_limit.py
+++ /dev/null
@@ -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
diff --git a/keystone/common/sql/expand_repo/versions/049_placeholder.py b/keystone/common/sql/expand_repo/versions/049_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/expand_repo/versions/049_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/050_placeholder.py b/keystone/common/sql/expand_repo/versions/050_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/expand_repo/versions/050_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/051_placeholder.py b/keystone/common/sql/expand_repo/versions/051_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/expand_repo/versions/051_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/052_placeholder.py b/keystone/common/sql/expand_repo/versions/052_placeholder.py
deleted file mode 100644
index 8f51a8962..000000000
--- a/keystone/common/sql/expand_repo/versions/052_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 Rocky backports. Do not use this number for new
-# Stein work. New Stein work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/053_expand_add_role_description_to_role_table.py b/keystone/common/sql/expand_repo/versions/053_expand_add_role_description_to_role_table.py
deleted file mode 100644
index 99e41ff15..000000000
--- a/keystone/common/sql/expand_repo/versions/053_expand_add_role_description_to_role_table.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 sqlalchemy as sql
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- role_table = sql.Table('role', meta, autoload=True)
- description = sql.Column('description', sql.String(255),
- nullable=True)
- role_table.create_column(description)
diff --git a/keystone/common/sql/expand_repo/versions/054_expand_drop_old_passoword_column.py b/keystone/common/sql/expand_repo/versions/054_expand_drop_old_passoword_column.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/expand_repo/versions/054_expand_drop_old_passoword_column.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/055_expand_add_domain_to_limit.py b/keystone/common/sql/expand_repo/versions/055_expand_add_domain_to_limit.py
deleted file mode 100644
index c0f88ee57..000000000
--- a/keystone/common/sql/expand_repo/versions/055_expand_add_domain_to_limit.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
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- limit_table = sql.Table('limit', meta, autoload=True)
- domain_id = sql.Column('domain_id', sql.String(64), nullable=True)
- limit_table.create_column(domain_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)
- domain_id = sql.Column('domain_id', sql.String(64), nullable=True)
- limit_table_new.create_column(domain_id)
- except sql.exc.NoSuchTableError:
- pass
diff --git a/keystone/common/sql/expand_repo/versions/056_expand_add_application_credential_access_rules.py b/keystone/common/sql/expand_repo/versions/056_expand_add_application_credential_access_rules.py
deleted file mode 100644
index 5df205b00..000000000
--- a/keystone/common/sql/expand_repo/versions/056_expand_add_application_credential_access_rules.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2019 SUSE Linux GmbH
-#
-# 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
-
- application_credential = sql.Table(
- 'application_credential', meta, autoload=True)
- access_rule = sql.Table(
- 'access_rule', meta,
- sql.Column('id', sql.Integer, primary_key=True, nullable=False),
- sql.Column('service', sql.String(64)),
- sql.Column('path', sql.String(128)),
- sql.Column('method', sql.String(16)),
- mysql_engine='InnoDB', mysql_charset='utf8'
- )
- app_cred_access_rule = sql.Table(
- 'application_credential_access_rule', meta,
- sql.Column('application_credential_id', sql.Integer,
- sql.ForeignKey(application_credential.c.internal_id,
- ondelete='CASCADE'),
- primary_key=True, nullable=False),
- sql.Column('access_rule_id', sql.Integer,
- sql.ForeignKey(access_rule.c.id,
- ondelete='CASCADE'),
- primary_key=True, nullable=False),
- mysql_engine='InnoDB', mysql_charset='utf8'
- )
- access_rule.create(migrate_engine, checkfirst=True)
- app_cred_access_rule.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/expand_repo/versions/057_placeholder.py b/keystone/common/sql/expand_repo/versions/057_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/expand_repo/versions/057_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/058_placeholder.py b/keystone/common/sql/expand_repo/versions/058_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/expand_repo/versions/058_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/059_placeholder.py b/keystone/common/sql/expand_repo/versions/059_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/expand_repo/versions/059_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/060_placeholder.py b/keystone/common/sql/expand_repo/versions/060_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/expand_repo/versions/060_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/061_placeholder.py b/keystone/common/sql/expand_repo/versions/061_placeholder.py
deleted file mode 100644
index dff6bd138..000000000
--- a/keystone/common/sql/expand_repo/versions/061_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 Stein backports. Do not use this number for new
-# Train work. New Train work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/062_expand_extract_redelegation_data_from_extras.py b/keystone/common/sql/expand_repo/versions/062_expand_extract_redelegation_data_from_extras.py
deleted file mode 100644
index 7e3019eb5..000000000
--- a/keystone/common/sql/expand_repo/versions/062_expand_extract_redelegation_data_from_extras.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
-
- trust_table = sql.Table('trust', meta, autoload=True)
- trust_id_column = sql.Column(
- 'redelegated_trust_id',
- sql.String(64),
- nullable=True)
- count_column = sql.Column(
- 'redelegation_count',
- sql.Integer,
- nullable=True)
-
- trust_table.create_column(trust_id_column)
- trust_table.create_column(count_column)
diff --git a/keystone/common/sql/expand_repo/versions/063_expand_drop_limit_columns.py b/keystone/common/sql/expand_repo/versions/063_expand_drop_limit_columns.py
deleted file mode 100644
index 8aa15c1ef..000000000
--- a/keystone/common/sql/expand_repo/versions/063_expand_drop_limit_columns.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/064_expand_add_remote_id_attribute_to_federation_protocol_table.py b/keystone/common/sql/expand_repo/versions/064_expand_add_remote_id_attribute_to_federation_protocol_table.py
deleted file mode 100644
index e16c90eeb..000000000
--- a/keystone/common/sql/expand_repo/versions/064_expand_add_remote_id_attribute_to_federation_protocol_table.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 sqlalchemy as sql
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- federation_protocol_table = sql.Table(
- 'federation_protocol', meta, autoload=True)
- remote_id_attribute = sql.Column('remote_id_attribute', sql.String(64))
- federation_protocol_table.create_column(remote_id_attribute)
diff --git a/keystone/common/sql/expand_repo/versions/065_expand_add_user_external_id_to_access_rule.py b/keystone/common/sql/expand_repo/versions/065_expand_add_user_external_id_to_access_rule.py
deleted file mode 100644
index 1f687ccf3..000000000
--- a/keystone/common/sql/expand_repo/versions/065_expand_add_user_external_id_to_access_rule.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2019 SUSE Linux GmbH
-#
-# 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
-
- access_rule = sql.Table('access_rule', meta, autoload=True)
-
- external_id = sql.Column('external_id', sql.String(64))
- access_rule.create_column(external_id)
- sql.Index('external_id', access_rule.c.external_id).create()
- unique_constraint_id = migrate.UniqueConstraint('external_id',
- table=access_rule)
- unique_constraint_id.create()
-
- user_id = sql.Column('user_id', sql.String(64))
- access_rule.create_column(user_id)
- sql.Index('user_id', access_rule.c.user_id).create()
- unique_constraint_rule_for_user = migrate.UniqueConstraint(
- 'user_id', 'service', 'path', 'method',
- name='duplicate_access_rule_for_user_constraint',
- table=access_rule)
- unique_constraint_rule_for_user.create()
diff --git a/keystone/common/sql/expand_repo/versions/066_expand_add_role_and_project_option_tables.py b/keystone/common/sql/expand_repo/versions/066_expand_add_role_and_project_option_tables.py
deleted file mode 100644
index a051b5336..000000000
--- a/keystone/common/sql/expand_repo/versions/066_expand_add_role_and_project_option_tables.py
+++ /dev/null
@@ -1,51 +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
-
- role_table = sql.Table('role', meta, autoload=True)
- project_table = sql.Table('project', meta, autoload=True)
-
- role_resource_options_table = sql.Table(
- 'role_option',
- meta,
- sql.Column('role_id', sql.String(64), sql.ForeignKey(role_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'
- )
- project_resource_options_table = sql.Table(
- 'project_option',
- meta,
- sql.Column('project_id', sql.String(64),
- sql.ForeignKey(project_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'
- )
-
- project_resource_options_table.create()
- role_resource_options_table.create()
diff --git a/keystone/common/sql/expand_repo/versions/067_placeholder.py b/keystone/common/sql/expand_repo/versions/067_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/expand_repo/versions/067_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/068_placeholder.py b/keystone/common/sql/expand_repo/versions/068_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/expand_repo/versions/068_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/069_placeholder.py b/keystone/common/sql/expand_repo/versions/069_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/expand_repo/versions/069_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/070_placeholder.py b/keystone/common/sql/expand_repo/versions/070_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/expand_repo/versions/070_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/071_placeholder.py b/keystone/common/sql/expand_repo/versions/071_placeholder.py
deleted file mode 100644
index 8522ef3ce..000000000
--- a/keystone/common/sql/expand_repo/versions/071_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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/072_expand_drop_domain_id_fk.py b/keystone/common/sql/expand_repo/versions/072_expand_drop_domain_id_fk.py
deleted file mode 100644
index bb90c3de3..000000000
--- a/keystone/common/sql/expand_repo/versions/072_expand_drop_domain_id_fk.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2019 SUSE LLC
-#
-# 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 Train backports. Do not use this number for new
-# Ussuri work. New Ussuri work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/expand_repo/versions/073_expand_expiring_group_membership.py b/keystone/common/sql/expand_repo/versions/073_expand_expiring_group_membership.py
deleted file mode 100644
index 8577ee052..000000000
--- a/keystone/common/sql/expand_repo/versions/073_expand_expiring_group_membership.py
+++ /dev/null
@@ -1,47 +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
-
- identity_provider = sql.Table('identity_provider', meta, autoload=True)
- authorization_ttl = sql.Column('authorization_ttl', sql.Integer,
- nullable=True)
- identity_provider.create_column(authorization_ttl)
-
- user_table = sql.Table('user', meta, autoload=True)
- group_table = sql.Table('group', meta, autoload=True)
- idp_table = sql.Table('identity_provider', meta, autoload=True)
-
- expiring_user_group_membership = sql.Table(
- 'expiring_user_group_membership', meta,
-
- sql.Column('user_id', sql.String(64),
- sql.ForeignKey(user_table.c.id), primary_key=True),
- sql.Column('group_id', sql.String(64),
- sql.ForeignKey(group_table.c.id), primary_key=True),
- sql.Column('idp_id',
- sql.String(64),
- sql.ForeignKey(idp_table.c.id,
- ondelete='CASCADE'),
- primary_key=True),
- sql.Column('last_verified', sql.DateTime(), nullable=False),
-
- mysql_engine='InnoDB',
- mysql_charset='utf8'
- )
-
- expiring_user_group_membership.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/contract_repo/__init__.py b/keystone/common/sql/legacy_migrations/__init__.py
index e69de29bb..e69de29bb 100644
--- a/keystone/common/sql/contract_repo/__init__.py
+++ b/keystone/common/sql/legacy_migrations/__init__.py
diff --git a/keystone/common/sql/legacy_migrations/contract_repo/README.rst b/keystone/common/sql/legacy_migrations/contract_repo/README.rst
new file mode 100644
index 000000000..6ecb178cc
--- /dev/null
+++ b/keystone/common/sql/legacy_migrations/contract_repo/README.rst
@@ -0,0 +1,13 @@
+Contract repo migrations
+========================
+
+.. warning::
+
+ This repo is deprecated and will be removed in a future release. All new
+ migrations should be alembic-based and placed in
+ ``keystone/common/sql/migrations``.
+
+Contract-style or destructive migrations for the database.
+
+This is a database migration repository. More information at
+https://opendev.org/x/sqlalchemy-migrate
diff --git a/keystone/common/sql/contract_repo/versions/__init__.py b/keystone/common/sql/legacy_migrations/contract_repo/__init__.py
index e69de29bb..e69de29bb 100644
--- a/keystone/common/sql/contract_repo/versions/__init__.py
+++ b/keystone/common/sql/legacy_migrations/contract_repo/__init__.py
diff --git a/keystone/common/sql/contract_repo/manage.py b/keystone/common/sql/legacy_migrations/contract_repo/manage.py
index 41cba1adb..41cba1adb 100644
--- a/keystone/common/sql/contract_repo/manage.py
+++ b/keystone/common/sql/legacy_migrations/contract_repo/manage.py
diff --git a/keystone/common/sql/contract_repo/migrate.cfg b/keystone/common/sql/legacy_migrations/contract_repo/migrate.cfg
index fd50aa546..fd50aa546 100644
--- a/keystone/common/sql/contract_repo/migrate.cfg
+++ b/keystone/common/sql/legacy_migrations/contract_repo/migrate.cfg
diff --git a/keystone/common/sql/contract_repo/versions/001_contract_initial_null_migration.py b/keystone/common/sql/legacy_migrations/contract_repo/versions/073_contract_initial_migration.py
index 1cd34e617..1cd34e617 100644
--- a/keystone/common/sql/contract_repo/versions/001_contract_initial_null_migration.py
+++ b/keystone/common/sql/legacy_migrations/contract_repo/versions/073_contract_initial_migration.py
diff --git a/keystone/common/sql/contract_repo/versions/074_placeholder.py b/keystone/common/sql/legacy_migrations/contract_repo/versions/074_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/contract_repo/versions/074_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/contract_repo/versions/074_placeholder.py
diff --git a/keystone/common/sql/contract_repo/versions/075_placeholder.py b/keystone/common/sql/legacy_migrations/contract_repo/versions/075_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/contract_repo/versions/075_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/contract_repo/versions/075_placeholder.py
diff --git a/keystone/common/sql/contract_repo/versions/076_placeholder.py b/keystone/common/sql/legacy_migrations/contract_repo/versions/076_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/contract_repo/versions/076_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/contract_repo/versions/076_placeholder.py
diff --git a/keystone/common/sql/contract_repo/versions/077_placeholder.py b/keystone/common/sql/legacy_migrations/contract_repo/versions/077_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/contract_repo/versions/077_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/contract_repo/versions/077_placeholder.py
diff --git a/keystone/common/sql/contract_repo/versions/078_placeholder.py b/keystone/common/sql/legacy_migrations/contract_repo/versions/078_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/contract_repo/versions/078_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/contract_repo/versions/078_placeholder.py
diff --git a/keystone/common/sql/contract_repo/versions/079_contract_update_local_id_limit.py b/keystone/common/sql/legacy_migrations/contract_repo/versions/079_contract_update_local_id_limit.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/contract_repo/versions/079_contract_update_local_id_limit.py
+++ b/keystone/common/sql/legacy_migrations/contract_repo/versions/079_contract_update_local_id_limit.py
diff --git a/keystone/common/sql/data_migration_repo/__init__.py b/keystone/common/sql/legacy_migrations/contract_repo/versions/__init__.py
index e69de29bb..e69de29bb 100644
--- a/keystone/common/sql/data_migration_repo/__init__.py
+++ b/keystone/common/sql/legacy_migrations/contract_repo/versions/__init__.py
diff --git a/keystone/common/sql/legacy_migrations/data_migration_repo/README.rst b/keystone/common/sql/legacy_migrations/data_migration_repo/README.rst
new file mode 100644
index 000000000..0b4202f9f
--- /dev/null
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/README.rst
@@ -0,0 +1,13 @@
+Data migration repo migrations
+==============================
+
+.. warning::
+
+ This repo is deprecated and will be removed in a future release. All new
+ migrations should be alembic-based and placed in
+ ``keystone/common/sql/migrations``.
+
+Data migrations for the database.
+
+This is a database migration repository. More information at
+https://opendev.org/x/sqlalchemy-migrate
diff --git a/keystone/common/sql/data_migration_repo/versions/__init__.py b/keystone/common/sql/legacy_migrations/data_migration_repo/__init__.py
index e69de29bb..e69de29bb 100644
--- a/keystone/common/sql/data_migration_repo/versions/__init__.py
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/__init__.py
diff --git a/keystone/common/sql/data_migration_repo/manage.py b/keystone/common/sql/legacy_migrations/data_migration_repo/manage.py
index 41cba1adb..41cba1adb 100644
--- a/keystone/common/sql/data_migration_repo/manage.py
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/manage.py
diff --git a/keystone/common/sql/data_migration_repo/migrate.cfg b/keystone/common/sql/legacy_migrations/data_migration_repo/migrate.cfg
index 97f8e1d0e..97f8e1d0e 100644
--- a/keystone/common/sql/data_migration_repo/migrate.cfg
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/migrate.cfg
diff --git a/keystone/common/sql/migrate_repo/versions/089_add_root_of_all_domains.py b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/073_migrate_initial_migration.py
index 477c719a6..d05b151b8 100644
--- a/keystone/common/sql/migrate_repo/versions/089_add_root_of_all_domains.py
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/073_migrate_initial_migration.py
@@ -10,11 +10,12 @@
# License for the specific language governing permissions and limitations
# under the License.
-import sqlalchemy as sql
+# A null initial migration to open this repo. Do not re-use replace this with
+# a real migration, add additional ones in subsequent version scripts.
+import sqlalchemy as sql
+import sqlalchemy.orm
-_PROJECT_TABLE_NAME = 'project'
-_DOMAIN_TABLE_NAME = 'domain'
NULL_DOMAIN_ID = '<<keystone.domain.root>>'
@@ -37,39 +38,18 @@ def upgrade(migrate_engine):
'domain_id': NULL_DOMAIN_ID,
'is_domain': True,
'parent_id': None,
- 'extra': '{}'
+ 'extra': '{}',
}
return project_ref
- def _generate_root_domain():
- # Generate a similar root for the domain table, this is an interim
- # step so as to allow continuation of current project domain_id FK.
- #
- # This special domain is filtered out by the driver, so is never
- # visible to the manager or API.
-
- domain_ref = {
- 'id': NULL_DOMAIN_ID,
- 'name': NULL_DOMAIN_ID,
- 'enabled': False,
- 'extra': '{}'
- }
- return domain_ref
-
meta = sql.MetaData()
meta.bind = migrate_engine
session = sql.orm.sessionmaker(bind=migrate_engine)()
- project_table = sql.Table(_PROJECT_TABLE_NAME, meta, autoload=True)
- domain_table = sql.Table(_DOMAIN_TABLE_NAME, meta, autoload=True)
-
- root_domain = _generate_root_domain()
- new_entry = domain_table.insert().values(**root_domain)
- session.execute(new_entry)
- session.commit()
+ project = sql.Table('project', meta, autoload=True)
root_domain_project = _generate_root_domain_project()
- new_entry = project_table.insert().values(**root_domain_project)
+ new_entry = project.insert().values(**root_domain_project)
session.execute(new_entry)
session.commit()
diff --git a/keystone/common/sql/data_migration_repo/versions/074_placeholder.py b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/074_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/data_migration_repo/versions/074_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/074_placeholder.py
diff --git a/keystone/common/sql/data_migration_repo/versions/075_placeholder.py b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/075_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/data_migration_repo/versions/075_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/075_placeholder.py
diff --git a/keystone/common/sql/data_migration_repo/versions/076_placeholder.py b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/076_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/data_migration_repo/versions/076_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/076_placeholder.py
diff --git a/keystone/common/sql/data_migration_repo/versions/077_placeholder.py b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/077_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/data_migration_repo/versions/077_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/077_placeholder.py
diff --git a/keystone/common/sql/data_migration_repo/versions/078_placeholder.py b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/078_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/data_migration_repo/versions/078_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/078_placeholder.py
diff --git a/keystone/common/sql/data_migration_repo/versions/079_migrate_update_local_id_limit.py b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/079_migrate_update_local_id_limit.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/data_migration_repo/versions/079_migrate_update_local_id_limit.py
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/079_migrate_update_local_id_limit.py
diff --git a/keystone/common/sql/migrate_repo/__init__.py b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/__init__.py
index e69de29bb..e69de29bb 100644
--- a/keystone/common/sql/migrate_repo/__init__.py
+++ b/keystone/common/sql/legacy_migrations/data_migration_repo/versions/__init__.py
diff --git a/keystone/common/sql/legacy_migrations/expand_repo/README.rst b/keystone/common/sql/legacy_migrations/expand_repo/README.rst
new file mode 100644
index 000000000..6019e2d6c
--- /dev/null
+++ b/keystone/common/sql/legacy_migrations/expand_repo/README.rst
@@ -0,0 +1,13 @@
+Expand repo migrations
+======================
+
+.. warning::
+
+ This repo is deprecated and will be removed in a future release. All new
+ migrations should be alembic-based and placed in
+ ``keystone/common/sql/migrations``.
+
+Expand-style or additive migrations for the database.
+
+This is a database migration repository. More information at
+https://opendev.org/x/sqlalchemy-migrate
diff --git a/keystone/common/sql/expand_repo/__init__.py b/keystone/common/sql/legacy_migrations/expand_repo/__init__.py
index 84e0fb83b..84e0fb83b 100644
--- a/keystone/common/sql/expand_repo/__init__.py
+++ b/keystone/common/sql/legacy_migrations/expand_repo/__init__.py
diff --git a/keystone/common/sql/expand_repo/manage.py b/keystone/common/sql/legacy_migrations/expand_repo/manage.py
index 41cba1adb..41cba1adb 100644
--- a/keystone/common/sql/expand_repo/manage.py
+++ b/keystone/common/sql/legacy_migrations/expand_repo/manage.py
diff --git a/keystone/common/sql/expand_repo/migrate.cfg b/keystone/common/sql/legacy_migrations/expand_repo/migrate.cfg
index 74a33e330..74a33e330 100644
--- a/keystone/common/sql/expand_repo/migrate.cfg
+++ b/keystone/common/sql/legacy_migrations/expand_repo/migrate.cfg
diff --git a/keystone/common/sql/legacy_migrations/expand_repo/versions/073_expand_initial_migration.py b/keystone/common/sql/legacy_migrations/expand_repo/versions/073_expand_initial_migration.py
new file mode 100644
index 000000000..00efa6ee1
--- /dev/null
+++ b/keystone/common/sql/legacy_migrations/expand_repo/versions/073_expand_initial_migration.py
@@ -0,0 +1,1183 @@
+# 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 datetime
+import textwrap
+
+import migrate
+from oslo_log import log
+import sqlalchemy as sql
+
+from keystone.assignment.backends import sql as assignment_sql
+from keystone.common import sql as ks_sql
+import keystone.conf
+from keystone.identity.mapping_backends import mapping as mapping_backend
+
+CONF = keystone.conf.CONF
+LOG = log.getLogger(__name__)
+
+# FIXME(stephenfin): Remove this as soon as we're done reworking the
+# migrations. Until then, this is necessary to allow us to use the native
+# sqlalchemy-migrate tooling (which won't register opts). Alternatively, maybe
+# the server default *shouldn't* rely on a (changeable) config option value?
+try:
+ service_provider_relay_state_prefix_default = CONF.saml.relay_state_prefix
+except Exception:
+ service_provider_relay_state_prefix_default = 'ss:mem:'
+
+
+def upgrade(migrate_engine):
+ meta = sql.MetaData()
+ meta.bind = migrate_engine
+
+ if migrate_engine.name == 'mysql':
+ # In Folsom we explicitly converted migrate_version to UTF8.
+ migrate_engine.execute(
+ 'ALTER TABLE migrate_version CONVERT TO CHARACTER SET utf8'
+ )
+ # Set default DB charset to UTF8.
+ migrate_engine.execute(
+ 'ALTER DATABASE %s DEFAULT CHARACTER SET utf8'
+ % migrate_engine.url.database
+ )
+
+ application_credential = sql.Table(
+ 'application_credential',
+ meta,
+ sql.Column(
+ 'internal_id', sql.Integer, primary_key=True, nullable=False
+ ),
+ sql.Column('id', sql.String(length=64), nullable=False),
+ sql.Column('name', sql.String(length=255), nullable=False),
+ sql.Column('secret_hash', sql.String(length=255), nullable=False),
+ sql.Column('description', sql.Text),
+ sql.Column('user_id', sql.String(length=64), nullable=False),
+ sql.Column('project_id', sql.String(64), nullable=True),
+ sql.Column('expires_at', ks_sql.DateTimeInt()),
+ sql.Column('system', sql.String(64), nullable=True),
+ sql.Column('unrestricted', sql.Boolean),
+ sql.UniqueConstraint(
+ 'user_id', 'name', name='duplicate_app_cred_constraint'
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ assignment = sql.Table(
+ 'assignment',
+ meta,
+ sql.Column(
+ 'type',
+ sql.Enum(
+ assignment_sql.AssignmentType.USER_PROJECT,
+ assignment_sql.AssignmentType.GROUP_PROJECT,
+ assignment_sql.AssignmentType.USER_DOMAIN,
+ assignment_sql.AssignmentType.GROUP_DOMAIN,
+ name='type',
+ ),
+ nullable=False,
+ ),
+ sql.Column('actor_id', sql.String(64), nullable=False),
+ sql.Column('target_id', sql.String(64), nullable=False),
+ sql.Column('role_id', sql.String(64), nullable=False),
+ sql.Column('inherited', sql.Boolean, default=False, nullable=False),
+ sql.PrimaryKeyConstraint(
+ 'type',
+ 'actor_id',
+ 'target_id',
+ 'role_id',
+ 'inherited',
+ ),
+ sql.Index('ix_actor_id', 'actor_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ access_rule = sql.Table(
+ 'access_rule',
+ meta,
+ sql.Column('id', sql.Integer, primary_key=True, nullable=False),
+ sql.Column('service', sql.String(64)),
+ sql.Column('path', sql.String(128)),
+ sql.Column('method', sql.String(16)),
+ sql.Column('external_id', sql.String(64)),
+ sql.Column('user_id', sql.String(64)),
+ sql.UniqueConstraint(
+ 'external_id',
+ name='access_rule_external_id_key',
+ ),
+ sql.UniqueConstraint(
+ 'user_id',
+ 'service',
+ 'path',
+ 'method',
+ name='duplicate_access_rule_for_user_constraint',
+ ),
+ sql.Index('user_id', 'user_id'),
+ sql.Index('external_id', 'external_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ config_register = sql.Table(
+ 'config_register',
+ meta,
+ sql.Column('type', sql.String(64), primary_key=True),
+ sql.Column('domain_id', sql.String(64), nullable=False),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ consumer = sql.Table(
+ 'consumer',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True, nullable=False),
+ sql.Column('description', sql.String(64), nullable=True),
+ sql.Column('secret', sql.String(64), nullable=False),
+ sql.Column('extra', sql.Text(), nullable=False),
+ )
+
+ credential = sql.Table(
+ 'credential',
+ meta,
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('user_id', sql.String(length=64), nullable=False),
+ sql.Column('project_id', sql.String(length=64)),
+ sql.Column('type', sql.String(length=255), nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column('key_hash', sql.String(64), nullable=False),
+ sql.Column(
+ 'encrypted_blob',
+ ks_sql.Text,
+ nullable=False,
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ group = sql.Table(
+ 'group',
+ meta,
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('domain_id', sql.String(length=64), nullable=False),
+ sql.Column('name', sql.String(length=64), nullable=False),
+ sql.Column('description', sql.Text),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ migrate.UniqueConstraint(
+ 'domain_id',
+ 'name',
+ name='ixu_group_name_domain_id',
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ id_mapping = sql.Table(
+ 'id_mapping',
+ meta,
+ sql.Column('public_id', sql.String(64), primary_key=True),
+ sql.Column('domain_id', sql.String(64), nullable=False),
+ sql.Column('local_id', sql.String(64), nullable=False),
+ sql.Column(
+ 'entity_type',
+ sql.Enum(
+ mapping_backend.EntityType.USER,
+ mapping_backend.EntityType.GROUP,
+ name='entity_type',
+ ),
+ nullable=False,
+ ),
+ migrate.UniqueConstraint(
+ 'domain_id',
+ 'local_id',
+ 'entity_type',
+ name='domain_id',
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ identity_provider = sql.Table(
+ 'identity_provider',
+ meta,
+ 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),
+ sql.Column('authorization_ttl', sql.Integer, nullable=True),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ idp_remote_ids = sql.Table(
+ 'idp_remote_ids',
+ meta,
+ sql.Column(
+ 'idp_id',
+ sql.String(64),
+ sql.ForeignKey(identity_provider.c.id, ondelete='CASCADE'),
+ ),
+ sql.Column('remote_id', sql.String(255), primary_key=True),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ mapping = sql.Table(
+ 'mapping',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('rules', sql.Text(), nullable=False),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ policy = sql.Table(
+ 'policy',
+ meta,
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('type', sql.String(length=255), nullable=False),
+ sql.Column('blob', ks_sql.JsonBlob, nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ policy_association = sql.Table(
+ 'policy_association',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('policy_id', sql.String(64), nullable=False),
+ sql.Column('endpoint_id', sql.String(64), nullable=True),
+ sql.Column('service_id', sql.String(64), nullable=True),
+ sql.Column('region_id', sql.String(64), nullable=True),
+ sql.UniqueConstraint('endpoint_id', 'service_id', 'region_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ project = sql.Table(
+ 'project',
+ meta,
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('name', sql.String(length=64), nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column('description', sql.Text),
+ sql.Column('enabled', sql.Boolean),
+ sql.Column(
+ 'domain_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ 'project.id',
+ name='project_domain_id_fkey',
+ ),
+ nullable=False,
+ ),
+ sql.Column(
+ 'parent_id',
+ sql.String(64),
+ sql.ForeignKey(
+ 'project.id',
+ name='project_parent_id_fkey',
+ ),
+ nullable=True,
+ ),
+ sql.Column(
+ 'is_domain',
+ sql.Boolean,
+ nullable=False,
+ server_default='0',
+ default=False,
+ ),
+ migrate.UniqueConstraint(
+ 'domain_id',
+ 'name',
+ name='ixu_project_name_domain_id',
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ project_endpoint = sql.Table(
+ 'project_endpoint',
+ meta,
+ sql.Column(
+ 'endpoint_id', sql.String(64), primary_key=True, nullable=False
+ ),
+ sql.Column(
+ 'project_id', sql.String(64), primary_key=True, nullable=False
+ ),
+ )
+
+ project_option = sql.Table(
+ 'project_option',
+ meta,
+ sql.Column(
+ 'project_id',
+ sql.String(64),
+ sql.ForeignKey(project.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',
+ )
+
+ # NOTE(lamt) To allow tag name to be case sensitive for MySQL, the 'name'
+ # column needs to use collation, which is incompatible with Postgresql.
+ # Using unicode to mirror nova's server tag:
+ # https://github.com/openstack/nova/blob/master/nova/db/sqlalchemy/models.py
+ project_tag = sql.Table(
+ 'project_tag',
+ meta,
+ sql.Column(
+ 'project_id',
+ sql.String(64),
+ sql.ForeignKey(project.c.id, ondelete='CASCADE'),
+ nullable=False,
+ primary_key=True,
+ ),
+ sql.Column('name', sql.Unicode(255), nullable=False, primary_key=True),
+ sql.UniqueConstraint('project_id', 'name'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ region = sql.Table(
+ 'region',
+ meta,
+ sql.Column('id', sql.String(255), primary_key=True),
+ sql.Column('description', sql.String(255), nullable=False),
+ sql.Column('parent_region_id', sql.String(255), nullable=True),
+ sql.Column('extra', sql.Text()),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ registered_limit = sql.Table(
+ 'registered_limit',
+ meta,
+ 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.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',
+ )
+
+ request_token = sql.Table(
+ 'request_token',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True, nullable=False),
+ sql.Column('request_secret', sql.String(64), nullable=False),
+ sql.Column('verifier', sql.String(64), nullable=True),
+ sql.Column('authorizing_user_id', sql.String(64), nullable=True),
+ sql.Column('requested_project_id', sql.String(64), nullable=False),
+ sql.Column('role_ids', sql.Text(), nullable=True),
+ sql.Column(
+ 'consumer_id',
+ sql.String(64),
+ sql.ForeignKey(consumer.c.id),
+ nullable=False,
+ index=True,
+ ),
+ sql.Column('expires_at', sql.String(64), nullable=True),
+ )
+
+ revocation_event = sql.Table(
+ 'revocation_event',
+ meta,
+ sql.Column('id', sql.Integer, primary_key=True),
+ sql.Column('domain_id', sql.String(64)),
+ sql.Column('project_id', sql.String(64)),
+ sql.Column('user_id', sql.String(64)),
+ sql.Column('role_id', sql.String(64)),
+ sql.Column('trust_id', sql.String(64)),
+ sql.Column('consumer_id', sql.String(64)),
+ sql.Column('access_token_id', sql.String(64)),
+ sql.Column('issued_before', sql.DateTime(), nullable=False),
+ sql.Column('expires_at', sql.DateTime()),
+ sql.Column('revoked_at', sql.DateTime(), nullable=False),
+ sql.Column('audit_id', sql.String(32), nullable=True),
+ sql.Column('audit_chain_id', sql.String(32), nullable=True),
+ # NOTE(stephenfin): The '_new' suffix here is due to migration 095,
+ # which changed the 'id' column from String(64) to Integer. It did this
+ # by creating a 'revocation_event_new' table and populating it with
+ # data from the 'revocation_event' table before deleting the
+ # 'revocation_event' table and renaming the 'revocation_event_new'
+ # table to 'revocation_event'. Because the 'revoked_at' column had
+ # 'index=True', sqlalchemy automatically generated the index name as
+ # 'ix_{table}_{column}'. However, when intitially created, '{table}'
+ # 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(
+ 'role',
+ meta,
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('name', sql.String(length=255), nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column(
+ 'domain_id',
+ sql.String(64),
+ nullable=False,
+ server_default='<<null>>',
+ ),
+ sql.Column('description', sql.String(255), nullable=True),
+ migrate.UniqueConstraint(
+ 'name',
+ 'domain_id',
+ name='ixu_role_name_domain_id',
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ role_option = sql.Table(
+ 'role_option',
+ meta,
+ sql.Column(
+ 'role_id',
+ sql.String(64),
+ sql.ForeignKey(role.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',
+ )
+
+ sensitive_config = sql.Table(
+ 'sensitive_config',
+ meta,
+ sql.Column('domain_id', sql.String(64), primary_key=True),
+ sql.Column('group', sql.String(255), primary_key=True),
+ sql.Column('option', sql.String(255), primary_key=True),
+ sql.Column('value', ks_sql.JsonBlob.impl, nullable=False),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ service = sql.Table(
+ 'service',
+ meta,
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('type', sql.String(length=255)),
+ sql.Column(
+ 'enabled',
+ sql.Boolean,
+ nullable=False,
+ default=True,
+ server_default='1',
+ ),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ service_provider = sql.Table(
+ 'service_provider',
+ meta,
+ sql.Column('auth_url', sql.String(256), nullable=False),
+ 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('sp_url', sql.String(256), nullable=False),
+ sql.Column(
+ 'relay_state_prefix',
+ sql.String(256),
+ nullable=False,
+ server_default=service_provider_relay_state_prefix_default,
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ system_assignment = sql.Table(
+ 'system_assignment',
+ meta,
+ sql.Column('type', sql.String(64), nullable=False),
+ sql.Column('actor_id', sql.String(64), nullable=False),
+ sql.Column('target_id', sql.String(64), nullable=False),
+ sql.Column('role_id', sql.String(64), nullable=False),
+ sql.Column('inherited', sql.Boolean, default=False, nullable=False),
+ sql.PrimaryKeyConstraint(
+ 'type', 'actor_id', 'target_id', 'role_id', 'inherited'
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ token = sql.Table(
+ 'token',
+ meta,
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('expires', sql.DateTime, default=None),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column('valid', sql.Boolean, default=True, nullable=False),
+ 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_user_id', 'user_id'),
+ sql.Index('ix_token_trust_id', 'trust_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ trust = sql.Table(
+ 'trust',
+ meta,
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('trustor_user_id', sql.String(length=64), nullable=False),
+ sql.Column('trustee_user_id', sql.String(length=64), nullable=False),
+ sql.Column('project_id', sql.String(length=64)),
+ sql.Column('impersonation', sql.Boolean, nullable=False),
+ sql.Column('deleted_at', sql.DateTime),
+ sql.Column('expires_at', sql.DateTime),
+ sql.Column('remaining_uses', sql.Integer, nullable=True),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column('expires_at_int', ks_sql.DateTimeInt()),
+ sql.UniqueConstraint(
+ 'trustor_user_id',
+ 'trustee_user_id',
+ 'project_id',
+ 'impersonation',
+ 'expires_at',
+ 'expires_at_int',
+ name='duplicate_trust_constraint_expanded',
+ ),
+ sql.Column(
+ 'redelegated_trust_id',
+ sql.String(64),
+ nullable=True,
+ ),
+ sql.Column(
+ 'redelegation_count',
+ sql.Integer,
+ nullable=True,
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ trust_role = sql.Table(
+ 'trust_role',
+ meta,
+ sql.Column(
+ 'trust_id', sql.String(length=64), primary_key=True, nullable=False
+ ),
+ sql.Column(
+ 'role_id', sql.String(length=64), primary_key=True, nullable=False
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ user = sql.Table(
+ 'user',
+ meta,
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column('enabled', sql.Boolean),
+ 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), nullable=False),
+ sql.UniqueConstraint('id', 'domain_id', name='ixu_user_id_domain_id'),
+ sql.Index('ix_default_project_id', 'default_project_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ user_group_membership = sql.Table(
+ 'user_group_membership',
+ meta,
+ sql.Column(
+ 'user_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ user.c.id,
+ name='fk_user_group_membership_user_id',
+ ),
+ primary_key=True,
+ ),
+ sql.Column(
+ 'group_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ group.c.id,
+ name='fk_user_group_membership_group_id',
+ ),
+ primary_key=True,
+ ),
+ # NOTE(stevemar): The index was named 'group_id' in
+ # 050_fk_consistent_indexes.py and needs to be preserved
+ sql.Index('group_id', 'group_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',
+ )
+
+ whitelisted_config = sql.Table(
+ 'whitelisted_config',
+ meta,
+ sql.Column('domain_id', sql.String(64), primary_key=True),
+ sql.Column('group', sql.String(255), primary_key=True),
+ sql.Column('option', sql.String(255), primary_key=True),
+ sql.Column('value', ks_sql.JsonBlob.impl, nullable=False),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ access_token = sql.Table(
+ 'access_token',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True, nullable=False),
+ sql.Column('access_secret', sql.String(64), nullable=False),
+ sql.Column(
+ 'authorizing_user_id', sql.String(64), nullable=False, index=True
+ ),
+ sql.Column('project_id', sql.String(64), nullable=False),
+ sql.Column('role_ids', sql.Text(), nullable=False),
+ sql.Column(
+ 'consumer_id',
+ sql.String(64),
+ sql.ForeignKey(consumer.c.id),
+ nullable=False,
+ index=True,
+ ),
+ sql.Column('expires_at', sql.String(64), nullable=True),
+ )
+
+ application_credential_role = sql.Table(
+ 'application_credential_role',
+ meta,
+ sql.Column(
+ 'application_credential_id',
+ sql.Integer,
+ sql.ForeignKey(
+ application_credential.c.internal_id, ondelete='CASCADE'
+ ),
+ primary_key=True,
+ nullable=False,
+ ),
+ sql.Column(
+ 'role_id', sql.String(length=64), primary_key=True, nullable=False
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ application_credential_access_rule = sql.Table(
+ 'application_credential_access_rule',
+ meta,
+ sql.Column(
+ 'application_credential_id',
+ sql.Integer,
+ sql.ForeignKey(
+ application_credential.c.internal_id, ondelete='CASCADE'
+ ),
+ primary_key=True,
+ nullable=False,
+ ),
+ sql.Column(
+ 'access_rule_id',
+ sql.Integer,
+ sql.ForeignKey(access_rule.c.id, ondelete='CASCADE'),
+ primary_key=True,
+ nullable=False,
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ endpoint = sql.Table(
+ 'endpoint',
+ meta,
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('legacy_endpoint_id', sql.String(length=64)),
+ sql.Column('interface', sql.String(length=8), nullable=False),
+ sql.Column(
+ 'service_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ service.c.id,
+ name='endpoint_service_id_fkey',
+ ),
+ nullable=False,
+ ),
+ sql.Column('url', sql.Text, nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column(
+ 'enabled',
+ sql.Boolean,
+ nullable=False,
+ default=True,
+ server_default='1',
+ ),
+ sql.Column(
+ 'region_id',
+ sql.String(length=255),
+ sql.ForeignKey(
+ region.c.id,
+ name='fk_endpoint_region_id',
+ ),
+ nullable=True,
+ ),
+ # NOTE(stevemar): The index was named 'service_id' in
+ # 050_fk_consistent_indexes.py and needs to be preserved
+ sql.Index('service_id', 'service_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ endpoint_group = sql.Table(
+ 'endpoint_group',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('name', sql.String(255), nullable=False),
+ sql.Column('description', sql.Text, nullable=True),
+ sql.Column('filters', sql.Text(), nullable=False),
+ )
+
+ expiring_user_group_membership = sql.Table(
+ 'expiring_user_group_membership',
+ meta,
+ sql.Column(
+ 'user_id',
+ sql.String(64),
+ sql.ForeignKey(user.c.id),
+ primary_key=True,
+ ),
+ sql.Column(
+ 'group_id',
+ sql.String(64),
+ sql.ForeignKey(group.c.id),
+ primary_key=True,
+ ),
+ sql.Column(
+ 'idp_id',
+ sql.String(64),
+ sql.ForeignKey(identity_provider.c.id, ondelete='CASCADE'),
+ primary_key=True,
+ ),
+ sql.Column('last_verified', sql.DateTime(), nullable=False),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ federation_protocol = sql.Table(
+ 'federation_protocol',
+ meta,
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column(
+ 'idp_id',
+ sql.String(64),
+ sql.ForeignKey(identity_provider.c.id, ondelete='CASCADE'),
+ primary_key=True,
+ ),
+ sql.Column('mapping_id', sql.String(64), nullable=False),
+ sql.Column('remote_id_attribute', sql.String(64)),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ implied_role = sql.Table(
+ 'implied_role',
+ meta,
+ sql.Column(
+ 'prior_role_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ role.c.id,
+ name='implied_role_prior_role_id_fkey',
+ ondelete='CASCADE',
+ ),
+ primary_key=True,
+ ),
+ sql.Column(
+ 'implied_role_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ role.c.id,
+ name='implied_role_implied_role_id_fkey',
+ ondelete='CASCADE',
+ ),
+ primary_key=True,
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ limit = sql.Table(
+ 'limit',
+ meta,
+ sql.Column('id', sql.String(length=64), nullable=False),
+ sql.Column('project_id', sql.String(64), nullable=True),
+ sql.Column('resource_limit', sql.Integer, nullable=False),
+ 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),
+ ),
+ sql.Column('domain_id', sql.String(64), nullable=True),
+ # 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',
+ )
+
+ local_user = sql.Table(
+ 'local_user',
+ meta,
+ sql.Column('id', sql.Integer, primary_key=True, nullable=False),
+ sql.Column(
+ 'user_id',
+ sql.String(64),
+ nullable=False,
+ unique=True,
+ ),
+ sql.Column('domain_id', sql.String(64), nullable=False),
+ sql.Column('name', sql.String(255), nullable=False),
+ sql.Column('failed_auth_count', sql.Integer, nullable=True),
+ sql.Column('failed_auth_at', sql.DateTime(), nullable=True),
+ sql.ForeignKeyConstraint(
+ ['user_id', 'domain_id'],
+ [user.c.id, user.c.domain_id],
+ name='local_user_user_id_fkey',
+ onupdate='CASCADE',
+ ondelete='CASCADE',
+ ),
+ sql.UniqueConstraint('domain_id', 'name'),
+ )
+
+ nonlocal_user = sql.Table(
+ 'nonlocal_user',
+ meta,
+ sql.Column('domain_id', sql.String(64), primary_key=True),
+ sql.Column('name', sql.String(255), primary_key=True),
+ sql.Column(
+ 'user_id',
+ sql.String(64),
+ nullable=False,
+ ),
+ sql.ForeignKeyConstraint(
+ ['user_id', 'domain_id'],
+ [user.c.id, user.c.domain_id],
+ name='nonlocal_user_user_id_fkey',
+ onupdate='CASCADE',
+ ondelete='CASCADE',
+ ),
+ sql.UniqueConstraint('user_id', name='ixu_nonlocal_user_user_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ password = sql.Table(
+ 'password',
+ meta,
+ sql.Column('id', sql.Integer, primary_key=True, nullable=False),
+ sql.Column(
+ 'local_user_id',
+ sql.Integer,
+ sql.ForeignKey(local_user.c.id, ondelete='CASCADE'),
+ nullable=False,
+ ),
+ sql.Column('expires_at', sql.DateTime(), nullable=True),
+ sql.Column(
+ 'self_service',
+ sql.Boolean,
+ nullable=False,
+ server_default='0',
+ default=False,
+ ),
+ # NOTE(notmorgan): To support the full range of scrypt and pbkfd
+ # password hash lengths, this should be closer to varchar(1500) instead
+ # of varchar(255).
+ sql.Column('password_hash', sql.String(255), nullable=True),
+ sql.Column(
+ 'created_at_int',
+ ks_sql.DateTimeInt(),
+ nullable=False,
+ default=0,
+ server_default='0',
+ ),
+ sql.Column('expires_at_int', ks_sql.DateTimeInt(), nullable=True),
+ sql.Column(
+ 'created_at',
+ sql.DateTime(),
+ nullable=False,
+ default=datetime.datetime.utcnow,
+ ),
+ )
+
+ project_endpoint_group = sql.Table(
+ 'project_endpoint_group',
+ meta,
+ sql.Column(
+ 'endpoint_group_id',
+ sql.String(64),
+ sql.ForeignKey(endpoint_group.c.id),
+ nullable=False,
+ ),
+ sql.Column('project_id', sql.String(64), nullable=False),
+ sql.PrimaryKeyConstraint('endpoint_group_id', 'project_id'),
+ )
+
+ federated_user = sql.Table(
+ 'federated_user',
+ meta,
+ sql.Column('id', sql.Integer, primary_key=True, nullable=False),
+ sql.Column(
+ 'user_id',
+ sql.String(64),
+ sql.ForeignKey(user.c.id, ondelete='CASCADE'),
+ nullable=False,
+ ),
+ sql.Column(
+ 'idp_id',
+ sql.String(64),
+ sql.ForeignKey(identity_provider.c.id, ondelete='CASCADE'),
+ nullable=False,
+ ),
+ sql.Column('protocol_id', sql.String(64), nullable=False),
+ sql.Column('unique_id', sql.String(255), nullable=False),
+ sql.Column('display_name', sql.String(255), nullable=True),
+ sql.ForeignKeyConstraint(
+ ['protocol_id', 'idp_id'],
+ [federation_protocol.c.id, federation_protocol.c.idp_id],
+ name='federated_user_protocol_id_fkey',
+ ondelete='CASCADE',
+ ),
+ sql.UniqueConstraint('idp_id', 'protocol_id', 'unique_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ # create all tables
+ tables = [
+ access_rule,
+ application_credential,
+ assignment,
+ config_register,
+ consumer,
+ credential,
+ group,
+ id_mapping,
+ identity_provider,
+ idp_remote_ids,
+ mapping,
+ policy,
+ policy_association,
+ project,
+ project_endpoint,
+ project_option,
+ project_tag,
+ region,
+ registered_limit,
+ request_token,
+ revocation_event,
+ role,
+ role_option,
+ sensitive_config,
+ service,
+ service_provider,
+ system_assignment,
+ token,
+ trust,
+ trust_role,
+ user,
+ user_group_membership,
+ user_option,
+ whitelisted_config,
+
+ access_token,
+ application_credential_access_rule,
+ application_credential_role,
+ endpoint,
+ endpoint_group,
+ expiring_user_group_membership,
+ federation_protocol,
+ implied_role,
+ limit,
+ local_user,
+ nonlocal_user,
+ password,
+ project_endpoint_group,
+
+ federated_user,
+ ]
+
+ for table in tables:
+ try:
+ table.create()
+ except Exception:
+ LOG.exception('Exception while creating table: %r', table)
+ raise
+
+ fkeys = []
+
+ if migrate_engine.name == 'sqlite':
+ # NOTE(stevemar): We need to keep this FK constraint due to 073, but
+ # only for sqlite, once we collapse 073 we can remove this constraint
+ fkeys.append(
+ {
+ 'columns': [assignment.c.role_id],
+ 'references': [role.c.id],
+ 'name': 'fk_assignment_role_id',
+ },
+ )
+
+ for fkey in fkeys:
+ migrate.ForeignKeyConstraint(
+ columns=fkey['columns'],
+ 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
+
+ if migrate_engine.name == 'postgresql':
+ error_message = (
+ 'Credential migration in progress. Cannot perform '
+ 'writes to credential table.'
+ )
+ credential_update_trigger = textwrap.dedent(f"""
+ CREATE OR REPLACE FUNCTION keystone_read_only_update()
+ RETURNS trigger AS
+ $BODY$
+ BEGIN
+ IF NEW.encrypted_blob IS NULL THEN
+ RAISE EXCEPTION '{error_message}';
+ END IF;
+ IF NEW.encrypted_blob IS NOT NULL AND OLD.blob IS NULL THEN
+ RAISE EXCEPTION '{error_message}';
+ END IF;
+ RETURN NEW;
+ END
+ $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)
+
+ # FIXME(stephenfin): Remove these indexes. They're left over from attempts
+ # to remove foreign key constraints in past migrations. Apparently
+ # 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()
+
+ # FIXME(stephenfin): These are leftover from when we removed a FK
+ # constraint and should probable be dropped
+ sql.Index('domain_id', identity_provider.c.domain_id).create()
+ sql.Index('domain_id', user.c.domain_id).create()
diff --git a/keystone/common/sql/expand_repo/versions/074_placeholder.py b/keystone/common/sql/legacy_migrations/expand_repo/versions/074_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/expand_repo/versions/074_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/expand_repo/versions/074_placeholder.py
diff --git a/keystone/common/sql/expand_repo/versions/075_placeholder.py b/keystone/common/sql/legacy_migrations/expand_repo/versions/075_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/expand_repo/versions/075_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/expand_repo/versions/075_placeholder.py
diff --git a/keystone/common/sql/expand_repo/versions/076_placeholder.py b/keystone/common/sql/legacy_migrations/expand_repo/versions/076_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/expand_repo/versions/076_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/expand_repo/versions/076_placeholder.py
diff --git a/keystone/common/sql/expand_repo/versions/077_placeholder.py b/keystone/common/sql/legacy_migrations/expand_repo/versions/077_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/expand_repo/versions/077_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/expand_repo/versions/077_placeholder.py
diff --git a/keystone/common/sql/expand_repo/versions/078_placeholder.py b/keystone/common/sql/legacy_migrations/expand_repo/versions/078_placeholder.py
index 2b09cbc99..2b09cbc99 100644
--- a/keystone/common/sql/expand_repo/versions/078_placeholder.py
+++ b/keystone/common/sql/legacy_migrations/expand_repo/versions/078_placeholder.py
diff --git a/keystone/common/sql/expand_repo/versions/079_expand_update_local_id_limit.py b/keystone/common/sql/legacy_migrations/expand_repo/versions/079_expand_update_local_id_limit.py
index 20db83851..20db83851 100644
--- a/keystone/common/sql/expand_repo/versions/079_expand_update_local_id_limit.py
+++ b/keystone/common/sql/legacy_migrations/expand_repo/versions/079_expand_update_local_id_limit.py
diff --git a/keystone/common/sql/expand_repo/versions/__init__.py b/keystone/common/sql/legacy_migrations/expand_repo/versions/__init__.py
index 84e0fb83b..84e0fb83b 100644
--- a/keystone/common/sql/expand_repo/versions/__init__.py
+++ b/keystone/common/sql/legacy_migrations/expand_repo/versions/__init__.py
diff --git a/keystone/common/sql/migrate_repo/README b/keystone/common/sql/migrate_repo/README
deleted file mode 100644
index 131117104..000000000
--- a/keystone/common/sql/migrate_repo/README
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a database migration repository.
-
-More information at
-https://opendev.org/openstack/sqlalchemy-migrate
diff --git a/keystone/common/sql/migrate_repo/manage.py b/keystone/common/sql/migrate_repo/manage.py
deleted file mode 100644
index 41cba1adb..000000000
--- a/keystone/common/sql/migrate_repo/manage.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env python
-
-# 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.
-
-from migrate.versioning.shell import main
-
-if __name__ == '__main__':
- main(debug='False')
diff --git a/keystone/common/sql/migrate_repo/migrate.cfg b/keystone/common/sql/migrate_repo/migrate.cfg
deleted file mode 100644
index db531bb41..000000000
--- a/keystone/common/sql/migrate_repo/migrate.cfg
+++ /dev/null
@@ -1,25 +0,0 @@
-[db_settings]
-# Used to identify which repository this database is versioned under.
-# You can use the name of your project.
-repository_id=keystone
-
-# The name of the database table used to track the schema version.
-# This name shouldn't already be used by your project.
-# If this is changed once a database is under version control, you'll need to
-# change the table name in each database too.
-version_table=migrate_version
-
-# When committing a change script, Migrate will attempt to generate the
-# sql for all supported databases; normally, if one of them fails - probably
-# because you don't have that database installed - it is ignored and the
-# commit continues, perhaps ending successfully.
-# Databases in this list MUST compile successfully during a commit, or the
-# entire commit will fail. List the databases your application will actually
-# be using to ensure your updates to that database work properly.
-# This must be a list; example: ['postgres','sqlite']
-required_dbs=[]
-
-# When creating new change scripts, Migrate will stamp the new script with
-# a version number. By default this is latest_version + 1. You can set this
-# to 'true' to tell Migrate to use the UTC timestamp instead.
-use_timestamp_numbering=False
diff --git a/keystone/common/sql/migrate_repo/versions/067_kilo.py b/keystone/common/sql/migrate_repo/versions/067_kilo.py
deleted file mode 100644
index a6dbed670..000000000
--- a/keystone/common/sql/migrate_repo/versions/067_kilo.py
+++ /dev/null
@@ -1,317 +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
-from oslo_log import log
-import sqlalchemy as sql
-
-from keystone.assignment.backends import sql as assignment_sql
-from keystone.common import sql as ks_sql
-from keystone.identity.mapping_backends import mapping as mapping_backend
-
-
-LOG = log.getLogger(__name__)
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- if migrate_engine.name == 'mysql':
- # In Folsom we explicitly converted migrate_version to UTF8.
- migrate_engine.execute(
- 'ALTER TABLE migrate_version CONVERT TO CHARACTER SET utf8')
- # Set default DB charset to UTF8.
- migrate_engine.execute(
- 'ALTER DATABASE %s DEFAULT CHARACTER SET utf8' %
- migrate_engine.url.database)
-
- credential = sql.Table(
- 'credential', meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('user_id', sql.String(length=64), nullable=False),
- sql.Column('project_id', sql.String(length=64)),
- sql.Column('blob', ks_sql.JsonBlob, nullable=False),
- sql.Column('type', sql.String(length=255), nullable=False),
- sql.Column('extra', ks_sql.JsonBlob.impl),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- domain = sql.Table(
- 'domain', meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('name', sql.String(length=64), nullable=False),
- sql.Column('enabled', sql.Boolean, default=True, nullable=False),
- sql.Column('extra', ks_sql.JsonBlob.impl),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- endpoint = sql.Table(
- 'endpoint', meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('legacy_endpoint_id', sql.String(length=64)),
- sql.Column('interface', sql.String(length=8), nullable=False),
- sql.Column('service_id', sql.String(length=64), nullable=False),
- sql.Column('url', sql.Text, nullable=False),
- sql.Column('extra', ks_sql.JsonBlob.impl),
- sql.Column('enabled', sql.Boolean, nullable=False, default=True,
- server_default='1'),
- sql.Column('region_id', sql.String(length=255), nullable=True),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- group = sql.Table(
- 'group', meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('domain_id', sql.String(length=64), nullable=False),
- sql.Column('name', sql.String(length=64), nullable=False),
- sql.Column('description', sql.Text),
- sql.Column('extra', ks_sql.JsonBlob.impl),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- policy = sql.Table(
- 'policy', meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('type', sql.String(length=255), nullable=False),
- sql.Column('blob', ks_sql.JsonBlob, nullable=False),
- sql.Column('extra', ks_sql.JsonBlob.impl),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- project = sql.Table(
- 'project', meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('name', sql.String(length=64), nullable=False),
- sql.Column('extra', ks_sql.JsonBlob.impl),
- sql.Column('description', sql.Text),
- sql.Column('enabled', sql.Boolean),
- sql.Column('domain_id', sql.String(length=64), nullable=False),
- sql.Column('parent_id', sql.String(64), nullable=True),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- role = sql.Table(
- 'role', meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('name', sql.String(length=255), nullable=False),
- sql.Column('extra', ks_sql.JsonBlob.impl),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- service = sql.Table(
- 'service', meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('type', sql.String(length=255)),
- sql.Column('enabled', sql.Boolean, nullable=False, default=True,
- server_default='1'),
- sql.Column('extra', ks_sql.JsonBlob.impl),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- token = sql.Table(
- 'token', meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('expires', sql.DateTime, default=None),
- sql.Column('extra', ks_sql.JsonBlob.impl),
- sql.Column('valid', sql.Boolean, default=True, nullable=False),
- sql.Column('trust_id', sql.String(length=64)),
- sql.Column('user_id', sql.String(length=64)),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- trust = sql.Table(
- 'trust', meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('trustor_user_id', sql.String(length=64), nullable=False),
- sql.Column('trustee_user_id', sql.String(length=64), nullable=False),
- sql.Column('project_id', sql.String(length=64)),
- sql.Column('impersonation', sql.Boolean, nullable=False),
- sql.Column('deleted_at', sql.DateTime),
- sql.Column('expires_at', sql.DateTime),
- sql.Column('remaining_uses', sql.Integer, nullable=True),
- sql.Column('extra', ks_sql.JsonBlob.impl),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- trust_role = sql.Table(
- 'trust_role', meta,
- sql.Column('trust_id', sql.String(length=64), primary_key=True,
- nullable=False),
- sql.Column('role_id', sql.String(length=64), primary_key=True,
- nullable=False),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- user = sql.Table(
- 'user', meta,
- sql.Column('id', sql.String(length=64), primary_key=True),
- sql.Column('name', sql.String(length=255), nullable=False),
- sql.Column('extra', ks_sql.JsonBlob.impl),
- sql.Column('password', sql.String(length=128)),
- sql.Column('enabled', sql.Boolean),
- sql.Column('domain_id', sql.String(length=64), nullable=False),
- sql.Column('default_project_id', sql.String(length=64)),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- user_group_membership = sql.Table(
- 'user_group_membership', meta,
- sql.Column('user_id', sql.String(length=64), primary_key=True),
- sql.Column('group_id', sql.String(length=64), primary_key=True),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- region = sql.Table(
- 'region',
- meta,
- sql.Column('id', sql.String(255), primary_key=True),
- sql.Column('description', sql.String(255), nullable=False),
- sql.Column('parent_region_id', sql.String(255), nullable=True),
- sql.Column('extra', sql.Text()),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- assignment = sql.Table(
- 'assignment',
- meta,
- sql.Column('type', sql.Enum(
- assignment_sql.AssignmentType.USER_PROJECT,
- assignment_sql.AssignmentType.GROUP_PROJECT,
- assignment_sql.AssignmentType.USER_DOMAIN,
- assignment_sql.AssignmentType.GROUP_DOMAIN,
- name='type'),
- nullable=False),
- sql.Column('actor_id', sql.String(64), nullable=False),
- sql.Column('target_id', sql.String(64), nullable=False),
- sql.Column('role_id', sql.String(64), nullable=False),
- sql.Column('inherited', sql.Boolean, default=False, nullable=False),
- sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id', 'role_id'),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- mapping = sql.Table(
- 'id_mapping',
- meta,
- sql.Column('public_id', sql.String(64), primary_key=True),
- sql.Column('domain_id', sql.String(64), nullable=False),
- sql.Column('local_id', sql.String(64), nullable=False),
- sql.Column('entity_type', sql.Enum(
- mapping_backend.EntityType.USER,
- mapping_backend.EntityType.GROUP,
- name='entity_type'),
- nullable=False),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- domain_config_whitelist = sql.Table(
- 'whitelisted_config',
- meta,
- sql.Column('domain_id', sql.String(64), primary_key=True),
- sql.Column('group', sql.String(255), primary_key=True),
- sql.Column('option', sql.String(255), primary_key=True),
- sql.Column('value', ks_sql.JsonBlob.impl, nullable=False),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- domain_config_sensitive = sql.Table(
- 'sensitive_config',
- meta,
- sql.Column('domain_id', sql.String(64), primary_key=True),
- sql.Column('group', sql.String(255), primary_key=True),
- sql.Column('option', sql.String(255), primary_key=True),
- sql.Column('value', ks_sql.JsonBlob.impl, nullable=False),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- # create all tables
- tables = [credential, domain, endpoint, group, policy, project, role,
- service, token, trust, trust_role, user, user_group_membership,
- region, assignment, mapping, domain_config_whitelist,
- domain_config_sensitive]
-
- for table in tables:
- try:
- table.create()
- except Exception:
- LOG.exception('Exception while creating table: %r', table)
- raise
-
- # Unique Constraints
- migrate.UniqueConstraint(user.c.domain_id,
- user.c.name,
- name='ixu_user_name_domain_id').create()
- migrate.UniqueConstraint(group.c.domain_id,
- group.c.name,
- name='ixu_group_name_domain_id').create()
- migrate.UniqueConstraint(role.c.name,
- name='ixu_role_name').create()
- migrate.UniqueConstraint(project.c.domain_id,
- project.c.name,
- name='ixu_project_name_domain_id').create()
- migrate.UniqueConstraint(domain.c.name,
- name='ixu_domain_name').create()
- migrate.UniqueConstraint(mapping.c.domain_id,
- mapping.c.local_id,
- mapping.c.entity_type,
- name='domain_id').create()
-
- # Indexes
- sql.Index('ix_token_expires', token.c.expires).create()
- sql.Index('ix_token_expires_valid', token.c.expires,
- token.c.valid).create()
- sql.Index('ix_actor_id', assignment.c.actor_id).create()
- sql.Index('ix_token_user_id', token.c.user_id).create()
- sql.Index('ix_token_trust_id', token.c.trust_id).create()
- # NOTE(stevemar): The two indexes below were named 'service_id' and
- # 'group_id' in 050_fk_consistent_indexes.py, and need to be preserved
- sql.Index('service_id', endpoint.c.service_id).create()
- sql.Index('group_id', user_group_membership.c.group_id).create()
-
- fkeys = [
- {'columns': [endpoint.c.service_id],
- 'references': [service.c.id]},
-
- {'columns': [user_group_membership.c.group_id],
- 'references': [group.c.id],
- 'name': 'fk_user_group_membership_group_id'},
-
- {'columns': [user_group_membership.c.user_id],
- 'references':[user.c.id],
- 'name': 'fk_user_group_membership_user_id'},
-
- {'columns': [project.c.domain_id],
- 'references': [domain.c.id],
- 'name': 'fk_project_domain_id'},
-
- {'columns': [endpoint.c.region_id],
- 'references': [region.c.id],
- 'name': 'fk_endpoint_region_id'},
-
- {'columns': [project.c.parent_id],
- 'references': [project.c.id],
- 'name': 'project_parent_id_fkey'},
- ]
-
- if migrate_engine.name == 'sqlite':
- # NOTE(stevemar): We need to keep this FK constraint due to 073, but
- # only for sqlite, once we collapse 073 we can remove this constraint
- fkeys.append(
- {'columns': [assignment.c.role_id],
- 'references': [role.c.id],
- 'name': 'fk_assignment_role_id'})
-
- for fkey in fkeys:
- migrate.ForeignKeyConstraint(columns=fkey['columns'],
- refcolumns=fkey['references'],
- name=fkey.get('name')).create()
diff --git a/keystone/common/sql/migrate_repo/versions/068_placeholder.py b/keystone/common/sql/migrate_repo/versions/068_placeholder.py
deleted file mode 100644
index 111df9d4a..000000000
--- a/keystone/common/sql/migrate_repo/versions/068_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 Kilo backports. Do not use this number for new
-# Liberty work. New Liberty work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/069_placeholder.py b/keystone/common/sql/migrate_repo/versions/069_placeholder.py
deleted file mode 100644
index 111df9d4a..000000000
--- a/keystone/common/sql/migrate_repo/versions/069_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 Kilo backports. Do not use this number for new
-# Liberty work. New Liberty work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/070_placeholder.py b/keystone/common/sql/migrate_repo/versions/070_placeholder.py
deleted file mode 100644
index 111df9d4a..000000000
--- a/keystone/common/sql/migrate_repo/versions/070_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 Kilo backports. Do not use this number for new
-# Liberty work. New Liberty work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/071_placeholder.py b/keystone/common/sql/migrate_repo/versions/071_placeholder.py
deleted file mode 100644
index 111df9d4a..000000000
--- a/keystone/common/sql/migrate_repo/versions/071_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 Kilo backports. Do not use this number for new
-# Liberty work. New Liberty work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/072_placeholder.py b/keystone/common/sql/migrate_repo/versions/072_placeholder.py
deleted file mode 100644
index 111df9d4a..000000000
--- a/keystone/common/sql/migrate_repo/versions/072_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 Kilo backports. Do not use this number for new
-# Liberty work. New Liberty work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/073_insert_assignment_inherited_pk.py b/keystone/common/sql/migrate_repo/versions/073_insert_assignment_inherited_pk.py
deleted file mode 100644
index dc0905b5f..000000000
--- a/keystone/common/sql/migrate_repo/versions/073_insert_assignment_inherited_pk.py
+++ /dev/null
@@ -1,113 +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 sqlalchemy.orm import sessionmaker
-
-from keystone.assignment.backends import sql as assignment_sql
-
-
-def upgrade(migrate_engine):
- """Insert inherited column to assignment table PK constraints.
-
- For non-SQLite databases, it changes the constraint in the existing table.
-
- For SQLite, since changing constraints is not supported, it recreates the
- assignment table with the new PK constraint and migrates the existing data.
-
- """
- ASSIGNMENT_TABLE_NAME = 'assignment'
-
- metadata = sql.MetaData()
- metadata.bind = migrate_engine
-
- # Retrieve the existing assignment table
- assignment_table = sql.Table(ASSIGNMENT_TABLE_NAME, metadata,
- autoload=True)
-
- if migrate_engine.name == 'sqlite':
- ACTOR_ID_INDEX_NAME = 'ix_actor_id'
- TMP_ASSIGNMENT_TABLE_NAME = 'tmp_assignment'
-
- # Define the new assignment table with a temporary name
- new_assignment_table = sql.Table(
- TMP_ASSIGNMENT_TABLE_NAME, metadata,
- sql.Column('type', sql.Enum(
- assignment_sql.AssignmentType.USER_PROJECT,
- assignment_sql.AssignmentType.GROUP_PROJECT,
- assignment_sql.AssignmentType.USER_DOMAIN,
- assignment_sql.AssignmentType.GROUP_DOMAIN,
- name='type'),
- nullable=False),
- sql.Column('actor_id', sql.String(64), nullable=False),
- sql.Column('target_id', sql.String(64), nullable=False),
- sql.Column('role_id', sql.String(64), sql.ForeignKey('role.id'),
- nullable=False),
- sql.Column('inherited', sql.Boolean, default=False,
- nullable=False),
- sql.PrimaryKeyConstraint('type', 'actor_id', 'target_id',
- 'role_id', 'inherited'),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- # Create the new assignment table
- new_assignment_table.create(migrate_engine, checkfirst=True)
-
- # Change the index from the existing assignment table to the new one
- sql.Index(ACTOR_ID_INDEX_NAME, assignment_table.c.actor_id).drop()
- sql.Index(ACTOR_ID_INDEX_NAME,
- new_assignment_table.c.actor_id).create()
-
- # Instantiate session
- maker = sessionmaker(bind=migrate_engine)
- session = maker()
-
- # Migrate existing data
- insert = new_assignment_table.insert().from_select(
- assignment_table.c, select=session.query(assignment_table))
- session.execute(insert)
- session.commit()
-
- # Drop the existing assignment table, in favor of the new one
- assignment_table.deregister()
- assignment_table.drop()
-
- # Finally, rename the new table to the original assignment table name
- new_assignment_table.rename(ASSIGNMENT_TABLE_NAME)
- elif migrate_engine.name == 'ibm_db_sa':
- # Recreate the existing constraint, marking the inherited column as PK
- # for DB2.
-
- # This is a workaround to the general case in the else statement below.
- # Due to a bug in the DB2 sqlalchemy dialect, Column.alter() actually
- # creates a primary key over only the "inherited" column. This is wrong
- # because the primary key for the table actually covers other columns
- # too, not just the "inherited" column. Since the primary key already
- # exists for the table after the Column.alter() call, it causes the
- # next line to fail with an error that the primary key already exists.
-
- # The workaround here skips doing the Column.alter(). This causes a
- # warning message since the metadata is out of sync. We can remove this
- # workaround once the DB2 sqlalchemy dialect is fixed.
- # DB2 Issue: https://code.google.com/p/ibm-db/issues/detail?id=173
-
- migrate.PrimaryKeyConstraint(table=assignment_table).drop()
- migrate.PrimaryKeyConstraint(
- assignment_table.c.type, assignment_table.c.actor_id,
- assignment_table.c.target_id, assignment_table.c.role_id,
- assignment_table.c.inherited).create()
- else:
- # Recreate the existing constraint, marking the inherited column as PK
- migrate.PrimaryKeyConstraint(table=assignment_table).drop()
- assignment_table.c.inherited.alter(primary_key=True)
- migrate.PrimaryKeyConstraint(table=assignment_table).create()
diff --git a/keystone/common/sql/migrate_repo/versions/074_add_is_domain_project.py b/keystone/common/sql/migrate_repo/versions/074_add_is_domain_project.py
deleted file mode 100644
index dcb89b07c..000000000
--- a/keystone/common/sql/migrate_repo/versions/074_add_is_domain_project.py
+++ /dev/null
@@ -1,27 +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
-
-
-_PROJECT_TABLE_NAME = 'project'
-_IS_DOMAIN_COLUMN_NAME = 'is_domain'
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- project_table = sql.Table(_PROJECT_TABLE_NAME, meta, autoload=True)
- is_domain = sql.Column(_IS_DOMAIN_COLUMN_NAME, sql.Boolean, nullable=False,
- server_default='0', default=False)
- project_table.create_column(is_domain)
diff --git a/keystone/common/sql/migrate_repo/versions/075_confirm_config_registration.py b/keystone/common/sql/migrate_repo/versions/075_confirm_config_registration.py
deleted file mode 100644
index 576842c69..000000000
--- a/keystone/common/sql/migrate_repo/versions/075_confirm_config_registration.py
+++ /dev/null
@@ -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
-
-REGISTRATION_TABLE = 'config_register'
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- registration_table = sql.Table(
- REGISTRATION_TABLE,
- meta,
- sql.Column('type', sql.String(64), primary_key=True),
- sql.Column('domain_id', sql.String(64), nullable=False),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
- registration_table.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/migrate_repo/versions/076_placeholder.py b/keystone/common/sql/migrate_repo/versions/076_placeholder.py
deleted file mode 100644
index 9f6e84156..000000000
--- a/keystone/common/sql/migrate_repo/versions/076_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 Liberty backports. Do not use this number for new
-# Mitaka work. New Mitaka work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/077_placeholder.py b/keystone/common/sql/migrate_repo/versions/077_placeholder.py
deleted file mode 100644
index 9f6e84156..000000000
--- a/keystone/common/sql/migrate_repo/versions/077_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 Liberty backports. Do not use this number for new
-# Mitaka work. New Mitaka work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/078_placeholder.py b/keystone/common/sql/migrate_repo/versions/078_placeholder.py
deleted file mode 100644
index 9f6e84156..000000000
--- a/keystone/common/sql/migrate_repo/versions/078_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 Liberty backports. Do not use this number for new
-# Mitaka work. New Mitaka work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/079_placeholder.py b/keystone/common/sql/migrate_repo/versions/079_placeholder.py
deleted file mode 100644
index 9f6e84156..000000000
--- a/keystone/common/sql/migrate_repo/versions/079_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 Liberty backports. Do not use this number for new
-# Mitaka work. New Mitaka work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/080_placeholder.py b/keystone/common/sql/migrate_repo/versions/080_placeholder.py
deleted file mode 100644
index 9f6e84156..000000000
--- a/keystone/common/sql/migrate_repo/versions/080_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 Liberty backports. Do not use this number for new
-# Mitaka work. New Mitaka work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/081_add_endpoint_policy_table.py b/keystone/common/sql/migrate_repo/versions/081_add_endpoint_policy_table.py
deleted file mode 100644
index f8bffa1cd..000000000
--- a/keystone/common/sql/migrate_repo/versions/081_add_endpoint_policy_table.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright 2014 IBM Corp.
-#
-# 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):
- try:
- extension_version = upgrades.get_db_version(
- extension='endpoint_policy',
- engine=migrate_engine)
- except Exception:
- extension_version = 0
-
- # This migration corresponds to endpoint_policy extension migration 1. Only
- # update if it has not been run.
- if extension_version >= 1:
- return
-
- # Upgrade operations go here. Don't create your own engine; bind
- # migrate_engine to your metadata
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- endpoint_policy_table = sql.Table(
- 'policy_association',
- meta,
- sql.Column('id', sql.String(64), primary_key=True),
- sql.Column('policy_id', sql.String(64),
- nullable=False),
- sql.Column('endpoint_id', sql.String(64),
- nullable=True),
- sql.Column('service_id', sql.String(64),
- nullable=True),
- sql.Column('region_id', sql.String(64),
- nullable=True),
- sql.UniqueConstraint('endpoint_id', 'service_id', 'region_id'),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
-
- endpoint_policy_table.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/migrate_repo/versions/082_add_federation_tables.py b/keystone/common/sql/migrate_repo/versions/082_add_federation_tables.py
deleted file mode 100644
index bbda554a4..000000000
--- a/keystone/common/sql/migrate_repo/versions/082_add_federation_tables.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# Copyright 2014 IBM Corp.
-#
-# 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
-import keystone.conf
-
-CONF = keystone.conf.CONF
-_RELAY_STATE_PREFIX = 'relay_state_prefix'
-
-
-def upgrade(migrate_engine):
- try:
- extension_version = upgrades.get_db_version(
- extension='federation',
- engine=migrate_engine)
- except Exception:
- extension_version = 0
-
- # This migration corresponds to federation extension migration 8. Only
- # update if it has not been run.
- if extension_version >= 8:
- return
-
- # Upgrade operations go here. Don't create your own engine; bind
- # migrate_engine to your metadata
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- idp_table = sql.Table(
- 'identity_provider',
- meta,
- sql.Column('id', sql.String(64), primary_key=True),
- sql.Column('enabled', sql.Boolean, nullable=False),
- sql.Column('description', sql.Text(), nullable=True),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
- idp_table.create(migrate_engine, checkfirst=True)
-
- federation_protocol_table = sql.Table(
- 'federation_protocol',
- meta,
- sql.Column('id', sql.String(64), primary_key=True),
- sql.Column('idp_id', sql.String(64),
- sql.ForeignKey('identity_provider.id', ondelete='CASCADE'),
- primary_key=True),
- sql.Column('mapping_id', sql.String(64), nullable=False),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
- federation_protocol_table.create(migrate_engine, checkfirst=True)
-
- mapping_table = sql.Table(
- 'mapping',
- meta,
- sql.Column('id', sql.String(64), primary_key=True),
- sql.Column('rules', sql.Text(), nullable=False),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
- mapping_table.create(migrate_engine, checkfirst=True)
-
- relay_state_prefix_default = CONF.saml.relay_state_prefix
- sp_table = sql.Table(
- 'service_provider',
- meta,
- sql.Column('auth_url', sql.String(256), nullable=False),
- 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('sp_url', sql.String(256), nullable=False),
- sql.Column(_RELAY_STATE_PREFIX, sql.String(256), nullable=False,
- server_default=relay_state_prefix_default),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
- sp_table.create(migrate_engine, checkfirst=True)
-
- idp_table = sql.Table('identity_provider', meta, autoload=True)
- remote_id_table = sql.Table(
- 'idp_remote_ids',
- meta,
- sql.Column('idp_id', sql.String(64),
- sql.ForeignKey('identity_provider.id', ondelete='CASCADE')),
- sql.Column('remote_id', sql.String(255), primary_key=True),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
- remote_id_table.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/migrate_repo/versions/083_add_oauth1_tables.py b/keystone/common/sql/migrate_repo/versions/083_add_oauth1_tables.py
deleted file mode 100644
index 8bbccb962..000000000
--- a/keystone/common/sql/migrate_repo/versions/083_add_oauth1_tables.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright 2014 IBM Corp.
-#
-# 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):
- try:
- extension_version = upgrades.get_db_version(
- extension='oauth1',
- engine=migrate_engine)
- except Exception:
- extension_version = 0
-
- # This migration corresponds to oauth extension migration 5. Only
- # update if it has not been run.
- if extension_version >= 5:
- return
-
- # Upgrade operations go here. Don't create your own engine; bind
- # migrate_engine to your metadata
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- consumer_table = sql.Table(
- 'consumer',
- meta,
- sql.Column('id', sql.String(64), primary_key=True, nullable=False),
- sql.Column('description', sql.String(64), nullable=True),
- sql.Column('secret', sql.String(64), nullable=False),
- sql.Column('extra', sql.Text(), nullable=False))
- consumer_table.create(migrate_engine, checkfirst=True)
-
- request_token_table = sql.Table(
- 'request_token',
- meta,
- sql.Column('id', sql.String(64), primary_key=True, nullable=False),
- sql.Column('request_secret', sql.String(64), nullable=False),
- sql.Column('verifier', sql.String(64), nullable=True),
- sql.Column('authorizing_user_id', sql.String(64), nullable=True),
- sql.Column('requested_project_id', sql.String(64), nullable=False),
- sql.Column('role_ids', sql.Text(), nullable=True),
- sql.Column('consumer_id', sql.String(64),
- sql.ForeignKey('consumer.id'),
- nullable=False, index=True),
- sql.Column('expires_at', sql.String(64), nullable=True))
- request_token_table.create(migrate_engine, checkfirst=True)
-
- access_token_table = sql.Table(
- 'access_token',
- meta,
- sql.Column('id', sql.String(64), primary_key=True, nullable=False),
- sql.Column('access_secret', sql.String(64), nullable=False),
- sql.Column('authorizing_user_id', sql.String(64),
- nullable=False, index=True),
- sql.Column('project_id', sql.String(64), nullable=False),
- sql.Column('role_ids', sql.Text(), nullable=False),
- sql.Column('consumer_id', sql.String(64),
- sql.ForeignKey('consumer.id'),
- nullable=False, index=True),
- sql.Column('expires_at', sql.String(64), nullable=True))
- access_token_table.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/migrate_repo/versions/084_add_revoke_tables.py b/keystone/common/sql/migrate_repo/versions/084_add_revoke_tables.py
deleted file mode 100644
index 0cf37e7d7..000000000
--- a/keystone/common/sql/migrate_repo/versions/084_add_revoke_tables.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2014 IBM Corp.
-#
-# 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):
- try:
- extension_version = upgrades.get_db_version(
- extension='revoke',
- engine=migrate_engine)
- except Exception:
- extension_version = 0
-
- # This migration corresponds to revoke extension migration 2. Only
- # update if it has not been run.
- if extension_version >= 2:
- return
-
- # Upgrade operations go here. Don't create your own engine; bind
- # migrate_engine to your metadata
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- service_table = sql.Table(
- 'revocation_event',
- meta,
- sql.Column('id', sql.String(64), primary_key=True),
- sql.Column('domain_id', sql.String(64)),
- sql.Column('project_id', sql.String(64)),
- sql.Column('user_id', sql.String(64)),
- sql.Column('role_id', sql.String(64)),
- sql.Column('trust_id', sql.String(64)),
- sql.Column('consumer_id', sql.String(64)),
- sql.Column('access_token_id', sql.String(64)),
- sql.Column('issued_before', sql.DateTime(), nullable=False),
- sql.Column('expires_at', sql.DateTime()),
- sql.Column('revoked_at', sql.DateTime(), index=True, nullable=False),
- sql.Column('audit_id', sql.String(32), nullable=True),
- sql.Column('audit_chain_id', sql.String(32), nullable=True))
-
- service_table.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/migrate_repo/versions/085_add_endpoint_filtering_table.py b/keystone/common/sql/migrate_repo/versions/085_add_endpoint_filtering_table.py
deleted file mode 100644
index 0283bc335..000000000
--- a/keystone/common/sql/migrate_repo/versions/085_add_endpoint_filtering_table.py
+++ /dev/null
@@ -1,70 +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):
- try:
- extension_version = upgrades.get_db_version(
- extension='endpoint_filter',
- engine=migrate_engine)
- except Exception:
- extension_version = 0
-
- # This migration corresponds to endpoint_filter extension migration 2. Only
- # update if it has not been run.
- if extension_version >= 2:
- return
-
- # Upgrade operations go here. Don't create your own engine; bind
- # migrate_engine to your metadata
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- EP_GROUP_ID = 'endpoint_group_id'
- PROJECT_ID = 'project_id'
-
- endpoint_filtering_table = sql.Table(
- 'project_endpoint',
- meta,
- sql.Column(
- 'endpoint_id',
- sql.String(64),
- primary_key=True,
- nullable=False),
- sql.Column(
- 'project_id',
- sql.String(64),
- primary_key=True,
- nullable=False))
- endpoint_filtering_table.create(migrate_engine, checkfirst=True)
-
- endpoint_group_table = sql.Table(
- 'endpoint_group',
- meta,
- sql.Column('id', sql.String(64), primary_key=True),
- sql.Column('name', sql.String(255), nullable=False),
- sql.Column('description', sql.Text, nullable=True),
- sql.Column('filters', sql.Text(), nullable=False))
- endpoint_group_table.create(migrate_engine, checkfirst=True)
-
- project_endpoint_group_table = sql.Table(
- 'project_endpoint_group',
- meta,
- sql.Column(EP_GROUP_ID, sql.String(64),
- sql.ForeignKey('endpoint_group.id'), nullable=False),
- sql.Column(PROJECT_ID, sql.String(64), nullable=False),
- sql.PrimaryKeyConstraint(EP_GROUP_ID, PROJECT_ID))
- project_endpoint_group_table.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/migrate_repo/versions/086_add_duplicate_constraint_trusts.py b/keystone/common/sql/migrate_repo/versions/086_add_duplicate_constraint_trusts.py
deleted file mode 100644
index 2b115ea42..000000000
--- a/keystone/common/sql/migrate_repo/versions/086_add_duplicate_constraint_trusts.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2015 Intel Corporation
-# All Rights Reserved
-#
-# 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.
-
-from migrate import UniqueConstraint
-from sqlalchemy import MetaData, Table
-
-
-def upgrade(migrate_engine):
- meta = MetaData(bind=migrate_engine)
- trusts = Table('trust', meta, autoload=True)
-
- UniqueConstraint('trustor_user_id', 'trustee_user_id', 'project_id',
- 'impersonation', 'expires_at', table=trusts,
- name='duplicate_trust_constraint').create()
diff --git a/keystone/common/sql/migrate_repo/versions/087_implied_roles.py b/keystone/common/sql/migrate_repo/versions/087_implied_roles.py
deleted file mode 100644
index 7713ce8fa..000000000
--- a/keystone/common/sql/migrate_repo/versions/087_implied_roles.py
+++ /dev/null
@@ -1,43 +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
-
-
-ROLE_TABLE = 'role'
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- implied_role = sql.Table(
- 'implied_role', meta,
- sql.Column('prior_role_id', sql.String(length=64), primary_key=True),
- sql.Column(
- 'implied_role_id', sql.String(length=64), primary_key=True),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
- implied_role.create()
- role = sql.Table(ROLE_TABLE, meta, autoload=True)
- fkeys = [
- {'columns': [implied_role.c.prior_role_id],
- 'references': [role.c.id]},
- {'columns': [implied_role.c.implied_role_id],
- 'references': [role.c.id]},
- ]
- for fkey in fkeys:
- migrate.ForeignKeyConstraint(columns=fkey['columns'],
- refcolumns=fkey['references'],
- name=fkey.get('name')).create()
diff --git a/keystone/common/sql/migrate_repo/versions/088_domain_specific_roles.py b/keystone/common/sql/migrate_repo/versions/088_domain_specific_roles.py
deleted file mode 100644
index 8b792dfa7..000000000
--- a/keystone/common/sql/migrate_repo/versions/088_domain_specific_roles.py
+++ /dev/null
@@ -1,60 +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
-
-
-_ROLE_NAME_NEW_CONSTRAINT = 'ixu_role_name_domain_id'
-_ROLE_TABLE_NAME = 'role'
-_ROLE_NAME_COLUMN_NAME = 'name'
-_DOMAIN_ID_COLUMN_NAME = 'domain_id'
-_NULL_DOMAIN_ID = '<<null>>'
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- role_table = sql.Table(_ROLE_TABLE_NAME, meta, autoload=True)
- domain_id = sql.Column(_DOMAIN_ID_COLUMN_NAME, sql.String(64),
- nullable=False, server_default=_NULL_DOMAIN_ID)
-
- # NOTE(morganfainberg): the `role_name` unique constraint is not
- # guaranteed to be a fixed name, such as 'ixu_role_name`, so we need to
- # search for the correct constraint that only affects role_table.c.name
- # and drop that constraint.
- to_drop = None
- if migrate_engine.name == 'mysql':
- for c in role_table.indexes:
- if (c.unique and len(c.columns) == 1 and
- _ROLE_NAME_COLUMN_NAME in c.columns):
- to_drop = c
- break
- else:
- for c in role_table.constraints:
- if len(c.columns) == 1 and _ROLE_NAME_COLUMN_NAME in c.columns:
- to_drop = c
- break
-
- if to_drop is not None:
- migrate.UniqueConstraint(role_table.c.name,
- name=to_drop.name).drop()
-
- # perform changes after constraint is dropped.
- if 'domain_id' not in role_table.columns:
- # Only create the column if it doesn't already exist.
- role_table.create_column(domain_id)
-
- migrate.UniqueConstraint(role_table.c.name,
- role_table.c.domain_id,
- name=_ROLE_NAME_NEW_CONSTRAINT).create()
diff --git a/keystone/common/sql/migrate_repo/versions/090_add_local_user_and_password_tables.py b/keystone/common/sql/migrate_repo/versions/090_add_local_user_and_password_tables.py
deleted file mode 100644
index 800ba47e8..000000000
--- a/keystone/common/sql/migrate_repo/versions/090_add_local_user_and_password_tables.py
+++ /dev/null
@@ -1,42 +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
-
- user = sql.Table('user', meta, autoload=True)
-
- local_user = sql.Table(
- 'local_user',
- meta,
- sql.Column('id', sql.Integer, primary_key=True, nullable=False),
- sql.Column('user_id', sql.String(64),
- sql.ForeignKey(user.c.id, ondelete='CASCADE'),
- nullable=False, unique=True),
- sql.Column('domain_id', sql.String(64), nullable=False),
- sql.Column('name', sql.String(255), nullable=False),
- sql.UniqueConstraint('domain_id', 'name'))
- local_user.create(migrate_engine, checkfirst=True)
-
- password = sql.Table(
- 'password',
- meta,
- sql.Column('id', sql.Integer, primary_key=True, nullable=False),
- sql.Column('local_user_id', sql.Integer,
- sql.ForeignKey(local_user.c.id, ondelete='CASCADE'),
- nullable=False),
- sql.Column('password', sql.String(128), nullable=False))
- password.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/migrate_repo/versions/091_migrate_data_to_local_user_and_password_tables.py b/keystone/common/sql/migrate_repo/versions/091_migrate_data_to_local_user_and_password_tables.py
deleted file mode 100644
index 7e98b99b7..000000000
--- a/keystone/common/sql/migrate_repo/versions/091_migrate_data_to_local_user_and_password_tables.py
+++ /dev/null
@@ -1,84 +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 sqlalchemy import func
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- user_table = sql.Table('user', meta, autoload=True)
- local_user_table = sql.Table('local_user', meta, autoload=True)
- password_table = sql.Table('password', meta, autoload=True)
-
- # migrate data to local_user table
- local_user_values = []
- for row in user_table.select().execute():
- # skip the row that already exists in `local_user`, this could
- # happen if run into a partially-migrated table due to the
- # bug #1549705.
- filter_by = local_user_table.c.user_id == row['id']
- user_count = sql.select([func.count()]).select_from(
- local_user_table).where(filter_by).execute().fetchone()[0]
- if user_count == 0:
- local_user_values.append({'user_id': row['id'],
- 'domain_id': row['domain_id'],
- 'name': row['name']})
- if local_user_values:
- local_user_table.insert().values(local_user_values).execute()
-
- # migrate data to password table
- sel = (
- sql.select([user_table, local_user_table], use_labels=True)
- .select_from(user_table.join(local_user_table, user_table.c.id ==
- local_user_table.c.user_id))
- )
- user_rows = sel.execute()
- password_values = []
- for row in user_rows:
- if row['user_password']:
- password_values.append({'local_user_id': row['local_user_id'],
- 'password': row['user_password']})
- if password_values:
- password_table.insert().values(password_values).execute()
-
- # NOTE(gnuoy): the `domain_id` unique constraint is not guaranteed to
- # be a fixed name, such as 'ixu_user_name_domain_id`, so we need to
- # search for the correct constraint that only affects
- # user_table.c.domain_id and drop that constraint. (Fix based on
- # morganfainbergs fix in 088_domain_specific_roles.py)
- to_drop = None
- if migrate_engine.name == 'mysql':
- for index in user_table.indexes:
- if (index.unique and len(index.columns) == 2 and
- 'domain_id' in index.columns and 'name' in index.columns):
- to_drop = index
- break
- else:
- for index in user_table.constraints:
- if (len(index.columns) == 2 and 'domain_id' in index.columns and
- 'name' in index.columns):
- to_drop = index
- break
- # remove domain_id and name unique constraint
- if migrate_engine.name != 'sqlite' and to_drop is not None:
- migrate.UniqueConstraint(user_table.c.domain_id,
- user_table.c.name,
- name=to_drop.name).drop()
-
- # drop user columns
- user_table.c.domain_id.drop()
- user_table.c.name.drop()
- user_table.c.password.drop()
diff --git a/keystone/common/sql/migrate_repo/versions/092_make_implied_roles_fks_cascaded.py b/keystone/common/sql/migrate_repo/versions/092_make_implied_roles_fks_cascaded.py
deleted file mode 100644
index 5e8418999..000000000
--- a/keystone/common/sql/migrate_repo/versions/092_make_implied_roles_fks_cascaded.py
+++ /dev/null
@@ -1,46 +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
-
-
-ROLE_TABLE = 'role'
-IMPLIED_ROLE_TABLE = 'implied_role'
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- role = sql.Table(ROLE_TABLE, meta, autoload=True)
- implied_role = sql.Table(IMPLIED_ROLE_TABLE, meta, autoload=True)
-
- fkeys = [
- {'columns': [implied_role.c.prior_role_id],
- 'references': [role.c.id]},
- {'columns': [implied_role.c.implied_role_id],
- 'references': [role.c.id]},
- ]
-
- # NOTE(stevemar): We need to divide these into two separate loops otherwise
- # they may clobber each other and only end up with one foreign key.
- for fkey in fkeys:
- migrate.ForeignKeyConstraint(columns=fkey['columns'],
- refcolumns=fkey['references'],
- name=fkey.get('name')).drop()
- for fkey in fkeys:
- migrate.ForeignKeyConstraint(columns=fkey['columns'],
- refcolumns=fkey['references'],
- name=fkey.get('name'),
- ondelete="CASCADE").create()
diff --git a/keystone/common/sql/migrate_repo/versions/093_migrate_domains_to_projects.py b/keystone/common/sql/migrate_repo/versions/093_migrate_domains_to_projects.py
deleted file mode 100644
index e0d6a4ee5..000000000
--- a/keystone/common/sql/migrate_repo/versions/093_migrate_domains_to_projects.py
+++ /dev/null
@@ -1,125 +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 json
-
-import sqlalchemy as sql
-
-from keystone.common.sql import upgrades
-
-
-_PROJECT_TABLE_NAME = 'project'
-_DOMAIN_TABLE_NAME = 'domain'
-_PARENT_ID_COLUMN_NAME = 'parent_id'
-_DOMAIN_ID_COLUMN_NAME = 'domain_id'
-
-# Above the driver level, the domain_id of a project acting as a domain is
-# None. However, in order to enable sql integrity constraints to still operate
-# on this column, we create a special "root of all domains" row, with an ID of
-# NULL_DOMAIN_ID, which all projects acting as a domain reference in their
-# domain_id attribute. This special row, as well as NULL_DOMAIN_ID, are never
-# exposed outside of sql driver layer.
-NULL_DOMAIN_ID = '<<keystone.domain.root>>'
-
-
-def list_existing_project_constraints(project_table, domain_table):
- constraints = [{'table': project_table,
- 'fk_column': _PARENT_ID_COLUMN_NAME,
- 'ref_column': project_table.c.id},
- {'table': project_table,
- 'fk_column': _DOMAIN_ID_COLUMN_NAME,
- 'ref_column': domain_table.c.id}]
-
- return constraints
-
-
-def list_new_project_constraints(project_table):
- constraints = [{'table': project_table,
- 'fk_column': _PARENT_ID_COLUMN_NAME,
- 'ref_column': project_table.c.id},
- {'table': project_table,
- 'fk_column': _DOMAIN_ID_COLUMN_NAME,
- 'ref_column': project_table.c.id}]
-
- return constraints
-
-
-def upgrade(migrate_engine):
-
- def _project_from_domain(domain):
- # Creates a project dict with is_domain=True from the provided
- # domain.
-
- description = None
- extra = {}
- if domain.extra is not None:
- # 'description' property is an extra attribute in domains but a
- # first class attribute in projects
- extra = json.loads(domain.extra)
- description = extra.pop('description', None)
-
- return {
- 'id': domain.id,
- 'name': domain.name,
- 'enabled': domain.enabled,
- 'description': description,
- 'domain_id': NULL_DOMAIN_ID,
- 'is_domain': True,
- 'parent_id': None,
- 'extra': json.dumps(extra)
- }
-
- meta = sql.MetaData()
- meta.bind = migrate_engine
- session = sql.orm.sessionmaker(bind=migrate_engine)()
-
- project_table = sql.Table(_PROJECT_TABLE_NAME, meta, autoload=True)
- domain_table = sql.Table(_DOMAIN_TABLE_NAME, meta, autoload=True)
-
- # NOTE(htruta): Remove the parent_id constraint during the migration
- # because for every root project inside this domain, we will set
- # the project domain_id to be its parent_id. We re-enable the constraint
- # in the end of this method. We also remove the domain_id constraint,
- # while be recreated a FK to the project_id at the end.
- upgrades.remove_constraints(
- list_existing_project_constraints(project_table, domain_table))
-
- # For each domain, create a project acting as a domain. We ignore the
- # "root of all domains" row, since we already have one of these in the
- # project table.
- domains = list(domain_table.select().execute())
- for domain in domains:
- if domain.id == NULL_DOMAIN_ID:
- continue
- is_domain_project = _project_from_domain(domain)
- new_entry = project_table.insert().values(**is_domain_project)
- session.execute(new_entry)
- session.commit()
-
- # For each project, that has no parent (i.e. a top level project), update
- # it's parent_id to point at the project acting as its domain. We ignore
- # the "root of all domains" row, since its parent_id must always be None.
- projects = list(project_table.select().execute())
- for project in projects:
- if (project.parent_id is not None or project.is_domain or
- project.id == NULL_DOMAIN_ID):
- continue
- values = {'parent_id': project.domain_id}
- update = project_table.update().where(
- project_table.c.id == project.id).values(values)
- session.execute(update)
- session.commit()
-
- upgrades.add_constraints(
- list_new_project_constraints(project_table))
-
- session.close()
diff --git a/keystone/common/sql/migrate_repo/versions/094_add_federated_user_table.py b/keystone/common/sql/migrate_repo/versions/094_add_federated_user_table.py
deleted file mode 100644
index 8bc64ec1f..000000000
--- a/keystone/common/sql/migrate_repo/versions/094_add_federated_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 migrate
-import sqlalchemy as sql
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- user_table = sql.Table('user', meta, autoload=True)
- idp_table = sql.Table('identity_provider', meta, autoload=True)
- protocol_table = sql.Table('federation_protocol', meta, autoload=True)
-
- federated_table = sql.Table(
- 'federated_user',
- meta,
- sql.Column('id', sql.Integer, primary_key=True, nullable=False),
- sql.Column('user_id', sql.String(64),
- sql.ForeignKey(user_table.c.id, ondelete='CASCADE'),
- nullable=False),
- sql.Column('idp_id', sql.String(64),
- sql.ForeignKey(idp_table.c.id, ondelete='CASCADE'),
- nullable=False),
- sql.Column('protocol_id', sql.String(64), nullable=False),
- sql.Column('unique_id', sql.String(255), nullable=False),
- sql.Column('display_name', sql.String(255), nullable=True),
- sql.UniqueConstraint('idp_id', 'protocol_id', 'unique_id'),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
- federated_table.create(migrate_engine, checkfirst=True)
-
- migrate.ForeignKeyConstraint(
- columns=[federated_table.c.protocol_id, federated_table.c.idp_id],
- refcolumns=[protocol_table.c.id, protocol_table.c.idp_id]).create()
diff --git a/keystone/common/sql/migrate_repo/versions/095_add_integer_pkey_to_revocation_event_table.py b/keystone/common/sql/migrate_repo/versions/095_add_integer_pkey_to_revocation_event_table.py
deleted file mode 100644
index 7a75f7b19..000000000
--- a/keystone/common/sql/migrate_repo/versions/095_add_integer_pkey_to_revocation_event_table.py
+++ /dev/null
@@ -1,62 +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
-
- # You can specify primary keys when creating tables, however adding
- # auto-increment integer primary keys for existing tables is not
- # cross-engine compatibility supported. Thus, the approach is to:
- # (1) create a new revocation_event table with an int pkey,
- # (2) migrate data from the old table to the new table,
- # (3) delete the old revocation_event table
- # (4) rename the new revocation_event table
- revocation_table = sql.Table('revocation_event', meta, autoload=True)
-
- revocation_table_new = sql.Table(
- 'revocation_event_new',
- meta,
- sql.Column('id', sql.Integer, primary_key=True),
- sql.Column('domain_id', sql.String(64)),
- sql.Column('project_id', sql.String(64)),
- sql.Column('user_id', sql.String(64)),
- sql.Column('role_id', sql.String(64)),
- sql.Column('trust_id', sql.String(64)),
- sql.Column('consumer_id', sql.String(64)),
- sql.Column('access_token_id', sql.String(64)),
- sql.Column('issued_before', sql.DateTime(), nullable=False),
- sql.Column('expires_at', sql.DateTime()),
- sql.Column('revoked_at', sql.DateTime(), index=True, nullable=False),
- sql.Column('audit_id', sql.String(32), nullable=True),
- sql.Column('audit_chain_id', sql.String(32), nullable=True))
- revocation_table_new.create(migrate_engine, checkfirst=True)
-
- revocation_table_new.insert().from_select(['domain_id',
- 'project_id',
- 'user_id',
- 'role_id',
- 'trust_id',
- 'consumer_id',
- 'access_token_id',
- 'issued_before',
- 'expires_at',
- 'revoked_at',
- 'audit_id',
- 'audit_chain_id'],
- revocation_table.select())
-
- revocation_table.drop()
- revocation_table_new.rename('revocation_event')
diff --git a/keystone/common/sql/migrate_repo/versions/096_drop_role_name_constraint.py b/keystone/common/sql/migrate_repo/versions/096_drop_role_name_constraint.py
deleted file mode 100644
index 0156de217..000000000
--- a/keystone/common/sql/migrate_repo/versions/096_drop_role_name_constraint.py
+++ /dev/null
@@ -1,50 +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
-
-_ROLE_TABLE_NAME = 'role'
-_ROLE_NAME_COLUMN_NAME = 'name'
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- role_table = sql.Table(_ROLE_TABLE_NAME, meta, autoload=True)
-
- # NOTE(morganfainberg): the `role_name` unique constraint is not
- # guaranteed to be named 'ixu_role_name', so we need to search for the
- # correct constraint that only affects role_table.c.name and drop
- # that constraint.
- #
- # This is an idempotent change that reflects the fix to migration
- # 88 if the role_name unique constraint was not named consistently and
- # someone manually fixed the migrations / db without dropping the
- # old constraint.
- to_drop = None
- if migrate_engine.name == 'mysql':
- for c in role_table.indexes:
- if (c.unique and len(c.columns) == 1 and
- _ROLE_NAME_COLUMN_NAME in c.columns):
- to_drop = c
- break
- else:
- for c in role_table.constraints:
- if len(c.columns) == 1 and _ROLE_NAME_COLUMN_NAME in c.columns:
- to_drop = c
- break
-
- if to_drop is not None:
- migrate.UniqueConstraint(role_table.c.name,
- name=to_drop.name).drop()
diff --git a/keystone/common/sql/migrate_repo/versions/097_drop_user_name_domainid_constraint.py b/keystone/common/sql/migrate_repo/versions/097_drop_user_name_domainid_constraint.py
deleted file mode 100644
index d99d6aa6a..000000000
--- a/keystone/common/sql/migrate_repo/versions/097_drop_user_name_domainid_constraint.py
+++ /dev/null
@@ -1,67 +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
-
-_USER_TABLE_NAME = 'user'
-_USER_NAME_COLUMN_NAME = 'name'
-_USER_DOMAINID_COLUMN_NAME = 'domain_id'
-_USER_PASSWORD_COLUMN_NAME = 'password' # nosec
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- user_table = sql.Table(_USER_TABLE_NAME, meta, autoload=True)
-
- # NOTE(gnuoy): the `domain_id` unique constraint is not guaranteed to
- # be a fixed name, such as 'ixu_user_name_domain_id`, so we need to
- # search for the correct constraint that only affects
- # user_table.c.domain_id and drop that constraint. (Fix based on
- # morganfainbergs fix in 088_domain_specific_roles.py)
- #
- # This is an idempotent change that reflects the fix to migration
- # 91 if the user name & domain_id unique constraint was not named
- # consistently and someone manually fixed the migrations / db
- # without dropping the old constraint.
- to_drop = None
- if migrate_engine.name == 'mysql':
- for index in user_table.indexes:
- if (index.unique and len(index.columns) == 2 and
- _USER_DOMAINID_COLUMN_NAME in index.columns and
- _USER_NAME_COLUMN_NAME in index.columns):
- to_drop = index
- break
- else:
- for index in user_table.constraints:
- if (len(index.columns) == 2 and
- _USER_DOMAINID_COLUMN_NAME in index.columns and
- _USER_NAME_COLUMN_NAME in index.columns):
- to_drop = index
- break
-
- # remove domain_id and name unique constraint
- if to_drop is not None:
- migrate.UniqueConstraint(user_table.c.domain_id,
- user_table.c.name,
- name=to_drop.name).drop()
-
- # If migration 91 was aborted due to Bug #1572341 then columns may not
- # have been dropped.
- if _USER_DOMAINID_COLUMN_NAME in user_table.c:
- user_table.c.domain_id.drop()
- if _USER_NAME_COLUMN_NAME in user_table.c:
- user_table.c.name.drop()
- if _USER_PASSWORD_COLUMN_NAME in user_table.c:
- user_table.c.password.drop()
diff --git a/keystone/common/sql/migrate_repo/versions/098_placeholder.py b/keystone/common/sql/migrate_repo/versions/098_placeholder.py
deleted file mode 100644
index 295e0f45b..000000000
--- a/keystone/common/sql/migrate_repo/versions/098_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 Mitaka backports. Do not use this number for new
-# Newton work. New Newton work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/099_placeholder.py b/keystone/common/sql/migrate_repo/versions/099_placeholder.py
deleted file mode 100644
index 295e0f45b..000000000
--- a/keystone/common/sql/migrate_repo/versions/099_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 Mitaka backports. Do not use this number for new
-# Newton work. New Newton work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/100_placeholder.py b/keystone/common/sql/migrate_repo/versions/100_placeholder.py
deleted file mode 100644
index 295e0f45b..000000000
--- a/keystone/common/sql/migrate_repo/versions/100_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 Mitaka backports. Do not use this number for new
-# Newton work. New Newton work starts after all the placeholders.
-
-
-def upgrade(migrate_engine):
- pass
diff --git a/keystone/common/sql/migrate_repo/versions/101_drop_role_name_constraint.py b/keystone/common/sql/migrate_repo/versions/101_drop_role_name_constraint.py
deleted file mode 100644
index ff90d441d..000000000
--- a/keystone/common/sql/migrate_repo/versions/101_drop_role_name_constraint.py
+++ /dev/null
@@ -1,53 +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
-
-_ROLE_TABLE_NAME = 'role'
-_ROLE_NAME_COLUMN_NAME = 'name'
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- role_table = sql.Table(_ROLE_TABLE_NAME, meta, autoload=True)
-
- # NOTE(morganfainberg): the `role_name` unique constraint is not
- # guaranteed to be named 'ixu_role_name', so we need to search for the
- # correct constraint that only affects role_table.c.name and drop
- # that constraint.
- #
- # This is an idempotent change that reflects the fix to migration
- # 88 if the role_name unique constraint was not named consistently and
- # someone manually fixed the migrations / db without dropping the
- # old constraint.
- # This is a copy of migration 96 to catch any/all deployments that
- # are close to master. migration 96 will be backported to
- # stable/mitaka.
- to_drop = None
- if migrate_engine.name == 'mysql':
- for c in role_table.indexes:
- if (c.unique and len(c.columns) == 1 and
- _ROLE_NAME_COLUMN_NAME in c.columns):
- to_drop = c
- break
- else:
- for c in role_table.constraints:
- if len(c.columns) == 1 and _ROLE_NAME_COLUMN_NAME in c.columns:
- to_drop = c
- break
-
- if to_drop is not None:
- migrate.UniqueConstraint(role_table.c.name,
- name=to_drop.name).drop()
diff --git a/keystone/common/sql/migrate_repo/versions/102_drop_domain_table.py b/keystone/common/sql/migrate_repo/versions/102_drop_domain_table.py
deleted file mode 100644
index 85eb8e104..000000000
--- a/keystone/common/sql/migrate_repo/versions/102_drop_domain_table.py
+++ /dev/null
@@ -1,21 +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
-
- domain_table = sql.Table('domain', meta, autoload=True)
- domain_table.drop()
diff --git a/keystone/common/sql/migrate_repo/versions/103_add_nonlocal_user_table.py b/keystone/common/sql/migrate_repo/versions/103_add_nonlocal_user_table.py
deleted file mode 100644
index 2b5e6c296..000000000
--- a/keystone/common/sql/migrate_repo/versions/103_add_nonlocal_user_table.py
+++ /dev/null
@@ -1,32 +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
-
- user_table = sql.Table('user', meta, autoload=True)
-
- nonlocal_user_table = sql.Table(
- 'nonlocal_user',
- meta,
- sql.Column('domain_id', sql.String(64), primary_key=True),
- sql.Column('name', sql.String(255), primary_key=True),
- sql.Column('user_id', sql.String(64),
- sql.ForeignKey(user_table.c.id, ondelete='CASCADE'),
- nullable=False),
- mysql_engine='InnoDB',
- mysql_charset='utf8')
- nonlocal_user_table.create(migrate_engine, checkfirst=True)
diff --git a/keystone/common/sql/migrate_repo/versions/104_drop_user_name_domainid_constraint.py b/keystone/common/sql/migrate_repo/versions/104_drop_user_name_domainid_constraint.py
deleted file mode 100644
index a8740c594..000000000
--- a/keystone/common/sql/migrate_repo/versions/104_drop_user_name_domainid_constraint.py
+++ /dev/null
@@ -1,71 +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
-
-_USER_TABLE_NAME = 'user'
-_USER_NAME_COLUMN_NAME = 'name'
-_USER_DOMAINID_COLUMN_NAME = 'domain_id'
-_USER_PASSWORD_COLUMN_NAME = 'password' # nosec
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- user_table = sql.Table(_USER_TABLE_NAME, meta, autoload=True)
-
- # NOTE(gnuoy): the `domain_id` unique constraint is not guaranteed to
- # be a fixed name, such as 'ixu_user_name_domain_id`, so we need to
- # search for the correct constraint that only affects
- # user_table.c.domain_id and drop that constraint. (Fix based on
- # morganfainbergs fix in 088_domain_specific_roles.py)
- #
- # This is an idempotent change that reflects the fix to migration
- # 91 if the user name & domain_id unique constraint was not named
- # consistently and someone manually fixed the migrations / db
- # without dropping the old constraint.
- # This is a copy of migration 97 to catch any/all deployments that
- # are close to master. migration 97 will be backported to
- # stable/mitaka.
-
- to_drop = None
- if migrate_engine.name == 'mysql':
- for index in user_table.indexes:
- if (index.unique and len(index.columns) == 2 and
- _USER_DOMAINID_COLUMN_NAME in index.columns and
- _USER_NAME_COLUMN_NAME in index.columns):
- to_drop = index
- break
- else:
- for index in user_table.constraints:
- if (len(index.columns) == 2 and
- _USER_DOMAINID_COLUMN_NAME in index.columns and
- _USER_NAME_COLUMN_NAME in index.columns):
- to_drop = index
- break
-
- # remove domain_id and name unique constraint
- if to_drop is not None:
- migrate.UniqueConstraint(user_table.c.domain_id,
- user_table.c.name,
- name=to_drop.name).drop()
-
- # If migration 91 was aborted due to Bug #1572341 then columns may not
- # have been dropped.
- if _USER_DOMAINID_COLUMN_NAME in user_table.c:
- user_table.c.domain_id.drop()
- if _USER_NAME_COLUMN_NAME in user_table.c:
- user_table.c.name.drop()
- if _USER_PASSWORD_COLUMN_NAME in user_table.c:
- user_table.c.password.drop()
diff --git a/keystone/common/sql/migrate_repo/versions/105_add_password_date_columns.py b/keystone/common/sql/migrate_repo/versions/105_add_password_date_columns.py
deleted file mode 100644
index e12b82c28..000000000
--- a/keystone/common/sql/migrate_repo/versions/105_add_password_date_columns.py
+++ /dev/null
@@ -1,30 +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 datetime
-
-import sqlalchemy as sql
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- created_at = sql.Column('created_at', sql.DateTime(), nullable=True)
- expires_at = sql.Column('expires_at', sql.DateTime(), nullable=True)
- password_table = sql.Table('password', meta, autoload=True)
- password_table.create_column(created_at)
- password_table.create_column(expires_at)
-
- now = datetime.datetime.utcnow()
- stmt = password_table.update().values(created_at=now)
- stmt.execute()
diff --git a/keystone/common/sql/migrate_repo/versions/106_allow_password_column_to_be_nullable.py b/keystone/common/sql/migrate_repo/versions/106_allow_password_column_to_be_nullable.py
deleted file mode 100644
index 24abe1539..000000000
--- a/keystone/common/sql/migrate_repo/versions/106_allow_password_column_to_be_nullable.py
+++ /dev/null
@@ -1,21 +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
-
- password_table = sql.Table('password', meta, autoload=True)
- password_table.c.password.alter(nullable=True)
diff --git a/keystone/common/sql/migrate_repo/versions/107_add_user_date_columns.py b/keystone/common/sql/migrate_repo/versions/107_add_user_date_columns.py
deleted file mode 100644
index 64a1d1163..000000000
--- a/keystone/common/sql/migrate_repo/versions/107_add_user_date_columns.py
+++ /dev/null
@@ -1,30 +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 datetime
-
-import sqlalchemy as sql
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- created_at = sql.Column('created_at', sql.DateTime(), nullable=True)
- last_active_at = sql.Column('last_active_at', sql.Date(), nullable=True)
- user_table = sql.Table('user', meta, autoload=True)
- user_table.create_column(created_at)
- user_table.create_column(last_active_at)
-
- now = datetime.datetime.utcnow()
- stmt = user_table.update().values(created_at=now)
- stmt.execute()
diff --git a/keystone/common/sql/migrate_repo/versions/108_add_failed_auth_columns.py b/keystone/common/sql/migrate_repo/versions/108_add_failed_auth_columns.py
deleted file mode 100644
index a20487c4d..000000000
--- a/keystone/common/sql/migrate_repo/versions/108_add_failed_auth_columns.py
+++ /dev/null
@@ -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
-
-
-def upgrade(migrate_engine):
- meta = sql.MetaData()
- meta.bind = migrate_engine
-
- failed_auth_count = sql.Column('failed_auth_count', sql.Integer,
- nullable=True)
- failed_auth_at = sql.Column('failed_auth_at', sql.DateTime(),
- nullable=True)
- local_user_table = sql.Table('local_user', meta, autoload=True)
- local_user_table.create_column(failed_auth_count)
- local_user_table.create_column(failed_auth_at)
diff --git a/keystone/common/sql/migrate_repo/versions/109_add_password_self_service_column.py b/keystone/common/sql/migrate_repo/versions/109_add_password_self_service_column.py
deleted file mode 100644
index 1c85ead25..000000000
--- a/keystone/common/sql/migrate_repo/versions/109_add_password_self_service_column.py
+++ /dev/null
@@ -1,24 +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
-
- self_service_column = sql.Column('self_service', sql.Boolean,
- nullable=False, server_default='0',
- default=False)
- password_table = sql.Table('password', meta, autoload=True)
- password_table.create_column(self_service_column)
diff --git a/keystone/common/sql/migrate_repo/versions/__init__.py b/keystone/common/sql/migrate_repo/versions/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/keystone/common/sql/migrate_repo/versions/__init__.py
+++ /dev/null
diff --git a/keystone/common/sql/migrations/README.rst b/keystone/common/sql/migrations/README.rst
new file mode 100644
index 000000000..33b7373b9
--- /dev/null
+++ b/keystone/common/sql/migrations/README.rst
@@ -0,0 +1,15 @@
+Migrations for the database
+===========================
+
+This directory contains migrations for the database. These are implemented
+using `alembic`__, a lightweight database migration tool designed for usage
+with `SQLAlchemy`__.
+
+The best place to start understanding Alembic is with its own `tutorial`__. You
+can also play around with the :command:`alembic` command::
+
+ $ alembic --help
+
+.. __: https://alembic.sqlalchemy.org/en/latest/
+.. __: https://www.sqlalchemy.org/
+.. __: https://alembic.sqlalchemy.org/en/latest/tutorial.html
diff --git a/keystone/common/sql/migrations/env.py b/keystone/common/sql/migrations/env.py
new file mode 100644
index 000000000..2d116f1bd
--- /dev/null
+++ b/keystone/common/sql/migrations/env.py
@@ -0,0 +1,80 @@
+# 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.
+
+from logging.config import fileConfig
+
+from alembic import context
+from sqlalchemy import engine_from_config
+from sqlalchemy import pool
+
+# this is the Alembic Config object, which provides
+# access to the values within the .ini file in use.
+config = context.config
+
+# Interpret the config file for Python logging unless we're told not to.
+# This line sets up loggers basically.
+if config.attributes.get('configure_logger', True):
+ fileConfig(config.config_file_name)
+
+# add your model's MetaData object here
+# for 'autogenerate' support
+# from myapp import mymodel
+# target_metadata = mymodel.Base.metadata
+target_metadata = None
+
+
+def run_migrations_offline():
+ """Run migrations in 'offline' mode.
+
+ This configures the context with just a URL and not an Engine, though an
+ Engine is acceptable here as well. By skipping the Engine creation we
+ don't even need a DBAPI to be available.
+
+ Calls to context.execute() here emit the given string to the script output.
+ """
+ url = config.get_main_option("sqlalchemy.url")
+ context.configure(
+ url=url,
+ target_metadata=target_metadata,
+ literal_binds=True,
+ dialect_opts={"paramstyle": "named"},
+ )
+
+ with context.begin_transaction():
+ context.run_migrations()
+
+
+def run_migrations_online():
+ """Run migrations in 'online' mode.
+
+ In this scenario we need to create an Engine and associate a connection
+ with the context.
+ """
+ connectable = engine_from_config(
+ config.get_section(config.config_ini_section),
+ prefix="sqlalchemy.",
+ poolclass=pool.NullPool,
+ )
+
+ with connectable.connect() as connection:
+ context.configure(
+ connection=connection, target_metadata=target_metadata
+ )
+
+ with context.begin_transaction():
+ context.run_migrations()
+
+
+if context.is_offline_mode():
+ run_migrations_offline()
+else:
+ run_migrations_online()
diff --git a/keystone/common/sql/expand_repo/versions/035_expand_add_system_column_to_application_credential_table.py b/keystone/common/sql/migrations/script.py.mako
index 7f389508a..a9957ef6e 100644
--- a/keystone/common/sql/expand_repo/versions/035_expand_add_system_column_to_application_credential_table.py
+++ b/keystone/common/sql/migrations/script.py.mako
@@ -2,7 +2,7 @@
# 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
+# 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
@@ -10,16 +10,23 @@
# License for the specific language governing permissions and limitations
# under the License.
-import sqlalchemy as sql
+"""${message}
+Revision ID: ${up_revision}
+Revises: ${down_revision | comma,n}
+Create Date: ${create_date}
+"""
-def upgrade(migrate_engine):
+from alembic import op
+import sqlalchemy as sa
+${imports if imports else ""}
- meta = sql.MetaData()
- meta.bind = migrate_engine
+# revision identifiers, used by Alembic.
+revision = ${repr(up_revision)}
+down_revision = ${repr(down_revision)}
+branch_labels = ${repr(branch_labels)}
+depends_on = ${repr(depends_on)}
- system = sql.Column('system', sql.String(64), nullable=True)
- application_credential_table = sql.Table(
- 'application_credential', meta, autoload=True
- )
- application_credential_table.create_column(system)
+
+def upgrade():
+ ${upgrades if upgrades else "pass"}
diff --git a/keystone/common/sql/migrations/versions/27e647c0fad4_initial_version.py b/keystone/common/sql/migrations/versions/27e647c0fad4_initial_version.py
new file mode 100644
index 000000000..c57cdf13d
--- /dev/null
+++ b/keystone/common/sql/migrations/versions/27e647c0fad4_initial_version.py
@@ -0,0 +1,1106 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Initial version
+
+Revision ID: 27e647c0fad4
+Revises:
+Create Date: 2021-12-23 11:13:26.305412
+"""
+
+import datetime
+import textwrap
+
+from alembic import op
+from oslo_log import log
+import sqlalchemy as sql
+
+from keystone.assignment.backends import sql as assignment_sql
+from keystone.common import sql as ks_sql
+import keystone.conf
+from keystone.identity.mapping_backends import mapping as mapping_backend
+
+# revision identifiers, used by Alembic.
+revision = '27e647c0fad4'
+down_revision = None
+depends_on = None
+
+CONF = keystone.conf.CONF
+LOG = log.getLogger(__name__)
+
+NULL_DOMAIN_ID = '<<keystone.domain.root>>'
+
+# FIXME(stephenfin): Remove this as soon as we're done reworking the
+# migrations. Until then, this is necessary to allow us to use the native
+# alembic tooling (which won't register opts). Alternatively, maybe
+# the server default *shouldn't* rely on a (changeable) config option value?
+try:
+ service_provider_relay_state_prefix_default = CONF.saml.relay_state_prefix
+except Exception:
+ service_provider_relay_state_prefix_default = 'ss:mem:'
+
+
+def upgrade():
+ bind = op.get_bind()
+
+ if bind.engine.name == 'mysql':
+ # Set default DB charset to UTF8.
+ op.execute(
+ 'ALTER DATABASE %s DEFAULT CHARACTER SET utf8'
+ % bind.engine.url.database
+ )
+
+ op.create_table(
+ 'application_credential',
+ sql.Column(
+ 'internal_id', sql.Integer, primary_key=True, nullable=False
+ ),
+ sql.Column('id', sql.String(length=64), nullable=False),
+ sql.Column('name', sql.String(length=255), nullable=False),
+ sql.Column('secret_hash', sql.String(length=255), nullable=False),
+ sql.Column('description', sql.Text),
+ sql.Column('user_id', sql.String(length=64), nullable=False),
+ sql.Column('project_id', sql.String(64), nullable=True),
+ sql.Column('expires_at', ks_sql.DateTimeInt()),
+ sql.Column('system', sql.String(64), nullable=True),
+ sql.Column('unrestricted', sql.Boolean),
+ sql.UniqueConstraint(
+ 'user_id', 'name', name='duplicate_app_cred_constraint'
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'assignment',
+ sql.Column(
+ 'type',
+ sql.Enum(
+ assignment_sql.AssignmentType.USER_PROJECT,
+ assignment_sql.AssignmentType.GROUP_PROJECT,
+ assignment_sql.AssignmentType.USER_DOMAIN,
+ assignment_sql.AssignmentType.GROUP_DOMAIN,
+ name='type',
+ ),
+ nullable=False,
+ ),
+ sql.Column('actor_id', sql.String(64), nullable=False),
+ sql.Column('target_id', sql.String(64), nullable=False),
+ sql.Column('role_id', sql.String(64), nullable=False),
+ sql.Column('inherited', sql.Boolean, default=False, nullable=False),
+ sql.PrimaryKeyConstraint(
+ 'type',
+ 'actor_id',
+ 'target_id',
+ 'role_id',
+ 'inherited',
+ ),
+ sql.Index('ix_actor_id', 'actor_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'access_rule',
+ sql.Column('id', sql.Integer, primary_key=True, nullable=False),
+ sql.Column('service', sql.String(64)),
+ sql.Column('path', sql.String(128)),
+ sql.Column('method', sql.String(16)),
+ sql.Column('external_id', sql.String(64)),
+ sql.Column('user_id', sql.String(64)),
+ sql.UniqueConstraint(
+ 'external_id',
+ name='access_rule_external_id_key',
+ ),
+ sql.UniqueConstraint(
+ 'user_id',
+ 'service',
+ 'path',
+ 'method',
+ name='duplicate_access_rule_for_user_constraint',
+ ),
+ sql.Index('user_id', 'user_id'),
+ sql.Index('external_id', 'external_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'config_register',
+ sql.Column('type', sql.String(64), primary_key=True),
+ sql.Column('domain_id', sql.String(64), nullable=False),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'consumer',
+ sql.Column('id', sql.String(64), primary_key=True, nullable=False),
+ sql.Column('description', sql.String(64), nullable=True),
+ sql.Column('secret', sql.String(64), nullable=False),
+ sql.Column('extra', sql.Text(), nullable=False),
+ )
+
+ op.create_table(
+ 'credential',
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('user_id', sql.String(length=64), nullable=False),
+ sql.Column('project_id', sql.String(length=64)),
+ sql.Column('type', sql.String(length=255), nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column('key_hash', sql.String(64), nullable=False),
+ sql.Column(
+ 'encrypted_blob',
+ ks_sql.Text,
+ nullable=False,
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'group',
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('domain_id', sql.String(length=64), nullable=False),
+ sql.Column('name', sql.String(length=64), nullable=False),
+ sql.Column('description', sql.Text),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.UniqueConstraint(
+ 'domain_id',
+ 'name',
+ name='ixu_group_name_domain_id',
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'id_mapping',
+ sql.Column('public_id', sql.String(64), primary_key=True),
+ sql.Column('domain_id', sql.String(64), nullable=False),
+ sql.Column('local_id', sql.String(255), nullable=False),
+ sql.Column(
+ 'entity_type',
+ sql.Enum(
+ mapping_backend.EntityType.USER,
+ mapping_backend.EntityType.GROUP,
+ name='entity_type',
+ ),
+ nullable=False,
+ ),
+ sql.UniqueConstraint(
+ 'domain_id',
+ 'local_id',
+ 'entity_type',
+ name='domain_id',
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'identity_provider',
+ 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),
+ sql.Column('authorization_ttl', sql.Integer, nullable=True),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'idp_remote_ids',
+ sql.Column(
+ 'idp_id',
+ sql.String(64),
+ sql.ForeignKey('identity_provider.id', ondelete='CASCADE'),
+ ),
+ sql.Column('remote_id', sql.String(255), primary_key=True),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'mapping',
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('rules', sql.Text(), nullable=False),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'policy',
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('type', sql.String(length=255), nullable=False),
+ sql.Column('blob', ks_sql.JsonBlob, nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'policy_association',
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('policy_id', sql.String(64), nullable=False),
+ sql.Column('endpoint_id', sql.String(64), nullable=True),
+ sql.Column('service_id', sql.String(64), nullable=True),
+ sql.Column('region_id', sql.String(64), nullable=True),
+ sql.UniqueConstraint('endpoint_id', 'service_id', 'region_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'project',
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('name', sql.String(length=64), nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column('description', sql.Text),
+ sql.Column('enabled', sql.Boolean),
+ sql.Column(
+ 'domain_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ 'project.id',
+ name='project_domain_id_fkey',
+ ),
+ nullable=False,
+ ),
+ sql.Column(
+ 'parent_id',
+ sql.String(64),
+ sql.ForeignKey(
+ 'project.id',
+ name='project_parent_id_fkey',
+ ),
+ nullable=True,
+ ),
+ sql.Column(
+ 'is_domain',
+ sql.Boolean,
+ nullable=False,
+ server_default='0',
+ default=False,
+ ),
+ sql.UniqueConstraint(
+ 'domain_id',
+ 'name',
+ name='ixu_project_name_domain_id',
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'project_endpoint',
+ sql.Column(
+ 'endpoint_id', sql.String(64), primary_key=True, nullable=False
+ ),
+ sql.Column(
+ 'project_id', sql.String(64), primary_key=True, nullable=False
+ ),
+ )
+
+ op.create_table(
+ 'project_option',
+ sql.Column(
+ 'project_id',
+ sql.String(64),
+ sql.ForeignKey('project.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',
+ )
+
+ # NOTE(lamt) To allow tag name to be case sensitive for MySQL, the 'name'
+ # column needs to use collation, which is incompatible with Postgresql.
+ # Using unicode to mirror nova's server tag:
+ # https://github.com/openstack/nova/blob/master/nova/db/sqlalchemy/models.py
+ op.create_table(
+ 'project_tag',
+ sql.Column(
+ 'project_id',
+ sql.String(64),
+ sql.ForeignKey('project.id', ondelete='CASCADE'),
+ nullable=False,
+ primary_key=True,
+ ),
+ sql.Column('name', sql.Unicode(255), nullable=False, primary_key=True),
+ sql.UniqueConstraint('project_id', 'name'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'region',
+ sql.Column('id', sql.String(255), primary_key=True),
+ sql.Column('description', sql.String(255), nullable=False),
+ sql.Column('parent_region_id', sql.String(255), nullable=True),
+ sql.Column('extra', sql.Text()),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'registered_limit',
+ 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.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',
+ )
+
+ op.create_table(
+ 'request_token',
+ sql.Column('id', sql.String(64), primary_key=True, nullable=False),
+ sql.Column('request_secret', sql.String(64), nullable=False),
+ sql.Column('verifier', sql.String(64), nullable=True),
+ sql.Column('authorizing_user_id', sql.String(64), nullable=True),
+ sql.Column('requested_project_id', sql.String(64), nullable=False),
+ sql.Column('role_ids', sql.Text(), nullable=True),
+ sql.Column(
+ 'consumer_id',
+ sql.String(64),
+ sql.ForeignKey('consumer.id'),
+ nullable=False,
+ index=True,
+ ),
+ sql.Column('expires_at', sql.String(64), nullable=True),
+ )
+
+ op.create_table(
+ 'revocation_event',
+ sql.Column('id', sql.Integer, primary_key=True),
+ sql.Column('domain_id', sql.String(64)),
+ sql.Column('project_id', sql.String(64)),
+ sql.Column('user_id', sql.String(64)),
+ sql.Column('role_id', sql.String(64)),
+ sql.Column('trust_id', sql.String(64)),
+ sql.Column('consumer_id', sql.String(64)),
+ sql.Column('access_token_id', sql.String(64)),
+ sql.Column('issued_before', sql.DateTime(), nullable=False),
+ sql.Column('expires_at', sql.DateTime()),
+ sql.Column('revoked_at', sql.DateTime(), nullable=False),
+ sql.Column('audit_id', sql.String(32), nullable=True),
+ sql.Column('audit_chain_id', sql.String(32), nullable=True),
+ # NOTE(stephenfin): The '_new' suffix here is due to migration 095,
+ # which changed the 'id' column from String(64) to Integer. It did this
+ # by creating a 'revocation_event_new' table and populating it with
+ # data from the 'revocation_event' table before deleting the
+ # 'revocation_event' table and renaming the 'revocation_event_new'
+ # table to 'revocation_event'. Because the 'revoked_at' column had
+ # 'index=True', sqlalchemy automatically generated the index name as
+ # 'ix_{table}_{column}'. However, when intitially created, '{table}'
+ # 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',
+ ),
+ )
+
+ op.create_table(
+ 'role',
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('name', sql.String(length=255), nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column(
+ 'domain_id',
+ sql.String(64),
+ nullable=False,
+ server_default='<<null>>',
+ ),
+ sql.Column('description', sql.String(255), nullable=True),
+ sql.UniqueConstraint(
+ 'name',
+ 'domain_id',
+ name='ixu_role_name_domain_id',
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'role_option',
+ sql.Column(
+ 'role_id',
+ sql.String(64),
+ sql.ForeignKey('role.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',
+ )
+
+ op.create_table(
+ 'sensitive_config',
+ sql.Column('domain_id', sql.String(64), primary_key=True),
+ sql.Column('group', sql.String(255), primary_key=True),
+ sql.Column('option', sql.String(255), primary_key=True),
+ sql.Column('value', ks_sql.JsonBlob.impl, nullable=False),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'service',
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('type', sql.String(length=255)),
+ sql.Column(
+ 'enabled',
+ sql.Boolean,
+ nullable=False,
+ default=True,
+ server_default='1',
+ ),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'service_provider',
+ sql.Column('auth_url', sql.String(256), nullable=False),
+ 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('sp_url', sql.String(256), nullable=False),
+ sql.Column(
+ 'relay_state_prefix',
+ sql.String(256),
+ nullable=False,
+ server_default=service_provider_relay_state_prefix_default,
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'system_assignment',
+ sql.Column('type', sql.String(64), nullable=False),
+ sql.Column('actor_id', sql.String(64), nullable=False),
+ sql.Column('target_id', sql.String(64), nullable=False),
+ sql.Column('role_id', sql.String(64), nullable=False),
+ sql.Column('inherited', sql.Boolean, default=False, nullable=False),
+ sql.PrimaryKeyConstraint(
+ 'type', 'actor_id', 'target_id', 'role_id', 'inherited'
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'token',
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('expires', sql.DateTime, default=None),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column('valid', sql.Boolean, default=True, nullable=False),
+ 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_user_id', 'user_id'),
+ sql.Index('ix_token_trust_id', 'trust_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'trust',
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('trustor_user_id', sql.String(length=64), nullable=False),
+ sql.Column('trustee_user_id', sql.String(length=64), nullable=False),
+ sql.Column('project_id', sql.String(length=64)),
+ sql.Column('impersonation', sql.Boolean, nullable=False),
+ sql.Column('deleted_at', sql.DateTime),
+ sql.Column('expires_at', sql.DateTime),
+ sql.Column('remaining_uses', sql.Integer, nullable=True),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column('expires_at_int', ks_sql.DateTimeInt()),
+ sql.UniqueConstraint(
+ 'trustor_user_id',
+ 'trustee_user_id',
+ 'project_id',
+ 'impersonation',
+ 'expires_at',
+ 'expires_at_int',
+ name='duplicate_trust_constraint_expanded',
+ ),
+ sql.Column(
+ 'redelegated_trust_id',
+ sql.String(64),
+ nullable=True,
+ ),
+ sql.Column(
+ 'redelegation_count',
+ sql.Integer,
+ nullable=True,
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'trust_role',
+ sql.Column(
+ 'trust_id', sql.String(length=64), primary_key=True, nullable=False
+ ),
+ sql.Column(
+ 'role_id', sql.String(length=64), primary_key=True, nullable=False
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'user',
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column('enabled', sql.Boolean),
+ 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), nullable=False),
+ sql.UniqueConstraint('id', 'domain_id', name='ixu_user_id_domain_id'),
+ sql.Index('ix_default_project_id', 'default_project_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'user_group_membership',
+ sql.Column(
+ 'user_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ 'user.id',
+ name='fk_user_group_membership_user_id',
+ ),
+ primary_key=True,
+ ),
+ sql.Column(
+ 'group_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ 'group.id',
+ name='fk_user_group_membership_group_id',
+ ),
+ primary_key=True,
+ ),
+ # NOTE(stevemar): The index was named 'group_id' in
+ # 050_fk_consistent_indexes.py and needs to be preserved
+ sql.Index('group_id', 'group_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'user_option',
+ sql.Column(
+ 'user_id',
+ sql.String(64),
+ sql.ForeignKey('user.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',
+ )
+
+ op.create_table(
+ 'whitelisted_config',
+ sql.Column('domain_id', sql.String(64), primary_key=True),
+ sql.Column('group', sql.String(255), primary_key=True),
+ sql.Column('option', sql.String(255), primary_key=True),
+ sql.Column('value', ks_sql.JsonBlob.impl, nullable=False),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'access_token',
+ sql.Column('id', sql.String(64), primary_key=True, nullable=False),
+ sql.Column('access_secret', sql.String(64), nullable=False),
+ sql.Column(
+ 'authorizing_user_id', sql.String(64), nullable=False, index=True
+ ),
+ sql.Column('project_id', sql.String(64), nullable=False),
+ sql.Column('role_ids', sql.Text(), nullable=False),
+ sql.Column(
+ 'consumer_id',
+ sql.String(64),
+ sql.ForeignKey('consumer.id'),
+ nullable=False,
+ index=True,
+ ),
+ sql.Column('expires_at', sql.String(64), nullable=True),
+ )
+
+ op.create_table(
+ 'application_credential_role',
+ sql.Column(
+ 'application_credential_id',
+ sql.Integer,
+ sql.ForeignKey(
+ 'application_credential.internal_id', ondelete='CASCADE'
+ ),
+ primary_key=True,
+ nullable=False,
+ ),
+ sql.Column(
+ 'role_id', sql.String(length=64), primary_key=True, nullable=False
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'application_credential_access_rule',
+ sql.Column(
+ 'application_credential_id',
+ sql.Integer,
+ sql.ForeignKey(
+ 'application_credential.internal_id', ondelete='CASCADE'
+ ),
+ primary_key=True,
+ nullable=False,
+ ),
+ sql.Column(
+ 'access_rule_id',
+ sql.Integer,
+ sql.ForeignKey('access_rule.id', ondelete='CASCADE'),
+ primary_key=True,
+ nullable=False,
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'endpoint',
+ sql.Column('id', sql.String(length=64), primary_key=True),
+ sql.Column('legacy_endpoint_id', sql.String(length=64)),
+ sql.Column('interface', sql.String(length=8), nullable=False),
+ sql.Column(
+ 'service_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ 'service.id',
+ name='endpoint_service_id_fkey',
+ ),
+ nullable=False,
+ ),
+ sql.Column('url', sql.Text, nullable=False),
+ sql.Column('extra', ks_sql.JsonBlob.impl),
+ sql.Column(
+ 'enabled',
+ sql.Boolean,
+ nullable=False,
+ default=True,
+ server_default='1',
+ ),
+ sql.Column(
+ 'region_id',
+ sql.String(length=255),
+ sql.ForeignKey(
+ 'region.id',
+ name='fk_endpoint_region_id',
+ ),
+ nullable=True,
+ ),
+ # NOTE(stevemar): The index was named 'service_id' in
+ # 050_fk_consistent_indexes.py and needs to be preserved
+ sql.Index('service_id', 'service_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'endpoint_group',
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column('name', sql.String(255), nullable=False),
+ sql.Column('description', sql.Text, nullable=True),
+ sql.Column('filters', sql.Text(), nullable=False),
+ )
+
+ op.create_table(
+ 'expiring_user_group_membership',
+ sql.Column(
+ 'user_id',
+ sql.String(64),
+ sql.ForeignKey('user.id'),
+ primary_key=True,
+ ),
+ sql.Column(
+ 'group_id',
+ sql.String(64),
+ sql.ForeignKey('group.id'),
+ primary_key=True,
+ ),
+ sql.Column(
+ 'idp_id',
+ sql.String(64),
+ sql.ForeignKey('identity_provider.id', ondelete='CASCADE'),
+ primary_key=True,
+ ),
+ sql.Column('last_verified', sql.DateTime(), nullable=False),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'federation_protocol',
+ sql.Column('id', sql.String(64), primary_key=True),
+ sql.Column(
+ 'idp_id',
+ sql.String(64),
+ sql.ForeignKey('identity_provider.id', ondelete='CASCADE'),
+ primary_key=True,
+ ),
+ sql.Column('mapping_id', sql.String(64), nullable=False),
+ sql.Column('remote_id_attribute', sql.String(64)),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'implied_role',
+ sql.Column(
+ 'prior_role_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ 'role.id',
+ name='implied_role_prior_role_id_fkey',
+ ondelete='CASCADE',
+ ),
+ primary_key=True,
+ ),
+ sql.Column(
+ 'implied_role_id',
+ sql.String(length=64),
+ sql.ForeignKey(
+ 'role.id',
+ name='implied_role_implied_role_id_fkey',
+ ondelete='CASCADE',
+ ),
+ primary_key=True,
+ ),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'limit',
+ sql.Column('id', sql.String(length=64), nullable=False),
+ sql.Column('project_id', sql.String(64), nullable=True),
+ sql.Column('resource_limit', sql.Integer, nullable=False),
+ 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),
+ ),
+ sql.Column('domain_id', sql.String(64), nullable=True),
+ # 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',
+ )
+
+ op.create_table(
+ 'local_user',
+ sql.Column('id', sql.Integer, primary_key=True, nullable=False),
+ sql.Column(
+ 'user_id',
+ sql.String(64),
+ nullable=False,
+ unique=True,
+ ),
+ sql.Column('domain_id', sql.String(64), nullable=False),
+ sql.Column('name', sql.String(255), nullable=False),
+ sql.Column('failed_auth_count', sql.Integer, nullable=True),
+ sql.Column('failed_auth_at', sql.DateTime(), nullable=True),
+ sql.ForeignKeyConstraint(
+ ['user_id', 'domain_id'],
+ ['user.id', 'user.domain_id'],
+ name='local_user_user_id_fkey',
+ onupdate='CASCADE',
+ ondelete='CASCADE',
+ ),
+ sql.UniqueConstraint('domain_id', 'name'),
+ )
+
+ op.create_table(
+ 'nonlocal_user',
+ sql.Column('domain_id', sql.String(64), primary_key=True),
+ sql.Column('name', sql.String(255), primary_key=True),
+ sql.Column(
+ 'user_id',
+ sql.String(64),
+ nullable=False,
+ ),
+ sql.ForeignKeyConstraint(
+ ['user_id', 'domain_id'],
+ ['user.id', 'user.domain_id'],
+ name='nonlocal_user_user_id_fkey',
+ onupdate='CASCADE',
+ ondelete='CASCADE',
+ ),
+ sql.UniqueConstraint('user_id', name='ixu_nonlocal_user_user_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ op.create_table(
+ 'password',
+ sql.Column('id', sql.Integer, primary_key=True, nullable=False),
+ sql.Column(
+ 'local_user_id',
+ sql.Integer,
+ sql.ForeignKey('local_user.id', ondelete='CASCADE'),
+ nullable=False,
+ ),
+ sql.Column('expires_at', sql.DateTime(), nullable=True),
+ sql.Column(
+ 'self_service',
+ sql.Boolean,
+ nullable=False,
+ server_default='0',
+ default=False,
+ ),
+ # NOTE(notmorgan): To support the full range of scrypt and pbkfd
+ # password hash lengths, this should be closer to varchar(1500) instead
+ # of varchar(255).
+ sql.Column('password_hash', sql.String(255), nullable=True),
+ sql.Column(
+ 'created_at_int',
+ ks_sql.DateTimeInt(),
+ nullable=False,
+ default=0,
+ server_default='0',
+ ),
+ sql.Column('expires_at_int', ks_sql.DateTimeInt(), nullable=True),
+ sql.Column(
+ 'created_at',
+ sql.DateTime(),
+ nullable=False,
+ default=datetime.datetime.utcnow,
+ ),
+ )
+
+ op.create_table(
+ 'project_endpoint_group',
+ sql.Column(
+ 'endpoint_group_id',
+ sql.String(64),
+ sql.ForeignKey('endpoint_group.id'),
+ nullable=False,
+ ),
+ sql.Column('project_id', sql.String(64), nullable=False),
+ sql.PrimaryKeyConstraint('endpoint_group_id', 'project_id'),
+ )
+
+ op.create_table(
+ 'federated_user',
+ sql.Column('id', sql.Integer, primary_key=True, nullable=False),
+ sql.Column(
+ 'user_id',
+ sql.String(64),
+ sql.ForeignKey('user.id', ondelete='CASCADE'),
+ nullable=False,
+ ),
+ sql.Column(
+ 'idp_id',
+ sql.String(64),
+ sql.ForeignKey('identity_provider.id', ondelete='CASCADE'),
+ nullable=False,
+ ),
+ sql.Column('protocol_id', sql.String(64), nullable=False),
+ sql.Column('unique_id', sql.String(255), nullable=False),
+ sql.Column('display_name', sql.String(255), nullable=True),
+ sql.ForeignKeyConstraint(
+ ['protocol_id', 'idp_id'],
+ ['federation_protocol.id', 'federation_protocol.idp_id'],
+ name='federated_user_protocol_id_fkey',
+ ondelete='CASCADE',
+ ),
+ sql.UniqueConstraint('idp_id', 'protocol_id', 'unique_id'),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ if bind.engine.name == 'sqlite':
+ # NOTE(stevemar): We need to keep this FK constraint due to 073, but
+ # only for sqlite, once we collapse 073 we can remove this constraint
+ with op.batch_alter_table('assignment') as batch_op:
+ batch_op.create_foreign_key(
+ 'fk_assignment_role_id',
+ 'role',
+ ['role_id'],
+ ['id'],
+ )
+
+ # TODO(stephenfin): Remove these procedures in a future contract migration
+
+ if bind.engine.name == 'postgresql':
+ error_message = (
+ 'Credential migration in progress. Cannot perform '
+ 'writes to credential table.'
+ )
+ credential_update_trigger = textwrap.dedent(f"""
+ CREATE OR REPLACE FUNCTION keystone_read_only_update()
+ RETURNS trigger AS
+ $BODY$
+ BEGIN
+ IF NEW.encrypted_blob IS NULL THEN
+ RAISE EXCEPTION '{error_message}';
+ END IF;
+ IF NEW.encrypted_blob IS NOT NULL AND OLD.blob IS NULL THEN
+ RAISE EXCEPTION '{error_message}';
+ END IF;
+ RETURN NEW;
+ END
+ $BODY$ LANGUAGE plpgsql;
+ """)
+ op.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;
+ """)
+ op.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;
+ """)
+ op.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;
+ """)
+ op.execute(local_user_insert_trigger)
+
+ # FIXME(stephenfin): Remove these indexes. They're left over from attempts
+ # to remove foreign key constraints in past migrations. Apparently
+ # sqlalchemy-migrate didn't do the job fully and left behind indexes
+ if bind.engine.name == 'mysql':
+ op.create_index('region_id', 'registered_limit', ['region_id'])
+
+ # FIXME(stephenfin): This should be dropped when we add the FK
+ # constraint to this column
+ op.create_index(
+ 'registered_limit_id',
+ 'limit',
+ ['registered_limit_id'],
+ )
+
+ # FIXME(stephenfin): These are leftover from when we removed a FK
+ # constraint and should probable be dropped
+ op.create_index('domain_id', 'identity_provider', ['domain_id'])
+ op.create_index('domain_id', 'user', ['domain_id'])
+
+ # data migration
+
+ def _generate_root_domain_project():
+ # Generate a project that will act as a root for all domains, in order
+ # for use to be able to use a FK constraint on domain_id. Projects
+ # acting as a domain will not reference this as their parent_id, just
+ # as domain_id.
+ #
+ # This special project is filtered out by the driver, so is never
+ # visible to the manager or API.
+
+ project_ref = {
+ 'id': NULL_DOMAIN_ID,
+ 'name': NULL_DOMAIN_ID,
+ 'enabled': False,
+ 'description': '',
+ 'domain_id': NULL_DOMAIN_ID,
+ 'is_domain': True,
+ 'parent_id': None,
+ 'extra': '{}',
+ }
+ return project_ref
+
+ bind = op.get_bind()
+ meta = sql.MetaData()
+ project = sql.Table('project', meta, autoload_with=bind.engine)
+
+ root_domain_project = _generate_root_domain_project()
+ op.execute(project.insert().values(**root_domain_project))
diff --git a/keystone/common/sql/migrations/versions/CONTRACT_HEAD b/keystone/common/sql/migrations/versions/CONTRACT_HEAD
new file mode 100644
index 000000000..8dc296b9c
--- /dev/null
+++ b/keystone/common/sql/migrations/versions/CONTRACT_HEAD
@@ -0,0 +1 @@
+e25ffa003242
diff --git a/keystone/common/sql/migrations/versions/EXPAND_HEAD b/keystone/common/sql/migrations/versions/EXPAND_HEAD
new file mode 100644
index 000000000..b2bd55d17
--- /dev/null
+++ b/keystone/common/sql/migrations/versions/EXPAND_HEAD
@@ -0,0 +1 @@
+29e87d24a316
diff --git a/keystone/common/sql/expand_repo/versions/001_expand_initial_null_migration.py b/keystone/common/sql/migrations/versions/yoga/contract/e25ffa003242_initial.py
index 1cd34e617..bb36d3b2b 100644
--- a/keystone/common/sql/expand_repo/versions/001_expand_initial_null_migration.py
+++ b/keystone/common/sql/migrations/versions/yoga/contract/e25ffa003242_initial.py
@@ -2,7 +2,7 @@
# 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
+# 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
@@ -10,9 +10,18 @@
# License for the specific language governing permissions and limitations
# under the License.
-# A null initial migration to open this repo. Do not re-use replace this with
-# a real migration, add additional ones in subsequent version scripts.
+"""Initial no-op Yoga contract migration.
+Revision ID: e25ffa003242
+Revises: 27e647c0fad4
+Create Date: 2022-01-21 00:00:00.000000
+"""
-def upgrade(migrate_engine):
+# revision identifiers, used by Alembic.
+revision = 'e25ffa003242'
+down_revision = '27e647c0fad4'
+branch_labels = ('contract',)
+
+
+def upgrade():
pass
diff --git a/keystone/common/sql/data_migration_repo/versions/001_data_initial_null_migration.py b/keystone/common/sql/migrations/versions/yoga/expand/29e87d24a316_initial.py
index 1cd34e617..8fd4c5a84 100644
--- a/keystone/common/sql/data_migration_repo/versions/001_data_initial_null_migration.py
+++ b/keystone/common/sql/migrations/versions/yoga/expand/29e87d24a316_initial.py
@@ -2,7 +2,7 @@
# 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
+# 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
@@ -10,9 +10,18 @@
# License for the specific language governing permissions and limitations
# under the License.
-# A null initial migration to open this repo. Do not re-use replace this with
-# a real migration, add additional ones in subsequent version scripts.
+"""Initial no-op Yoga expand migration.
+Revision ID: 29e87d24a316
+Revises: 27e647c0fad4
+Create Date: 2022-01-21 00:00:00.000000
+"""
-def upgrade(migrate_engine):
+# revision identifiers, used by Alembic.
+revision = '29e87d24a316'
+down_revision = '27e647c0fad4'
+branch_labels = ('expand',)
+
+
+def upgrade():
pass
diff --git a/keystone/common/sql/upgrades.py b/keystone/common/sql/upgrades.py
index 8bfe453cf..f463771f2 100644
--- a/keystone/common/sql/upgrades.py
+++ b/keystone/common/sql/upgrades.py
@@ -16,226 +16,154 @@
import os
-import migrate
-from migrate import exceptions
-from migrate.versioning import api as versioning_api
+from migrate import exceptions as migrate_exceptions
+from migrate.versioning import api as migrate_api
+from migrate.versioning import repository as migrate_repository
from oslo_db import exception as db_exception
-from oslo_db.sqlalchemy import migration
-import sqlalchemy
+import sqlalchemy as sa
from keystone.common import sql
from keystone import exception
from keystone.i18n import _
+INITIAL_VERSION = 72
+LATEST_VERSION = 79
+EXPAND_BRANCH = 'expand'
+DATA_MIGRATION_BRANCH = 'data_migration'
+CONTRACT_BRANCH = 'contract'
-USE_TRIGGERS = True
-
-LEGACY_REPO = 'migrate_repo'
-EXPAND_REPO = 'expand_repo'
-DATA_MIGRATION_REPO = 'data_migration_repo'
-CONTRACT_REPO = 'contract_repo'
-
-
-class Repository(object):
- def __init__(self, engine, repo_name):
- self.repo_name = repo_name
-
- self.repo_path = find_repo(self.repo_name)
- self.min_version = (
- get_init_version(abs_path=self.repo_path))
- self.schema_ = versioning_api.ControlledSchema.create(
- engine, self.repo_path, self.min_version)
- self.max_version = self.schema_.repository.version().version
-
- def upgrade(self, version=None, current_schema=None):
- version = version or self.max_version
- err = ''
- upgrade = True
- version = versioning_api._migrate_version(
- self.schema_, version, upgrade, err)
- validate_upgrade_order(self.repo_name, target_repo_version=version)
- if not current_schema:
- current_schema = self.schema_
- changeset = current_schema.changeset(version)
- for ver, change in changeset:
- self.schema_.runchange(ver, change, changeset.step)
-
- if self.schema_.version != version:
- raise Exception(
- 'Actual version (%s) of %s does not equal expected '
- 'version (%s)' % (
- self.schema_.version, self.repo_name, version))
-
- @property
- def version(self):
- with sql.session_for_read() as session:
- return migration.db_version(
- session.get_bind(), self.repo_path, self.min_version)
-
-
-# Different RDBMSs use different schemes for naming the Foreign Key
-# Constraints. SQLAlchemy does not yet attempt to determine the name
-# for the constraint, and instead attempts to deduce it from the column.
-# This fails on MySQL.
-def get_constraints_names(table, column_name):
- fkeys = [fk.name for fk in table.constraints
- if (isinstance(fk, sqlalchemy.ForeignKeyConstraint) and
- column_name in fk.columns)]
- return fkeys
-
-
-# remove_constraints and add_constraints both accept a list of dictionaries
-# that contain:
-# {'table': a sqlalchemy table. The constraint is added to dropped from
-# this table.
-# 'fk_column': the name of a column on the above table, The constraint
-# is added to or dropped from this column
-# 'ref_column':a sqlalchemy column object. This is the reference column
-# for the constraint.
-def remove_constraints(constraints):
- for constraint_def in constraints:
- constraint_names = get_constraints_names(constraint_def['table'],
- constraint_def['fk_column'])
- for constraint_name in constraint_names:
- migrate.ForeignKeyConstraint(
- columns=[getattr(constraint_def['table'].c,
- constraint_def['fk_column'])],
- refcolumns=[constraint_def['ref_column']],
- name=constraint_name).drop()
-
-
-def add_constraints(constraints):
- for constraint_def in constraints:
-
- if constraint_def['table'].kwargs.get('mysql_engine') == 'MyISAM':
- # Don't try to create constraint when using MyISAM because it's
- # not supported.
- continue
-
- ref_col = constraint_def['ref_column']
- ref_engine = ref_col.table.kwargs.get('mysql_engine')
- if ref_engine == 'MyISAM':
- # Don't try to create constraint when using MyISAM because it's
- # not supported.
- continue
-
- migrate.ForeignKeyConstraint(
- columns=[getattr(constraint_def['table'].c,
- constraint_def['fk_column'])],
- refcolumns=[constraint_def['ref_column']]).create()
-
-
-def find_repo(repo_name):
- """Return the absolute path to the named repository."""
- path = os.path.abspath(os.path.join(
- os.path.dirname(sql.__file__), repo_name))
-
- if not os.path.isdir(path):
- raise exception.MigrationNotProvided(sql.__name__, path)
-
- return path
-
-
-def _sync_common_repo(version):
- abs_path = find_repo(LEGACY_REPO)
- init_version = get_init_version()
- with sql.session_for_write() as session:
- engine = session.get_bind()
- _assert_not_schema_downgrade(version=version)
- migration.db_sync(engine, abs_path, version=version,
- init_version=init_version, sanity_check=False)
+def _get_migrate_repo_path(branch):
+ abs_path = os.path.abspath(
+ os.path.join(
+ os.path.dirname(sql.__file__),
+ 'legacy_migrations',
+ f'{branch}_repo',
+ )
+ )
-def _sync_repo(repo_name):
- abs_path = find_repo(repo_name)
- with sql.session_for_write() as session:
- engine = session.get_bind()
- # Register the repo with the version control API
- # If it already knows about the repo, it will throw
- # an exception that we can safely ignore
- try:
- migration.db_version_control(engine, abs_path)
- except (migration.exception.DBMigrationError,
- exceptions.DatabaseAlreadyControlledError): # nosec
- pass
- init_version = get_init_version(abs_path=abs_path)
- migration.db_sync(engine, abs_path,
- init_version=init_version, sanity_check=False)
+ if not os.path.isdir(abs_path):
+ raise exception.MigrationNotProvided(sql.__name__, abs_path)
+ return abs_path
-def get_init_version(abs_path=None):
- """Get the initial version of a migrate repository.
- :param abs_path: Absolute path to migrate repository.
- :return: initial version number or None, if DB is empty.
+def _find_migrate_repo(abs_path):
+ """Get the project's change script repository
+
+ :param abs_path: Absolute path to migrate repository
"""
- if abs_path is None:
- abs_path = find_repo(LEGACY_REPO)
+ if not os.path.exists(abs_path):
+ raise db_exception.DBMigrationError("Path %s not found" % abs_path)
+ return migrate_repository.Repository(abs_path)
- repo = migrate.versioning.repository.Repository(abs_path)
- # Sadly, Repository has a `latest` but not an `oldest`.
- # The value is a VerNum object which needs to be converted into an int.
- oldest = int(min(repo.versions.versions))
+def _migrate_db_version_control(engine, abs_path, version=None):
+ """Mark a database as under this repository's version control.
- if oldest < 1:
- return None
+ Once a database is under version control, schema changes should
+ only be done via change scripts in this repository.
- # The initial version is one less
- return oldest - 1
+ :param engine: SQLAlchemy engine instance for a given database
+ :param abs_path: Absolute path to migrate repository
+ :param version: Initial database version
+ """
+ repository = _find_migrate_repo(abs_path)
+ try:
+ migrate_api.version_control(engine, repository, version)
+ except migrate_exceptions.InvalidVersionError as ex:
+ raise db_exception.DBMigrationError("Invalid version : %s" % ex)
+ except migrate_exceptions.DatabaseAlreadyControlledError:
+ raise db_exception.DBMigrationError("Database is already controlled.")
-def _assert_not_schema_downgrade(version=None):
- if version is not None:
- try:
- current_ver = int(str(get_db_version()))
- if int(version) < current_ver:
- raise migration.exception.DBMigrationError(
- _("Unable to downgrade schema"))
- except exceptions.DatabaseNotControlledError: # nosec
- # NOTE(morganfainberg): The database is not controlled, this action
- # cannot be a downgrade.
- pass
+ return version
-def offline_sync_database_to_version(version=None):
- """Perform and off-line sync of the database.
-
- Migrate the database up to the latest version, doing the equivalent of
- the cycle of --expand, --migrate and --contract, for when an offline
- upgrade is being performed.
-
- If a version is specified then only migrate the database up to that
- version. Downgrading is not supported. If version is specified, then only
- the main database migration is carried out - and the expand, migration and
- contract phases will NOT be run.
+def _migrate_db_version(engine, abs_path, init_version):
+ """Show the current version of the repository.
+ :param engine: SQLAlchemy engine instance for a given database
+ :param abs_path: Absolute path to migrate repository
+ :param init_version: Initial database version
+ """
+ repository = _find_migrate_repo(abs_path)
+ try:
+ return migrate_api.db_version(engine, repository)
+ except migrate_exceptions.DatabaseNotControlledError:
+ pass
+
+ meta = sa.MetaData()
+ meta.reflect(bind=engine)
+ tables = meta.tables
+ if (
+ len(tables) == 0 or
+ 'alembic_version' in tables or
+ 'migrate_version' in tables
+ ):
+ _migrate_db_version_control(engine, abs_path, version=init_version)
+ return migrate_api.db_version(engine, repository)
+
+ msg = _(
+ "The database is not under version control, but has tables. "
+ "Please stamp the current version of the schema manually."
+ )
+ raise db_exception.DBMigrationError(msg)
+
+
+def _migrate_db_sync(engine, abs_path, version=None, init_version=0):
+ """Upgrade or downgrade a database.
+
+ Function runs the upgrade() or downgrade() functions in change scripts.
+
+ :param engine: SQLAlchemy engine instance for a given database
+ :param abs_path: Absolute path to migrate repository.
+ :param version: Database will upgrade/downgrade until this version.
+ If None - database will update to the latest available version.
+ :param init_version: Initial database version
"""
- global USE_TRIGGERS
- # This flags let's us bypass trigger setup & teardown for non-rolling
- # upgrades. We set this as a global variable immediately before handing off
- # to sqlalchemy-migrate, because we can't pass arguments directly to
- # migrations that depend on it. We could also register this as a CONF
- # option, but the idea here is that we aren't exposing a new API.
- USE_TRIGGERS = False
+ if version is not None:
+ try:
+ version = int(version)
+ except ValueError:
+ msg = _("version should be an integer")
+ raise db_exception.DBMigrationError(msg)
+
+ current_version = _migrate_db_version(engine, abs_path, init_version)
+ repository = _find_migrate_repo(abs_path)
- if version:
- _sync_common_repo(version)
+ if version is None or version > current_version:
+ try:
+ return migrate_api.upgrade(engine, repository, version)
+ except Exception as ex:
+ raise db_exception.DBMigrationError(ex)
else:
- expand_schema()
- migrate_data()
- contract_schema()
+ return migrate_api.downgrade(engine, repository, version)
-def get_db_version(repo=LEGACY_REPO):
+def get_db_version(branch=EXPAND_BRANCH):
+ abs_path = _get_migrate_repo_path(branch)
with sql.session_for_read() as session:
- repo = find_repo(repo)
- return migration.db_version(
- session.get_bind(), repo, get_init_version(repo))
+ return _migrate_db_version(
+ session.get_bind(),
+ abs_path,
+ INITIAL_VERSION,
+ )
+
+
+def _db_sync(branch):
+ abs_path = _get_migrate_repo_path(branch)
+ with sql.session_for_write() as session:
+ engine = session.get_bind()
+ _migrate_db_sync(
+ engine=engine,
+ abs_path=abs_path,
+ init_version=INITIAL_VERSION,
+ )
-def validate_upgrade_order(repo_name, target_repo_version=None):
+def _validate_upgrade_order(branch, target_repo_version=None):
"""Validate the state of the migration repositories.
This is run before allowing the db_sync command to execute. Ensure the
@@ -243,7 +171,7 @@ def validate_upgrade_order(repo_name, target_repo_version=None):
the upgrade process. I.e. expand's version is greater or equal to
migrate's, migrate's version is greater or equal to contract's.
- :param repo_name: The name of the repository that the user is trying to
+ :param branch: The name of the repository that the user is trying to
upgrade.
:param target_repo_version: The version to upgrade the repo. Otherwise, the
version will be upgraded to the latest version
@@ -251,33 +179,23 @@ def validate_upgrade_order(repo_name, target_repo_version=None):
"""
# Initialize a dict to have each key assigned a repo with their value being
# the repo that comes before.
- db_sync_order = {DATA_MIGRATION_REPO: EXPAND_REPO,
- CONTRACT_REPO: DATA_MIGRATION_REPO}
+ db_sync_order = {
+ DATA_MIGRATION_BRANCH: EXPAND_BRANCH,
+ CONTRACT_BRANCH: DATA_MIGRATION_BRANCH,
+ }
- if repo_name == LEGACY_REPO:
- return
- # If expand is being run, we validate that Legacy repo is at the maximum
- # version before running the additional schema expansions.
- elif repo_name == EXPAND_REPO:
- abs_path = find_repo(LEGACY_REPO)
- repo = migrate.versioning.repository.Repository(abs_path)
- if int(repo.latest) != get_db_version():
- raise db_exception.DBMigrationError(
- 'Your Legacy repo version is not up to date. Please refer to '
- 'https://docs.openstack.org/keystone/latest/admin/'
- 'identity-upgrading.html '
- 'to see the proper steps for rolling upgrades.')
+ if branch == EXPAND_BRANCH:
return
# find the latest version that the current command will upgrade to if there
# wasn't a version specified for upgrade.
if not target_repo_version:
- abs_path = find_repo(repo_name)
- repo = migrate.versioning.repository.Repository(abs_path)
+ abs_path = _get_migrate_repo_path(branch)
+ repo = _find_migrate_repo(abs_path)
target_repo_version = int(repo.latest)
# get current version of the command that runs before the current command.
- dependency_repo_version = get_db_version(repo=db_sync_order[repo_name])
+ dependency_repo_version = get_db_version(branch=db_sync_order[branch])
if dependency_repo_version < target_repo_version:
raise db_exception.DBMigrationError(
@@ -285,7 +203,7 @@ def validate_upgrade_order(repo_name, target_repo_version=None):
'https://docs.openstack.org/keystone/latest/admin/'
'identity-upgrading.html '
'to see the proper steps for rolling upgrades.' % (
- repo_name, db_sync_order[repo_name]))
+ branch, db_sync_order[branch]))
def expand_schema():
@@ -293,13 +211,9 @@ def expand_schema():
This is run manually by the keystone-manage command before the first
keystone node is migrated to the latest release.
-
"""
- # Make sure all the legacy migrations are run before we run any new
- # expand migrations.
- _sync_common_repo(version=None)
- validate_upgrade_order(EXPAND_REPO)
- _sync_repo(repo_name=EXPAND_REPO)
+ _validate_upgrade_order(EXPAND_BRANCH)
+ _db_sync(branch=EXPAND_BRANCH)
def migrate_data():
@@ -307,10 +221,9 @@ def migrate_data():
This is run manually by the keystone-manage command once the keystone
schema has been expanded for the new release.
-
"""
- validate_upgrade_order(DATA_MIGRATION_REPO)
- _sync_repo(repo_name=DATA_MIGRATION_REPO)
+ _validate_upgrade_order(DATA_MIGRATION_BRANCH)
+ _db_sync(branch=DATA_MIGRATION_BRANCH)
def contract_schema():
@@ -319,7 +232,26 @@ def contract_schema():
This is run manually by the keystone-manage command once the keystone
nodes have been upgraded to the latest release and will remove any old
tables/columns that are no longer required.
+ """
+ _validate_upgrade_order(CONTRACT_BRANCH)
+ _db_sync(branch=CONTRACT_BRANCH)
+
+def offline_sync_database_to_version(version=None):
+ """Perform and off-line sync of the database.
+
+ Migrate the database up to the latest version, doing the equivalent of
+ the cycle of --expand, --migrate and --contract, for when an offline
+ upgrade is being performed.
+
+ If a version is specified then only migrate the database up to that
+ version. Downgrading is not supported. If version is specified, then only
+ the main database migration is carried out - and the expand, migration and
+ contract phases will NOT be run.
"""
- validate_upgrade_order(CONTRACT_REPO)
- _sync_repo(repo_name=CONTRACT_REPO)
+ if version:
+ raise Exception('Specifying a version is no longer supported')
+
+ expand_schema()
+ migrate_data()
+ contract_schema()
diff --git a/keystone/common/utils.py b/keystone/common/utils.py
index 7c3e7ae1a..70d277e52 100644
--- a/keystone/common/utils.py
+++ b/keystone/common/utils.py
@@ -17,6 +17,7 @@
# under the License.
import collections.abc
+import contextlib
import grp
import hashlib
import itertools
@@ -489,3 +490,9 @@ def create_directory(directory, keystone_user_id=None, keystone_group_id=None):
'Unable to change the ownership of key repository without '
'a keystone user ID and keystone group ID both being '
'provided: %s', directory)
+
+
+@contextlib.contextmanager
+def nested_contexts(*contexts):
+ with contextlib.ExitStack() as stack:
+ yield [stack.enter_context(c) for c in contexts]
diff --git a/keystone/conf/ldap.py b/keystone/conf/ldap.py
index 5943ff434..e9b89f9f6 100644
--- a/keystone/conf/ldap.py
+++ b/keystone/conf/ldap.py
@@ -411,11 +411,11 @@ use_pool` is also enabled.
pool_retry_max = cfg.IntOpt(
'pool_retry_max',
default=3,
- min=0,
+ min=1,
help=utils.fmt("""
-The maximum number of times to attempt reconnecting to the LDAP server before
-aborting. A value of zero prevents retries. This option has no effect unless
-`[ldap] use_pool` is also enabled.
+The maximum number of times to attempt connecting to the LDAP server before
+aborting. A value of one makes only one connection attempt.
+This option has no effect unless `[ldap] use_pool` is also enabled.
"""))
pool_retry_delay = cfg.FloatOpt(
diff --git a/keystone/federation/idp.py b/keystone/federation/idp.py
index fd464f5c2..2f1a4fe5a 100644
--- a/keystone/federation/idp.py
+++ b/keystone/federation/idp.py
@@ -366,7 +366,11 @@ class SAMLGenerator(object):
"""
canonicalization_method = xmldsig.CanonicalizationMethod()
- canonicalization_method.algorithm = xmldsig.ALG_EXC_C14N
+ # TODO(stephenfin): Drop when we remove support for pysaml < 7.1.0
+ if hasattr(xmldsig, 'TRANSFORM_C14N'): # >= 7.1.0
+ canonicalization_method.algorithm = xmldsig.TRANSFORM_C14N
+ else: # < 7.1.0
+ canonicalization_method.algorithm = xmldsig.ALG_EXC_C14N
signature_method = xmldsig.SignatureMethod(
algorithm=xmldsig.SIG_RSA_SHA1)
@@ -374,7 +378,11 @@ class SAMLGenerator(object):
envelope_transform = xmldsig.Transform(
algorithm=xmldsig.TRANSFORM_ENVELOPED)
- c14_transform = xmldsig.Transform(algorithm=xmldsig.ALG_EXC_C14N)
+ # TODO(stephenfin): Drop when we remove support for pysaml < 7.1.0
+ if hasattr(xmldsig, 'TRANSFORM_C14N'): # >= 7.1.0
+ c14_transform = xmldsig.Transform(algorithm=xmldsig.TRANSFORM_C14N)
+ else: # < 7.1.0
+ c14_transform = xmldsig.Transform(algorithm=xmldsig.ALG_EXC_C14N)
transforms.transform = [envelope_transform, c14_transform]
digest_method = xmldsig.DigestMethod(algorithm=xmldsig.DIGEST_SHA1)
diff --git a/keystone/identity/backends/ldap/common.py b/keystone/identity/backends/ldap/common.py
index 4af42de29..1033a4efd 100644
--- a/keystone/identity/backends/ldap/common.py
+++ b/keystone/identity/backends/ldap/common.py
@@ -1401,9 +1401,24 @@ class BaseLdap(object):
pass
else:
try:
- obj[k] = v[0]
+ value = v[0]
except IndexError:
- obj[k] = None
+ value = None
+
+ # NOTE(xek): Some LDAP servers return bytes data type
+ # We convert it to string here, so that it is consistent with
+ # the other (SQL) backends.
+ # Bytes data type caused issues in the past, because it could
+ # be cached and then passed into str() method to be used as
+ # LDAP filters, which results in an unexpected b'...' prefix.
+ if isinstance(value, bytes):
+ try:
+ value = value.decode('utf-8')
+ except UnicodeDecodeError:
+ LOG.error("Error decoding value %r (object id %r).",
+ value, res[0])
+ raise
+ obj[k] = value
return obj
diff --git a/keystone/tests/unit/common/sql/test_upgrades.py b/keystone/tests/unit/common/sql/test_upgrades.py
new file mode 100644
index 000000000..c6c4a2e56
--- /dev/null
+++ b/keystone/tests/unit/common/sql/test_upgrades.py
@@ -0,0 +1,252 @@
+# 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 os
+import tempfile
+from unittest import mock
+
+from migrate import exceptions as migrate_exception
+from migrate.versioning import api as migrate_api
+from migrate.versioning import repository as migrate_repository
+from oslo_db import exception as db_exception
+from oslo_db.sqlalchemy import enginefacade
+from oslo_db.sqlalchemy import test_fixtures as db_fixtures
+from oslotest import base as test_base
+import sqlalchemy
+
+from keystone.common.sql import upgrades
+from keystone.common import utils
+
+
+class TestMigrationCommon(
+ db_fixtures.OpportunisticDBTestMixin, test_base.BaseTestCase,
+):
+
+ def setUp(self):
+ super().setUp()
+
+ self.engine = enginefacade.writer.get_engine()
+
+ self.path = tempfile.mkdtemp('test_migration')
+ self.path1 = tempfile.mkdtemp('test_migration')
+ self.return_value = '/home/openstack/migrations'
+ self.return_value1 = '/home/extension/migrations'
+ self.init_version = 1
+ self.test_version = 123
+
+ self.patcher_repo = mock.patch.object(migrate_repository, 'Repository')
+ self.repository = self.patcher_repo.start()
+ self.repository.side_effect = [self.return_value, self.return_value1]
+
+ self.mock_api_db = mock.patch.object(migrate_api, 'db_version')
+ self.mock_api_db_version = self.mock_api_db.start()
+ self.mock_api_db_version.return_value = self.test_version
+
+ def tearDown(self):
+ os.rmdir(self.path)
+ self.mock_api_db.stop()
+ self.patcher_repo.stop()
+ super().tearDown()
+
+ def test_find_migrate_repo_path_not_found(self):
+ self.assertRaises(
+ db_exception.DBMigrationError,
+ upgrades._find_migrate_repo,
+ "/foo/bar/",
+ )
+
+ def test_find_migrate_repo_called_once(self):
+ my_repository = upgrades._find_migrate_repo(self.path)
+ self.repository.assert_called_once_with(self.path)
+ self.assertEqual(self.return_value, my_repository)
+
+ def test_find_migrate_repo_called_few_times(self):
+ repo1 = upgrades._find_migrate_repo(self.path)
+ repo2 = upgrades._find_migrate_repo(self.path1)
+ self.assertNotEqual(repo1, repo2)
+
+ def test_db_version_control(self):
+ with utils.nested_contexts(
+ mock.patch.object(upgrades, '_find_migrate_repo'),
+ mock.patch.object(migrate_api, 'version_control'),
+ ) as (mock_find_repo, mock_version_control):
+ mock_find_repo.return_value = self.return_value
+
+ version = upgrades._migrate_db_version_control(
+ self.engine, self.path, self.test_version)
+
+ self.assertEqual(self.test_version, version)
+ mock_version_control.assert_called_once_with(
+ self.engine, self.return_value, self.test_version)
+
+ @mock.patch.object(upgrades, '_find_migrate_repo')
+ @mock.patch.object(migrate_api, 'version_control')
+ def test_db_version_control_version_less_than_actual_version(
+ self, mock_version_control, mock_find_repo,
+ ):
+ mock_find_repo.return_value = self.return_value
+ mock_version_control.side_effect = \
+ migrate_exception.DatabaseAlreadyControlledError
+ self.assertRaises(
+ db_exception.DBMigrationError,
+ upgrades._migrate_db_version_control, self.engine,
+ self.path, self.test_version - 1)
+
+ @mock.patch.object(upgrades, '_find_migrate_repo')
+ @mock.patch.object(migrate_api, 'version_control')
+ def test_db_version_control_version_greater_than_actual_version(
+ self, mock_version_control, mock_find_repo,
+ ):
+ mock_find_repo.return_value = self.return_value
+ mock_version_control.side_effect = \
+ migrate_exception.InvalidVersionError
+ self.assertRaises(
+ db_exception.DBMigrationError,
+ upgrades._migrate_db_version_control, self.engine,
+ self.path, self.test_version + 1)
+
+ def test_db_version_return(self):
+ ret_val = upgrades._migrate_db_version(
+ self.engine, self.path, self.init_version)
+ self.assertEqual(self.test_version, ret_val)
+
+ def test_db_version_raise_not_controlled_error_first(self):
+ with mock.patch.object(
+ upgrades, '_migrate_db_version_control',
+ ) as mock_ver:
+ self.mock_api_db_version.side_effect = [
+ migrate_exception.DatabaseNotControlledError('oups'),
+ self.test_version]
+
+ ret_val = upgrades._migrate_db_version(
+ self.engine, self.path, self.init_version)
+ self.assertEqual(self.test_version, ret_val)
+ mock_ver.assert_called_once_with(
+ self.engine, self.path, version=self.init_version)
+
+ def test_db_version_raise_not_controlled_error_tables(self):
+ with mock.patch.object(sqlalchemy, 'MetaData') as mock_meta:
+ self.mock_api_db_version.side_effect = \
+ migrate_exception.DatabaseNotControlledError('oups')
+ my_meta = mock.MagicMock()
+ my_meta.tables = {'a': 1, 'b': 2}
+ mock_meta.return_value = my_meta
+
+ self.assertRaises(
+ db_exception.DBMigrationError, upgrades._migrate_db_version,
+ self.engine, self.path, self.init_version)
+
+ @mock.patch.object(migrate_api, 'version_control')
+ def test_db_version_raise_not_controlled_error_no_tables(self, mock_vc):
+ with mock.patch.object(sqlalchemy, 'MetaData') as mock_meta:
+ self.mock_api_db_version.side_effect = (
+ migrate_exception.DatabaseNotControlledError('oups'),
+ self.init_version)
+ my_meta = mock.MagicMock()
+ my_meta.tables = {}
+ mock_meta.return_value = my_meta
+
+ upgrades._migrate_db_version(
+ self.engine, self.path, self.init_version)
+
+ mock_vc.assert_called_once_with(
+ self.engine, self.return_value1, self.init_version)
+
+ @mock.patch.object(migrate_api, 'version_control')
+ def test_db_version_raise_not_controlled_alembic_tables(self, mock_vc):
+ # When there are tables but the alembic control table
+ # (alembic_version) is present, attempt to version the db.
+ # This simulates the case where there is are multiple repos (different
+ # abs_paths) and a different path has been versioned already.
+ with mock.patch.object(sqlalchemy, 'MetaData') as mock_meta:
+ self.mock_api_db_version.side_effect = [
+ migrate_exception.DatabaseNotControlledError('oups'), None]
+ my_meta = mock.MagicMock()
+ my_meta.tables = {'alembic_version': 1, 'b': 2}
+ mock_meta.return_value = my_meta
+
+ upgrades._migrate_db_version(
+ self.engine, self.path, self.init_version)
+
+ mock_vc.assert_called_once_with(
+ self.engine, self.return_value1, self.init_version)
+
+ @mock.patch.object(migrate_api, 'version_control')
+ def test_db_version_raise_not_controlled_migrate_tables(self, mock_vc):
+ # When there are tables but the sqlalchemy-migrate control table
+ # (migrate_version) is present, attempt to version the db.
+ # This simulates the case where there is are multiple repos (different
+ # abs_paths) and a different path has been versioned already.
+ with mock.patch.object(sqlalchemy, 'MetaData') as mock_meta:
+ self.mock_api_db_version.side_effect = [
+ migrate_exception.DatabaseNotControlledError('oups'), None]
+ my_meta = mock.MagicMock()
+ my_meta.tables = {'migrate_version': 1, 'b': 2}
+ mock_meta.return_value = my_meta
+
+ upgrades._migrate_db_version(
+ self.engine, self.path, self.init_version)
+
+ mock_vc.assert_called_once_with(
+ self.engine, self.return_value1, self.init_version)
+
+ def test_db_sync_wrong_version(self):
+ self.assertRaises(
+ db_exception.DBMigrationError,
+ upgrades._migrate_db_sync, self.engine, self.path, 'foo')
+
+ @mock.patch.object(migrate_api, 'upgrade')
+ def test_db_sync_script_not_present(self, upgrade):
+ # For non existent upgrades script file sqlalchemy-migrate will raise
+ # VersionNotFoundError which will be wrapped in DBMigrationError.
+ upgrade.side_effect = migrate_exception.VersionNotFoundError
+ self.assertRaises(
+ db_exception.DBMigrationError,
+ upgrades._migrate_db_sync, self.engine, self.path,
+ self.test_version + 1)
+
+ @mock.patch.object(migrate_api, 'upgrade')
+ def test_db_sync_known_error_raised(self, upgrade):
+ upgrade.side_effect = migrate_exception.KnownError
+ self.assertRaises(
+ db_exception.DBMigrationError,
+ upgrades._migrate_db_sync, self.engine, self.path,
+ self.test_version + 1)
+
+ def test_db_sync_upgrade(self):
+ init_ver = 55
+ with utils.nested_contexts(
+ mock.patch.object(upgrades, '_find_migrate_repo'),
+ mock.patch.object(migrate_api, 'upgrade')
+ ) as (mock_find_repo, mock_upgrade):
+ mock_find_repo.return_value = self.return_value
+ self.mock_api_db_version.return_value = self.test_version - 1
+
+ upgrades._migrate_db_sync(
+ self.engine, self.path, self.test_version, init_ver)
+
+ mock_upgrade.assert_called_once_with(
+ self.engine, self.return_value, self.test_version)
+
+ def test_db_sync_downgrade(self):
+ with utils.nested_contexts(
+ mock.patch.object(upgrades, '_find_migrate_repo'),
+ mock.patch.object(migrate_api, 'downgrade')
+ ) as (mock_find_repo, mock_downgrade):
+ mock_find_repo.return_value = self.return_value
+ self.mock_api_db_version.return_value = self.test_version + 1
+
+ upgrades._migrate_db_sync(
+ self.engine, self.path, self.test_version)
+
+ mock_downgrade.assert_called_once_with(
+ self.engine, self.return_value, self.test_version)
diff --git a/keystone/tests/unit/core.py b/keystone/tests/unit/core.py
index 92adbfb22..2a6c12038 100644
--- a/keystone/tests/unit/core.py
+++ b/keystone/tests/unit/core.py
@@ -11,6 +11,7 @@
# 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 atexit
import base64
import contextlib
@@ -26,7 +27,6 @@ import shutil
import socket
import sys
import uuid
-import warnings
import fixtures
import flask
@@ -38,7 +38,6 @@ from oslo_context import fixture as oslo_ctx_fixture
from oslo_log import fixture as log_fixture
from oslo_log import log
from oslo_utils import timeutils
-from sqlalchemy import exc
import testtools
from testtools import testcase
@@ -680,17 +679,9 @@ class BaseTestCase(testtools.TestCase):
self.useFixture(fixtures.MockPatchObject(sys, 'exit',
side_effect=UnexpectedExit))
self.useFixture(log_fixture.get_logging_handle_error_fixture())
+ self.stdlog = self.useFixture(ksfixtures.StandardLogging())
+ self.useFixture(ksfixtures.WarningsFixture())
- warnings.filterwarnings('error', category=DeprecationWarning,
- module='^keystone\\.')
- warnings.filterwarnings(
- 'ignore', category=DeprecationWarning,
- message=r"Using function/method 'db_version\(\)' is deprecated")
- warnings.simplefilter('error', exc.SAWarning)
- if hasattr(exc, "RemovedIn20Warning"):
- warnings.simplefilter('ignore', exc.RemovedIn20Warning)
-
- self.addCleanup(warnings.resetwarnings)
# Ensure we have an empty threadlocal context at the start of each
# test.
self.assertIsNone(oslo_context.get_current())
diff --git a/keystone/tests/unit/ksfixtures/__init__.py b/keystone/tests/unit/ksfixtures/__init__.py
index 7a92c42cd..a5fedbfc8 100644
--- a/keystone/tests/unit/ksfixtures/__init__.py
+++ b/keystone/tests/unit/ksfixtures/__init__.py
@@ -16,4 +16,6 @@ from keystone.tests.unit.ksfixtures.backendloader import BackendLoader # noqa
from keystone.tests.unit.ksfixtures.cache import Cache # noqa
from keystone.tests.unit.ksfixtures.jws_key_repository import JWSKeyRepository # noqa
from keystone.tests.unit.ksfixtures.key_repository import KeyRepository # noqa
+from keystone.tests.unit.ksfixtures.logging import StandardLogging # noqa
from keystone.tests.unit.ksfixtures.policy import Policy # noqa
+from keystone.tests.unit.ksfixtures.warnings import WarningsFixture # noqa
diff --git a/keystone/tests/unit/ksfixtures/logging.py b/keystone/tests/unit/ksfixtures/logging.py
new file mode 100644
index 000000000..419880deb
--- /dev/null
+++ b/keystone/tests/unit/ksfixtures/logging.py
@@ -0,0 +1,114 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import logging as std_logging
+import os
+
+import fixtures
+
+
+class NullHandler(std_logging.Handler):
+ """Custom default NullHandler to attempt to format the record.
+
+ Used to detect formatting errors in debug level logs without saving the
+ logs.
+ """
+
+ def handle(self, record):
+ self.format(record)
+
+ def emit(self, record):
+ pass
+
+ def createLock(self):
+ self.lock = None
+
+
+class StandardLogging(fixtures.Fixture):
+ """Setup Logging redirection for tests.
+
+ There are a number of things we want to handle with logging in tests:
+
+ * Redirect the logging to somewhere that we can test or dump it later.
+
+ * Ensure that as many DEBUG messages as possible are actually
+ executed, to ensure they are actually syntactically valid (they
+ often have not been).
+
+ * Ensure that we create useful output for tests that doesn't
+ overwhelm the testing system (which means we can't capture the
+ 100 MB of debug logging on every run).
+
+ To do this we create a logger fixture at the root level, which
+ defaults to INFO and create a NullLogger at DEBUG which lets
+ us execute log messages at DEBUG but not keep the output.
+
+ To support local debugging OS_DEBUG=True can be set in the
+ environment, which will print out the full debug logging.
+
+ There are also a set of overrides for particularly verbose
+ modules to be even less than INFO.
+ """
+
+ def setUp(self):
+ super().setUp()
+
+ # set root logger to debug
+ root = std_logging.getLogger()
+ root.setLevel(std_logging.DEBUG)
+
+ # supports collecting debug level for local runs
+ if os.environ.get('OS_DEBUG') in ('True', 'true', '1', 'yes'):
+ level = std_logging.DEBUG
+ else:
+ level = std_logging.INFO
+
+ # Collect logs
+ fs = '%(asctime)s %(levelname)s [%(name)s] %(message)s'
+ self.logger = self.useFixture(
+ fixtures.FakeLogger(format=fs, level=None))
+ # TODO(sdague): why can't we send level through the fake
+ # logger? Tests prove that it breaks, but it's worth getting
+ # to the bottom of.
+ root.handlers[0].setLevel(level)
+
+ if level > std_logging.DEBUG:
+ # Just attempt to format debug level logs, but don't save them
+ handler = NullHandler()
+ self.useFixture(fixtures.LogHandler(handler, nuke_handlers=False))
+ handler.setLevel(std_logging.DEBUG)
+
+ # Don't log every single DB migration step
+ std_logging.getLogger(
+ 'migrate.versioning.api').setLevel(std_logging.WARNING)
+ # Or alembic for model comparisons.
+ std_logging.getLogger('alembic').setLevel(std_logging.WARNING)
+ # Or oslo_db provisioning steps
+ std_logging.getLogger('oslo_db.sqlalchemy').setLevel(
+ std_logging.WARNING)
+
+ # At times we end up calling back into main() functions in
+ # testing. This has the possibility of calling logging.setup
+ # again, which completely unwinds the logging capture we've
+ # created here. Once we've setup the logging the way we want,
+ # disable the ability for the test to change this.
+ def fake_logging_setup(*args):
+ pass
+
+ self.useFixture(
+ fixtures.MonkeyPatch('oslo_log.log.setup', fake_logging_setup))
+
+ def delete_stored_logs(self):
+ # NOTE(gibi): this depends on the internals of the fixtures.FakeLogger.
+ # This could be enhanced once the PR
+ # https://github.com/testing-cabal/fixtures/pull/42 is released
+ self.logger._output.truncate(0)
diff --git a/keystone/tests/unit/ksfixtures/warnings.py b/keystone/tests/unit/ksfixtures/warnings.py
new file mode 100644
index 000000000..9e3a9c4d4
--- /dev/null
+++ b/keystone/tests/unit/ksfixtures/warnings.py
@@ -0,0 +1,62 @@
+# 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 warnings
+
+import fixtures
+from sqlalchemy import exc as sqla_exc
+
+
+class WarningsFixture(fixtures.Fixture):
+ """Filters out warnings during test runs."""
+
+ def setUp(self):
+ super().setUp()
+
+ self._original_warning_filters = warnings.filters[:]
+
+ # NOTE(stephenfin): Make deprecation warnings only happen once.
+ # Otherwise this gets kind of crazy given the way that upstream python
+ # libs use this.
+ warnings.simplefilter('once', DeprecationWarning)
+
+ warnings.filterwarnings(
+ 'error',
+ category=DeprecationWarning,
+ module='^keystone\\.',
+ )
+
+ # TODO(stephenfin): This will be fixed once we drop sqlalchemy-migrate
+ warnings.filterwarnings(
+ 'ignore',
+ category=DeprecationWarning,
+ message=r"Using function/method 'db_version\(\)' is deprecated",
+ )
+
+ # TODO(stephenfin): Remove these when we drop support for
+ # sqlalchemy-migrate
+ warnings.filterwarnings(
+ 'ignore',
+ category=sqla_exc.SADeprecationWarning,
+ module='migrate.versioning',
+ )
+
+ # TODO(stephenfin): We should filter on the specific RemovedIn20Warning
+ # warnings that affect us, so that we can slowly start addressing them
+ warnings.simplefilter('error', sqla_exc.SAWarning)
+ if hasattr(sqla_exc, 'RemovedIn20Warning'):
+ warnings.simplefilter('ignore', sqla_exc.RemovedIn20Warning)
+
+ self.addCleanup(self._reset_warning_filters)
+
+ def _reset_warning_filters(self):
+ warnings.filters[:] = self._original_warning_filters
diff --git a/keystone/tests/unit/test_cli.py b/keystone/tests/unit/test_cli.py
index e2c42ec8a..c94d8c196 100644
--- a/keystone/tests/unit/test_cli.py
+++ b/keystone/tests/unit/test_cli.py
@@ -25,7 +25,6 @@ import fixtures
import freezegun
import http.client
import oslo_config.fixture
-from oslo_db.sqlalchemy import migration
from oslo_log import log
from oslo_serialization import jsonutils
from oslo_upgradecheck import upgradecheck
@@ -805,17 +804,6 @@ class CliDBSyncTestCase(unit.BaseTestCase):
cli.DbSync.main()
self._assert_correct_call(upgrades.contract_schema)
- @mock.patch('keystone.cmd.cli.upgrades.get_db_version')
- def test_db_sync_check_when_database_is_empty(self, mocked_get_db_version):
- e = migration.exception.DBMigrationError("Invalid version")
- mocked_get_db_version.side_effect = e
- checker = cli.DbSync()
-
- log_info = self.useFixture(fixtures.FakeLogger(level=log.INFO))
- status = checker.check_db_sync_status()
- self.assertIn("not currently under version control", log_info.output)
- self.assertEqual(status, 2)
-
class TestMappingPopulate(unit.SQLDriverOverrides, unit.TestCase):
diff --git a/keystone/tests/unit/test_policy.py b/keystone/tests/unit/test_policy.py
index b4dea27b8..d0feec639 100644
--- a/keystone/tests/unit/test_policy.py
+++ b/keystone/tests/unit/test_policy.py
@@ -151,16 +151,14 @@ class PolicyScopeTypesEnforcementTestCase(unit.TestCase):
def test_warning_message_is_logged_if_enforce_scope_is_false(self):
self.config_fixture.config(group='oslo_policy', enforce_scope=False)
expected_msg = (
- 'failed scope check. The token used to make the '
+ 'Policy "foo": "" failed scope check. The token used to make the '
'request was project scoped but the policy requires [\'system\'] '
'scope. This behavior may change in the future where using the '
'intended scope is required'
)
with mock.patch('warnings.warn') as mock_warn:
policy.enforce(self.credentials, self.action, self.target)
- mock_warn.assert_called_once()
- warn_msg = mock_warn.call_args[0][0]
- self.assertIn(expected_msg, warn_msg)
+ mock_warn.assert_called_with(expected_msg)
class PolicyJsonTestCase(unit.TestCase):
diff --git a/keystone/tests/unit/test_sql_banned_operations.py b/keystone/tests/unit/test_sql_banned_operations.py
index 220714075..2a9be1029 100644
--- a/keystone/tests/unit/test_sql_banned_operations.py
+++ b/keystone/tests/unit/test_sql_banned_operations.py
@@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-
import os
import fixtures
@@ -25,10 +24,9 @@ from oslotest import base as test_base
import sqlalchemy
import testtools
-from keystone.common.sql import contract_repo
-from keystone.common.sql import data_migration_repo
-from keystone.common.sql import expand_repo
-from keystone.common.sql import migrate_repo
+from keystone.common.sql.legacy_migrations import contract_repo
+from keystone.common.sql.legacy_migrations import data_migration_repo
+from keystone.common.sql.legacy_migrations import expand_repo
from keystone.common.sql import upgrades
@@ -39,9 +37,8 @@ class DBOperationNotAllowed(Exception):
class BannedDBSchemaOperations(fixtures.Fixture):
"""Ban some operations for migrations."""
- def __init__(self, banned_ops=None,
- migration_repo=migrate_repo.__file__):
- super(BannedDBSchemaOperations, self).__init__()
+ def __init__(self, banned_ops, migration_repo):
+ super().__init__()
self._banned_ops = banned_ops or {}
self._migration_repo = migration_repo
@@ -54,7 +51,7 @@ class BannedDBSchemaOperations(fixtures.Fixture):
resource_op, repo_name))
def setUp(self):
- super(BannedDBSchemaOperations, self).setUp()
+ super().setUp()
explode_lambda = {
'Table.create': lambda *a, **k: self._explode(
'Table.create', self._migration_repo),
@@ -91,7 +88,9 @@ class TestBannedDBSchemaOperations(testtools.TestCase):
"""Test column operations raise DBOperationNotAllowed."""
column = sqlalchemy.Column()
with BannedDBSchemaOperations(
- banned_ops={'Column': ['create', 'alter', 'drop']}):
+ banned_ops={'Column': ['create', 'alter', 'drop']},
+ migration_repo=expand_repo.__file__,
+ ):
self.assertRaises(DBOperationNotAllowed, column.drop)
self.assertRaises(DBOperationNotAllowed, column.alter)
self.assertRaises(DBOperationNotAllowed, column.create)
@@ -100,8 +99,10 @@ class TestBannedDBSchemaOperations(testtools.TestCase):
"""Test table operations raise DBOperationNotAllowed."""
table = sqlalchemy.Table()
with BannedDBSchemaOperations(
- banned_ops={'Table': ['create', 'alter', 'drop',
- 'insert', 'update', 'delete']}):
+ banned_ops={'Table': ['create', 'alter', 'drop',
+ 'insert', 'update', 'delete']},
+ migration_repo=expand_repo.__file__,
+ ):
self.assertRaises(DBOperationNotAllowed, table.drop)
self.assertRaises(DBOperationNotAllowed, table.alter)
self.assertRaises(DBOperationNotAllowed, table.create)
@@ -113,35 +114,19 @@ class TestBannedDBSchemaOperations(testtools.TestCase):
class KeystoneMigrationsCheckers(test_migrations.WalkVersionsMixin):
"""Walk over and test all sqlalchemy-migrate migrations."""
- # NOTE(xek): We start requiring things be additive in Newton, so
- # ignore all migrations before the first version in Newton.
- migrate_file = migrate_repo.__file__
- first_version = 101
- # NOTE(henry-nash): We don't ban data modification in the legacy repo,
- # since there are already migrations that do this for Newton (and these
- # do not cause us issues, or are already worked around).
- banned_ops = {'Table': ['alter', 'drop'],
- 'Column': ['alter', 'drop']}
+ migrate_file = None
+ first_version = 1
+ # A mapping of entity (Table, Column, ...) to operation
+ banned_ops = {}
exceptions = [
# NOTE(xek): Reviewers: DO NOT ALLOW THINGS TO BE ADDED HERE UNLESS
# JUSTIFICATION CAN BE PROVIDED AS TO WHY THIS WILL NOT CAUSE
# PROBLEMS FOR ROLLING UPGRADES.
-
- # Migration 102 drops the domain table in the Newton release. All
- # code that referenced the domain table was removed in the Mitaka
- # release, hence this migration will not cause problems when
- # running a mixture of Mitaka and Newton versions of keystone.
- 102,
-
- # Migration 106 simply allows the password column to be nullable.
- # This change would not impact a rolling upgrade.
- 106
]
@property
def INIT_VERSION(self):
- return upgrades.get_init_version(
- abs_path=os.path.abspath(os.path.dirname(self.migrate_file)))
+ return upgrades.INITIAL_VERSION
@property
def REPOSITORY(self):
@@ -190,8 +175,7 @@ class KeystoneMigrationsCheckers(test_migrations.WalkVersionsMixin):
else:
banned_ops = None
with BannedDBSchemaOperations(banned_ops, self.migrate_file):
- super(KeystoneMigrationsCheckers,
- self).migrate_up(version, with_data)
+ super().migrate_up(version, with_data)
snake_walk = False
downgrade = False
@@ -200,43 +184,7 @@ class KeystoneMigrationsCheckers(test_migrations.WalkVersionsMixin):
self.walk_versions(self.snake_walk, self.downgrade)
-class TestKeystoneMigrationsMySQL(
- KeystoneMigrationsCheckers,
- db_fixtures.OpportunisticDBTestMixin,
- test_base.BaseTestCase):
- FIXTURE = db_fixtures.MySQLOpportunisticFixture
-
- def setUp(self):
- super(TestKeystoneMigrationsMySQL, self).setUp()
- self.engine = enginefacade.writer.get_engine()
- self.sessionmaker = enginefacade.writer.get_sessionmaker()
-
-
-class TestKeystoneMigrationsPostgreSQL(
- KeystoneMigrationsCheckers,
- db_fixtures.OpportunisticDBTestMixin,
- test_base.BaseTestCase):
- FIXTURE = db_fixtures.PostgresqlOpportunisticFixture
-
- def setUp(self):
- super(TestKeystoneMigrationsPostgreSQL, self).setUp()
- self.engine = enginefacade.writer.get_engine()
- self.sessionmaker = enginefacade.writer.get_sessionmaker()
-
-
-class TestKeystoneMigrationsSQLite(
- KeystoneMigrationsCheckers,
- db_fixtures.OpportunisticDBTestMixin,
- test_base.BaseTestCase):
-
- def setUp(self):
- super(TestKeystoneMigrationsSQLite, self).setUp()
- self.engine = enginefacade.writer.get_engine()
- self.sessionmaker = enginefacade.writer.get_sessionmaker()
-
-
-class TestKeystoneExpandSchemaMigrations(
- KeystoneMigrationsCheckers):
+class TestKeystoneExpandSchemaMigrations(KeystoneMigrationsCheckers):
migrate_file = expand_repo.__file__
first_version = 1
@@ -285,7 +233,6 @@ class TestKeystoneExpandSchemaMigrationsMySQL(
super(TestKeystoneExpandSchemaMigrationsMySQL, self).setUp()
self.engine = enginefacade.writer.get_engine()
self.sessionmaker = enginefacade.writer.get_sessionmaker()
- self.migrate_fully(migrate_repo.__file__)
class TestKeystoneExpandSchemaMigrationsPostgreSQL(
@@ -298,7 +245,6 @@ class TestKeystoneExpandSchemaMigrationsPostgreSQL(
super(TestKeystoneExpandSchemaMigrationsPostgreSQL, self).setUp()
self.engine = enginefacade.writer.get_engine()
self.sessionmaker = enginefacade.writer.get_sessionmaker()
- self.migrate_fully(migrate_repo.__file__)
class TestKeystoneDataMigrations(
@@ -326,7 +272,6 @@ class TestKeystoneDataMigrations(
def setUp(self):
super(TestKeystoneDataMigrations, self).setUp()
- self.migrate_fully(migrate_repo.__file__)
self.migrate_fully(expand_repo.__file__)
@@ -387,7 +332,6 @@ class TestKeystoneContractSchemaMigrations(
def setUp(self):
super(TestKeystoneContractSchemaMigrations, self).setUp()
- self.migrate_fully(migrate_repo.__file__)
self.migrate_fully(expand_repo.__file__)
self.migrate_fully(data_migration_repo.__file__)
diff --git a/keystone/tests/unit/test_sql_upgrade.py b/keystone/tests/unit/test_sql_upgrade.py
index 8d22ace54..78f644977 100644
--- a/keystone/tests/unit/test_sql_upgrade.py
+++ b/keystone/tests/unit/test_sql_upgrade.py
@@ -11,6 +11,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
+
"""
Test for SQL migration extensions.
@@ -25,12 +26,12 @@ To run these tests against a live database:
3. Run the tests using::
- tox -e py27 -- keystone.tests.unit.test_sql_upgrade
+ tox -e py39 -- keystone.tests.unit.test_sql_upgrade
For further information, see `oslo.db documentation
<https://docs.openstack.org/oslo.db/latest/contributor/index.html#how-to-run-unit-tests>`_.
-WARNING::
+.. warning::
Your database will be wiped.
@@ -38,35 +39,25 @@ WARNING::
all data will be lost.
"""
-import datetime
import glob
-import json
import os
-from unittest import mock
-import uuid
import fixtures
-import migrate
-from migrate.versioning import repository
+from migrate.versioning import api as migrate_api
from migrate.versioning import script
from oslo_db import exception as db_exception
from oslo_db.sqlalchemy import enginefacade
from oslo_db.sqlalchemy import test_fixtures as db_fixtures
+from oslo_log import fixture as log_fixture
from oslo_log import log
-from oslo_serialization import jsonutils
from oslotest import base as test_base
-import pytz
import sqlalchemy.exc
-from sqlalchemy import inspect
-from testtools import matchers
from keystone.cmd import cli
from keystone.common import sql
from keystone.common.sql import upgrades
from keystone.credential.providers import fernet as credential_fernet
-from keystone.resource.backends import base as resource_base
from keystone.tests import unit
-from keystone.tests.unit import default_fixtures
from keystone.tests.unit import ksfixtures
from keystone.tests.unit.ksfixtures import database
@@ -75,11 +66,12 @@ from keystone.tests.unit.ksfixtures import database
# is done to mirror the expected structure of the DB in the format of
# { <DB_TABLE_NAME>: [<COLUMN>, <COLUMN>, ...], ... }
INITIAL_TABLE_STRUCTURE = {
- 'credential': [
- 'id', 'user_id', 'project_id', 'blob', 'type', 'extra',
+ 'config_register': [
+ 'type', 'domain_id',
],
- 'domain': [
- 'id', 'name', 'enabled', 'extra',
+ 'credential': [
+ 'id', 'user_id', 'project_id', 'type', 'extra', 'key_hash',
+ 'encrypted_blob',
],
'endpoint': [
'id', 'legacy_endpoint_id', 'interface', 'region_id', 'service_id',
@@ -93,10 +85,19 @@ INITIAL_TABLE_STRUCTURE = {
],
'project': [
'id', 'name', 'extra', 'description', 'enabled', 'domain_id',
- 'parent_id',
+ 'parent_id', 'is_domain',
+ ],
+ 'project_option': [
+ 'project_id', 'option_id', 'option_value',
+ ],
+ 'project_tag': [
+ 'project_id', 'name',
],
'role': [
- 'id', 'name', 'extra',
+ 'id', 'name', 'extra', 'domain_id', 'description',
+ ],
+ 'role_option': [
+ 'role_id', 'option_id', 'option_value',
],
'service': [
'id', 'type', 'extra', 'enabled',
@@ -107,13 +108,17 @@ INITIAL_TABLE_STRUCTURE = {
'trust': [
'id', 'trustor_user_id', 'trustee_user_id', 'project_id',
'impersonation', 'deleted_at', 'expires_at', 'remaining_uses', 'extra',
+ 'expires_at_int', 'redelegated_trust_id', 'redelegation_count',
],
'trust_role': [
'trust_id', 'role_id',
],
'user': [
- 'id', 'name', 'extra', 'password', 'enabled', 'domain_id',
- 'default_project_id',
+ 'id', 'extra', 'enabled', 'default_project_id', 'created_at',
+ 'last_active_at', 'domain_id',
+ ],
+ 'user_option': [
+ 'user_id', 'option_id', 'option_value',
],
'user_group_membership': [
'user_id', 'group_id',
@@ -133,77 +138,152 @@ INITIAL_TABLE_STRUCTURE = {
'sensitive_config': [
'domain_id', 'group', 'option', 'value',
],
+ 'policy_association': [
+ 'id', 'policy_id', 'endpoint_id', 'service_id', 'region_id',
+ ],
+ 'identity_provider': [
+ 'id', 'enabled', 'description', 'domain_id', 'authorization_ttl',
+ ],
+ 'federation_protocol': [
+ 'id', 'idp_id', 'mapping_id', 'remote_id_attribute',
+ ],
+ 'mapping': [
+ 'id', 'rules',
+ ],
+ 'service_provider': [
+ 'auth_url', 'id', 'enabled', 'description', 'sp_url',
+ 'relay_state_prefix',
+ ],
+ 'idp_remote_ids': [
+ 'idp_id', 'remote_id',
+ ],
+ 'consumer': [
+ 'id', 'description', 'secret', 'extra',
+ ],
+ 'request_token': [
+ 'id', 'request_secret', 'verifier', 'authorizing_user_id',
+ 'requested_project_id', 'role_ids', 'consumer_id', 'expires_at',
+ ],
+ 'access_token': [
+ 'id', 'access_secret', 'authorizing_user_id', 'project_id', 'role_ids',
+ 'consumer_id', 'expires_at',
+ ],
+ 'revocation_event': [
+ 'id', 'domain_id', 'project_id', 'user_id', 'role_id', 'trust_id',
+ 'consumer_id', 'access_token_id', 'issued_before', 'expires_at',
+ 'revoked_at', 'audit_id', 'audit_chain_id',
+ ],
+ 'project_endpoint': [
+ 'endpoint_id', 'project_id'
+ ],
+ 'endpoint_group': [
+ 'id', 'name', 'description', 'filters',
+ ],
+ 'project_endpoint_group': [
+ 'endpoint_group_id', 'project_id',
+ ],
+ 'implied_role': [
+ 'prior_role_id', 'implied_role_id',
+ ],
+ 'local_user': [
+ 'id', 'user_id', 'domain_id', 'name', 'failed_auth_count',
+ 'failed_auth_at',
+ ],
+ 'password': [
+ 'id', 'local_user_id', 'created_at', 'expires_at',
+ 'self_service', 'password_hash', 'created_at_int', 'expires_at_int',
+ ],
+ 'federated_user': [
+ 'id', 'user_id', 'idp_id', 'protocol_id', 'unique_id', 'display_name',
+ ],
+ 'nonlocal_user': [
+ 'domain_id', 'name', 'user_id',
+ ],
+ 'system_assignment': [
+ 'type', 'actor_id', 'target_id', 'role_id', 'inherited',
+ ],
+ 'registered_limit': [
+ 'internal_id', 'id', 'service_id', 'region_id', 'resource_name',
+ 'default_limit', 'description',
+ ],
+ 'limit': [
+ 'internal_id', 'id', 'project_id', 'resource_limit', 'description',
+ 'registered_limit_id', 'domain_id',
+ ],
+ 'application_credential': [
+ 'internal_id', 'id', 'name', 'secret_hash', 'description', 'user_id',
+ 'project_id', 'expires_at', 'system', 'unrestricted',
+ ],
+ 'application_credential_role': [
+ 'application_credential_id', 'role_id',
+ ],
+ 'access_rule': [
+ 'id', 'service', 'path', 'method', 'external_id', 'user_id',
+ ],
+ 'application_credential_access_rule': [
+ 'application_credential_id', 'access_rule_id',
+ ],
+ 'expiring_user_group_membership': [
+ 'user_id', 'group_id', 'idp_id', 'last_verified',
+ ],
}
-LEGACY_REPO = 'migrate_repo'
-EXPAND_REPO = 'expand_repo'
-DATA_MIGRATION_REPO = 'data_migration_repo'
-CONTRACT_REPO = 'contract_repo'
-
-
-# Test upgrades.get_init_version separately to ensure it works before
-# using in the SqlUpgrade tests.
-class SqlUpgradeGetInitVersionTests(unit.TestCase):
- @mock.patch.object(repository, 'Repository')
- def test_get_init_version_no_path(self, repo):
- migrate_versions = mock.MagicMock()
- # make a version list starting with zero. `get_init_version` will
- # return None for this value.
- migrate_versions.versions.versions = list(range(0, 5))
- repo.return_value = migrate_versions
-
- # os.path.isdir() is called by `find_repo()`. Mock it to avoid
- # an exception.
- with mock.patch('os.path.isdir', return_value=True):
- # since 0 is the smallest version expect None
- version = upgrades.get_init_version()
- self.assertIsNone(version)
-
- # check that the default path was used as the first argument to the
- # first invocation of repo. Cannot match the full path because it is
- # based on where the test is run.
- param = repo.call_args_list[0][0][0]
- self.assertTrue(param.endswith('/sql/' + LEGACY_REPO))
-
- @mock.patch.object(repository, 'Repository')
- def test_get_init_version_with_path_initial_version_0(self, repo):
- migrate_versions = mock.MagicMock()
- # make a version list starting with zero. `get_init_version` will
- # return None for this value.
- migrate_versions.versions.versions = list(range(0, 5))
- repo.return_value = migrate_versions
-
- # os.path.isdir() is called by `find_repo()`. Mock it to avoid
- # an exception.
- with mock.patch('os.path.isdir', return_value=True):
- path = '/keystone/' + LEGACY_REPO + '/'
-
- # since 0 is the smallest version expect None
- version = upgrades.get_init_version(abs_path=path)
- self.assertIsNone(version)
-
- @mock.patch.object(repository, 'Repository')
- def test_get_init_version_with_path(self, repo):
- initial_version = 10
-
- migrate_versions = mock.MagicMock()
- migrate_versions.versions.versions = list(range(initial_version + 1,
- initial_version + 5))
- repo.return_value = migrate_versions
-
- # os.path.isdir() is called by `find_repo()`. Mock it to avoid
- # an exception.
- with mock.patch('os.path.isdir', return_value=True):
- path = '/keystone/' + LEGACY_REPO + '/'
-
- version = upgrades.get_init_version(abs_path=path)
- self.assertEqual(initial_version, version)
-
-
-class SqlMigrateBase(db_fixtures.OpportunisticDBTestMixin,
- test_base.BaseTestCase):
+
+class Repository:
+
+ def __init__(self, engine, repo_name):
+ self.repo_name = repo_name
+
+ self.repo_path = upgrades._get_migrate_repo_path(self.repo_name)
+ self.min_version = upgrades.INITIAL_VERSION
+ self.schema_ = migrate_api.ControlledSchema.create(
+ engine, self.repo_path, self.min_version,
+ )
+ self.max_version = self.schema_.repository.version().version
+
+ def upgrade(self, version=None, current_schema=None):
+ version = version or self.max_version
+ err = ''
+ upgrade = True
+ version = migrate_api._migrate_version(
+ self.schema_, version, upgrade, err,
+ )
+ upgrades._validate_upgrade_order(
+ self.repo_name, target_repo_version=version,
+ )
+ if not current_schema:
+ current_schema = self.schema_
+ changeset = current_schema.changeset(version)
+ for ver, change in changeset:
+ self.schema_.runchange(ver, change, changeset.step)
+
+ if self.schema_.version != version:
+ raise Exception(
+ 'Actual version (%s) of %s does not equal expected '
+ 'version (%s)' % (
+ self.schema_.version, self.repo_name, version,
+ ),
+ )
+
+ @property
+ def version(self):
+ with sql.session_for_read() as session:
+ return upgrades._migrate_db_version(
+ session.get_bind(), self.repo_path, self.min_version,
+ )
+
+
+class MigrateBase(
+ db_fixtures.OpportunisticDBTestMixin,
+ test_base.BaseTestCase,
+):
def setUp(self):
- super(SqlMigrateBase, self).setUp()
+ super().setUp()
+
+ self.useFixture(log_fixture.get_logging_handle_error_fixture())
+ self.stdlog = self.useFixture(ksfixtures.StandardLogging())
+ self.useFixture(ksfixtures.WarningsFixture())
+
self.engine = enginefacade.writer.get_engine()
self.sessionmaker = enginefacade.writer.get_sessionmaker()
@@ -225,27 +305,28 @@ class SqlMigrateBase(db_fixtures.OpportunisticDBTestMixin,
self.addCleanup(sql.cleanup)
self.repos = {
- LEGACY_REPO: upgrades.Repository(self.engine, LEGACY_REPO),
- EXPAND_REPO: upgrades.Repository(self.engine, EXPAND_REPO),
- DATA_MIGRATION_REPO: upgrades.Repository(
- self.engine, DATA_MIGRATION_REPO),
- CONTRACT_REPO: upgrades.Repository(self.engine, CONTRACT_REPO)}
-
- def upgrade(self, *args, **kwargs):
- """Upgrade the legacy migration repository."""
- self.repos[LEGACY_REPO].upgrade(*args, **kwargs)
+ upgrades.EXPAND_BRANCH: Repository(
+ self.engine, upgrades.EXPAND_BRANCH,
+ ),
+ upgrades.DATA_MIGRATION_BRANCH: Repository(
+ self.engine, upgrades.DATA_MIGRATION_BRANCH,
+ ),
+ upgrades.CONTRACT_BRANCH: Repository(
+ self.engine, upgrades.CONTRACT_BRANCH,
+ ),
+ }
def expand(self, *args, **kwargs):
"""Expand database schema."""
- self.repos[EXPAND_REPO].upgrade(*args, **kwargs)
+ self.repos[upgrades.EXPAND_BRANCH].upgrade(*args, **kwargs)
def migrate(self, *args, **kwargs):
"""Migrate data."""
- self.repos[DATA_MIGRATION_REPO].upgrade(*args, **kwargs)
+ self.repos[upgrades.DATA_MIGRATION_BRANCH].upgrade(*args, **kwargs)
def contract(self, *args, **kwargs):
"""Contract database schema."""
- self.repos[CONTRACT_REPO].upgrade(*args, **kwargs)
+ self.repos[upgrades.CONTRACT_BRANCH].upgrade(*args, **kwargs)
@property
def metadata(self):
@@ -253,17 +334,9 @@ class SqlMigrateBase(db_fixtures.OpportunisticDBTestMixin,
return sqlalchemy.MetaData(self.engine)
def load_table(self, name):
- table = sqlalchemy.Table(name,
- self.metadata,
- autoload=True)
+ table = sqlalchemy.Table(name, self.metadata, autoload=True)
return table
- def assertTableExists(self, table_name):
- try:
- self.load_table(table_name)
- except sqlalchemy.exc.NoSuchTableError:
- raise AssertionError('Table "%s" does not exist' % table_name)
-
def assertTableDoesNotExist(self, table_name):
"""Assert that a given table exists cannot be selected by name."""
# Switch to a different metadata otherwise you might still
@@ -275,22 +348,6 @@ class SqlMigrateBase(db_fixtures.OpportunisticDBTestMixin,
else:
raise AssertionError('Table "%s" already exists' % table_name)
- def calc_table_row_count(self, table_name):
- """Return the number of rows in the table."""
- t = sqlalchemy.Table(table_name, self.metadata, autoload=True)
- session = self.sessionmaker()
- row_count = session.query(
- sqlalchemy.func.count('*')).select_from(t).scalar()
- return row_count
-
- def assertTableCountsMatch(self, table1_name, table2_name):
- table1_count = self.calc_table_row_count(table1_name)
- table2_count = self.calc_table_row_count(table2_name)
- if table1_count != table2_count:
- raise AssertionError('Table counts do not match: {0} ({1}), {2} '
- '({3})'.format(table1_name, table1_count,
- table2_name, table2_count))
-
def assertTableColumns(self, table_name, expected_cols):
"""Assert that the table contains the expected set of columns."""
table = self.load_table(table_name)
@@ -300,1276 +357,72 @@ class SqlMigrateBase(db_fixtures.OpportunisticDBTestMixin,
self.assertCountEqual(expected_cols, actual_cols,
'%s table' % table_name)
- def insert_dict(self, session, table_name, d, table=None):
- """Naively inserts key-value pairs into a table, given a dictionary."""
- if table is None:
- this_table = sqlalchemy.Table(table_name, self.metadata,
- autoload=True)
- else:
- this_table = table
- insert = this_table.insert().values(**d)
- session.execute(insert)
-
- def does_pk_exist(self, table, pk_column):
- """Check whether a column is primary key on a table."""
- inspector = inspect(self.engine)
- pk_columns = inspector.get_pk_constraint(table)['constrained_columns']
-
- return pk_column in pk_columns
-
- def does_fk_exist(self, table, fk_column):
- inspector = inspect(self.engine)
- for fk in inspector.get_foreign_keys(table):
- if fk_column in fk['constrained_columns']:
- return True
- return False
-
- def does_constraint_exist(self, table_name, constraint_name):
- table = sqlalchemy.Table(table_name, self.metadata, autoload=True)
- return constraint_name in [con.name for con in table.constraints]
-
- def does_index_exist(self, table_name, index_name):
- table = sqlalchemy.Table(table_name, self.metadata, autoload=True)
- return index_name in [idx.name for idx in table.indexes]
-
- def does_unique_constraint_exist(self, table_name, column_names):
- inspector = inspect(self.engine)
- constraints = inspector.get_unique_constraints(table_name)
- for c in constraints:
- if (len(c['column_names']) == 1 and
- column_names in c['column_names']):
- return True
- if (len(c['column_names'])) > 1 and isinstance(column_names, list):
- return set(c['column_names']) == set(column_names)
- return False
-
-
-class SqlLegacyRepoUpgradeTests(SqlMigrateBase):
- def test_blank_db_to_start(self):
- self.assertTableDoesNotExist('user')
+
+class ExpandSchemaUpgradeTests(MigrateBase):
def test_start_version_db_init_version(self):
self.assertEqual(
- self.repos[LEGACY_REPO].min_version,
- self.repos[LEGACY_REPO].version,
- 'DB is not at version %s' % (
- self.repos[LEGACY_REPO].min_version)
- )
+ self.repos[upgrades.EXPAND_BRANCH].min_version,
+ self.repos[upgrades.EXPAND_BRANCH].version)
+
+ def test_blank_db_to_start(self):
+ self.assertTableDoesNotExist('user')
def test_upgrade_add_initial_tables(self):
- self.upgrade(self.repos[LEGACY_REPO].min_version + 1)
+ self.expand(upgrades.INITIAL_VERSION + 1)
self.check_initial_table_structure()
def check_initial_table_structure(self):
for table in INITIAL_TABLE_STRUCTURE:
self.assertTableColumns(table, INITIAL_TABLE_STRUCTURE[table])
- def test_kilo_squash(self):
- self.upgrade(67)
-
- # In 053 the size of ID and parent region ID columns were changed
- table = sqlalchemy.Table('region', self.metadata, autoload=True)
- self.assertEqual(255, table.c.id.type.length)
- self.assertEqual(255, table.c.parent_region_id.type.length)
- table = sqlalchemy.Table('endpoint', self.metadata, autoload=True)
- self.assertEqual(255, table.c.region_id.type.length)
-
- # In 054 an index was created for the actor_id of the assignment table
- table = sqlalchemy.Table('assignment', self.metadata, autoload=True)
- index_data = [(idx.name, list(idx.columns.keys()))
- for idx in table.indexes]
- self.assertIn(('ix_actor_id', ['actor_id']), index_data)
-
- # In 055 indexes were created for user and trust IDs in the token table
- table = sqlalchemy.Table('token', self.metadata, autoload=True)
- index_data = [(idx.name, list(idx.columns.keys()))
- for idx in table.indexes]
- self.assertIn(('ix_token_user_id', ['user_id']), index_data)
- self.assertIn(('ix_token_trust_id', ['trust_id']), index_data)
-
- # In 062 the role ID foreign key was removed from the assignment table
- if self.engine.name == "mysql":
- self.assertFalse(self.does_fk_exist('assignment', 'role_id'))
-
- # In 064 the domain ID FK was removed from the group and user tables
- if self.engine.name != 'sqlite':
- # sqlite does not support FK deletions (or enforcement)
- self.assertFalse(self.does_fk_exist('group', 'domain_id'))
- self.assertFalse(self.does_fk_exist('user', 'domain_id'))
-
- # In 067 the role ID index was removed from the assignment table
- if self.engine.name == "mysql":
- self.assertFalse(self.does_index_exist('assignment',
- 'assignment_role_id_fkey'))
-
- def test_insert_assignment_inherited_pk(self):
- ASSIGNMENT_TABLE_NAME = 'assignment'
- INHERITED_COLUMN_NAME = 'inherited'
- ROLE_TABLE_NAME = 'role'
-
- self.upgrade(72)
-
- # Check that the 'inherited' column is not part of the PK
- self.assertFalse(self.does_pk_exist(ASSIGNMENT_TABLE_NAME,
- INHERITED_COLUMN_NAME))
-
- session = self.sessionmaker()
-
- role = {'id': uuid.uuid4().hex,
- 'name': uuid.uuid4().hex}
- self.insert_dict(session, ROLE_TABLE_NAME, role)
-
- # Create both inherited and noninherited role assignments
- inherited = {'type': 'UserProject',
- 'actor_id': uuid.uuid4().hex,
- 'target_id': uuid.uuid4().hex,
- 'role_id': role['id'],
- 'inherited': True}
-
- noninherited = inherited.copy()
- noninherited['inherited'] = False
-
- # Create another inherited role assignment as a spoiler
- spoiler = inherited.copy()
- spoiler['actor_id'] = uuid.uuid4().hex
-
- self.insert_dict(session, ASSIGNMENT_TABLE_NAME, inherited)
- self.insert_dict(session, ASSIGNMENT_TABLE_NAME, spoiler)
-
- # Since 'inherited' is not part of the PK, we can't insert noninherited
- self.assertRaises(db_exception.DBDuplicateEntry,
- self.insert_dict,
- session,
- ASSIGNMENT_TABLE_NAME,
- noninherited)
-
- session.close()
-
- self.upgrade(73)
-
- session = self.sessionmaker()
-
- # Check that the 'inherited' column is now part of the PK
- self.assertTrue(self.does_pk_exist(ASSIGNMENT_TABLE_NAME,
- INHERITED_COLUMN_NAME))
-
- # The noninherited role assignment can now be inserted
- self.insert_dict(session, ASSIGNMENT_TABLE_NAME, noninherited)
-
- assignment_table = sqlalchemy.Table(ASSIGNMENT_TABLE_NAME,
- self.metadata,
- autoload=True)
-
- assignments = session.query(assignment_table).all()
- for assignment in (inherited, spoiler, noninherited):
- self.assertIn((assignment['type'], assignment['actor_id'],
- assignment['target_id'], assignment['role_id'],
- assignment['inherited']),
- assignments)
-
- def test_endpoint_policy_upgrade(self):
- self.assertTableDoesNotExist('policy_association')
- self.upgrade(81)
- self.assertTableColumns('policy_association',
- ['id', 'policy_id', 'endpoint_id',
- 'service_id', 'region_id'])
-
- @mock.patch.object(upgrades, 'get_db_version', return_value=1)
- def test_endpoint_policy_already_migrated(self, mock_ep):
-
- # By setting the return value to 1, the migration has already been
- # run, and there's no need to create the table again
-
- self.upgrade(81)
-
- mock_ep.assert_called_once_with(extension='endpoint_policy',
- engine=mock.ANY)
-
- # It won't exist because we are mocking it, but we can verify
- # that 081 did not create the table
- self.assertTableDoesNotExist('policy_association')
-
- def test_create_federation_tables(self):
- self.identity_provider = 'identity_provider'
- self.federation_protocol = 'federation_protocol'
- self.service_provider = 'service_provider'
- self.mapping = 'mapping'
- self.remote_ids = 'idp_remote_ids'
-
- self.assertTableDoesNotExist(self.identity_provider)
- self.assertTableDoesNotExist(self.federation_protocol)
- self.assertTableDoesNotExist(self.service_provider)
- self.assertTableDoesNotExist(self.mapping)
- self.assertTableDoesNotExist(self.remote_ids)
-
- self.upgrade(82)
- self.assertTableColumns(self.identity_provider,
- ['id', 'description', 'enabled'])
-
- self.assertTableColumns(self.federation_protocol,
- ['id', 'idp_id', 'mapping_id'])
-
- self.assertTableColumns(self.mapping,
- ['id', 'rules'])
-
- self.assertTableColumns(self.service_provider,
- ['id', 'description', 'enabled', 'auth_url',
- 'relay_state_prefix', 'sp_url'])
-
- self.assertTableColumns(self.remote_ids, ['idp_id', 'remote_id'])
-
- federation_protocol = sqlalchemy.Table(self.federation_protocol,
- self.metadata,
- autoload=True)
- self.assertFalse(federation_protocol.c.mapping_id.nullable)
-
- sp_table = sqlalchemy.Table(self.service_provider,
- self.metadata,
- autoload=True)
- self.assertFalse(sp_table.c.auth_url.nullable)
- self.assertFalse(sp_table.c.sp_url.nullable)
-
- @mock.patch.object(upgrades, 'get_db_version', return_value=8)
- def test_federation_already_migrated(self, mock_federation):
-
- # By setting the return value to 8, the migration has already been
- # run, and there's no need to create the table again.
- self.upgrade(82)
-
- mock_federation.assert_any_call(extension='federation',
- engine=mock.ANY)
-
- # It won't exist because we are mocking it, but we can verify
- # that 082 did not create the table.
- self.assertTableDoesNotExist('identity_provider')
- self.assertTableDoesNotExist('federation_protocol')
- self.assertTableDoesNotExist('mapping')
- self.assertTableDoesNotExist('service_provider')
- self.assertTableDoesNotExist('idp_remote_ids')
-
- def test_create_oauth_tables(self):
- consumer = 'consumer'
- request_token = 'request_token'
- access_token = 'access_token'
- self.assertTableDoesNotExist(consumer)
- self.assertTableDoesNotExist(request_token)
- self.assertTableDoesNotExist(access_token)
- self.upgrade(83)
- self.assertTableColumns(consumer,
- ['id',
- 'description',
- 'secret',
- 'extra'])
- self.assertTableColumns(request_token,
- ['id',
- 'request_secret',
- 'verifier',
- 'authorizing_user_id',
- 'requested_project_id',
- 'role_ids',
- 'consumer_id',
- 'expires_at'])
- self.assertTableColumns(access_token,
- ['id',
- 'access_secret',
- 'authorizing_user_id',
- 'project_id',
- 'role_ids',
- 'consumer_id',
- 'expires_at'])
-
- @mock.patch.object(upgrades, 'get_db_version', return_value=5)
- def test_oauth1_already_migrated(self, mock_oauth1):
-
- # By setting the return value to 5, the migration has already been
- # run, and there's no need to create the table again.
- self.upgrade(83)
-
- mock_oauth1.assert_any_call(extension='oauth1', engine=mock.ANY)
-
- # It won't exist because we are mocking it, but we can verify
- # that 083 did not create the table.
- self.assertTableDoesNotExist('consumer')
- self.assertTableDoesNotExist('request_token')
- self.assertTableDoesNotExist('access_token')
-
- def test_create_revoke_table(self):
- self.assertTableDoesNotExist('revocation_event')
- self.upgrade(84)
- self.assertTableColumns('revocation_event',
- ['id', 'domain_id', 'project_id', 'user_id',
- 'role_id', 'trust_id', 'consumer_id',
- 'access_token_id', 'issued_before',
- 'expires_at', 'revoked_at',
- 'audit_chain_id', 'audit_id'])
-
- @mock.patch.object(upgrades, 'get_db_version', return_value=2)
- def test_revoke_already_migrated(self, mock_revoke):
-
- # By setting the return value to 2, the migration has already been
- # run, and there's no need to create the table again.
- self.upgrade(84)
-
- mock_revoke.assert_any_call(extension='revoke', engine=mock.ANY)
-
- # It won't exist because we are mocking it, but we can verify
- # that 084 did not create the table.
- self.assertTableDoesNotExist('revocation_event')
-
- def test_project_is_domain_upgrade(self):
- self.upgrade(74)
- self.assertTableColumns('project',
- ['id', 'name', 'extra', 'description',
- 'enabled', 'domain_id', 'parent_id',
- 'is_domain'])
-
- def test_implied_roles_upgrade(self):
- self.upgrade(87)
- self.assertTableColumns('implied_role',
- ['prior_role_id', 'implied_role_id'])
- self.assertTrue(self.does_fk_exist('implied_role', 'prior_role_id'))
- self.assertTrue(self.does_fk_exist('implied_role', 'implied_role_id'))
-
- def test_add_config_registration(self):
- config_registration = 'config_register'
- self.upgrade(74)
- self.assertTableDoesNotExist(config_registration)
- self.upgrade(75)
- self.assertTableColumns(config_registration, ['type', 'domain_id'])
-
- def test_endpoint_filter_upgrade(self):
- def assert_tables_columns_exist():
- self.assertTableColumns('project_endpoint',
- ['endpoint_id', 'project_id'])
- self.assertTableColumns('endpoint_group',
- ['id', 'name', 'description', 'filters'])
- self.assertTableColumns('project_endpoint_group',
- ['endpoint_group_id', 'project_id'])
-
- self.assertTableDoesNotExist('project_endpoint')
- self.upgrade(85)
- assert_tables_columns_exist()
-
- @mock.patch.object(upgrades, 'get_db_version', return_value=2)
- def test_endpoint_filter_already_migrated(self, mock_endpoint_filter):
-
- # By setting the return value to 2, the migration has already been
- # run, and there's no need to create the table again.
- self.upgrade(85)
-
- mock_endpoint_filter.assert_any_call(extension='endpoint_filter',
- engine=mock.ANY)
-
- # It won't exist because we are mocking it, but we can verify
- # that 085 did not create the table.
- self.assertTableDoesNotExist('project_endpoint')
- self.assertTableDoesNotExist('endpoint_group')
- self.assertTableDoesNotExist('project_endpoint_group')
-
- def test_add_trust_unique_constraint_upgrade(self):
- self.upgrade(86)
- inspector = inspect(self.engine)
- constraints = inspector.get_unique_constraints('trust')
- constraint_names = [constraint['name'] for constraint in constraints]
- self.assertIn('duplicate_trust_constraint', constraint_names)
-
- def test_add_domain_specific_roles(self):
- """Check database upgraded successfully for domain specific roles.
-
- The following items need to be checked:
-
- - The domain_id column has been added
- - That it has been added to the uniqueness constraints
- - Existing roles have their domain_id columns set to the specific
- string of '<<null>>'
-
- """
- NULL_DOMAIN_ID = '<<null>>'
-
- self.upgrade(87)
- session = self.sessionmaker()
- role_table = sqlalchemy.Table('role', self.metadata, autoload=True)
- # Add a role before we upgrade, so we can check that its new domain_id
- # attribute is handled correctly
- role_id = uuid.uuid4().hex
- self.insert_dict(session, 'role',
- {'id': role_id, 'name': uuid.uuid4().hex})
- session.close()
-
- self.upgrade(88)
-
- session = self.sessionmaker()
- self.assertTableColumns('role', ['id', 'name', 'domain_id', 'extra'])
- # Check the domain_id has been added to the uniqueness constraint
- inspector = inspect(self.engine)
- constraints = inspector.get_unique_constraints('role')
- constraint_columns = [
- constraint['column_names'] for constraint in constraints
- if constraint['name'] == 'ixu_role_name_domain_id']
- self.assertIn('domain_id', constraint_columns[0])
-
- # Now check our role has its domain_id attribute set correctly
- role_table = sqlalchemy.Table('role', self.metadata, autoload=True)
- cols = [role_table.c.domain_id]
- filter = role_table.c.id == role_id
- statement = sqlalchemy.select(cols).where(filter)
- role_entry = session.execute(statement).fetchone()
- self.assertEqual(NULL_DOMAIN_ID, role_entry[0])
-
- def test_add_root_of_all_domains(self):
- NULL_DOMAIN_ID = '<<keystone.domain.root>>'
- self.upgrade(89)
- session = self.sessionmaker()
-
- domain_table = sqlalchemy.Table(
- 'domain', self.metadata, autoload=True)
- query = session.query(domain_table).filter_by(id=NULL_DOMAIN_ID)
- domain_from_db = query.one()
- self.assertIn(NULL_DOMAIN_ID, domain_from_db)
-
- project_table = sqlalchemy.Table(
- 'project', self.metadata, autoload=True)
- query = session.query(project_table).filter_by(id=NULL_DOMAIN_ID)
- project_from_db = query.one()
- self.assertIn(NULL_DOMAIN_ID, project_from_db)
-
- session.close()
-
- def test_add_local_user_and_password_tables(self):
- local_user_table = 'local_user'
- password_table = 'password'
- self.upgrade(89)
- self.assertTableDoesNotExist(local_user_table)
- self.assertTableDoesNotExist(password_table)
- self.upgrade(90)
- self.assertTableColumns(local_user_table,
- ['id',
- 'user_id',
- 'domain_id',
- 'name'])
- self.assertTableColumns(password_table,
- ['id',
- 'local_user_id',
- 'password'])
-
- def test_migrate_data_to_local_user_and_password_tables(self):
- def get_expected_users():
- expected_users = []
- for test_user in default_fixtures.USERS:
- user = {}
- user['id'] = uuid.uuid4().hex
- user['name'] = test_user['name']
- user['domain_id'] = test_user['domain_id']
- user['password'] = test_user['password']
- user['enabled'] = True
- user['extra'] = json.dumps(uuid.uuid4().hex)
- user['default_project_id'] = uuid.uuid4().hex
- expected_users.append(user)
- return expected_users
-
- def add_users_to_db(expected_users, user_table):
- for user in expected_users:
- ins = user_table.insert().values(
- {'id': user['id'],
- 'name': user['name'],
- 'domain_id': user['domain_id'],
- 'password': user['password'],
- 'enabled': user['enabled'],
- 'extra': user['extra'],
- 'default_project_id': user['default_project_id']})
- ins.execute()
-
- def get_users_from_db(user_table, local_user_table, password_table):
- sel = (
- sqlalchemy.select([user_table.c.id,
- user_table.c.enabled,
- user_table.c.extra,
- user_table.c.default_project_id,
- local_user_table.c.name,
- local_user_table.c.domain_id,
- password_table.c.password])
- .select_from(user_table.join(local_user_table,
- user_table.c.id ==
- local_user_table.c.user_id)
- .join(password_table,
- local_user_table.c.id ==
- password_table.c.local_user_id))
- )
- user_rows = sel.execute()
- users = []
- for row in user_rows:
- users.append(
- {'id': row['id'],
- 'name': row['name'],
- 'domain_id': row['domain_id'],
- 'password': row['password'],
- 'enabled': row['enabled'],
- 'extra': row['extra'],
- 'default_project_id': row['default_project_id']})
- return users
-
- user_table_name = 'user'
- local_user_table_name = 'local_user'
- password_table_name = 'password'
-
- # populate current user table
- self.upgrade(90)
- user_table = sqlalchemy.Table(
- user_table_name, self.metadata, autoload=True)
- expected_users = get_expected_users()
- add_users_to_db(expected_users, user_table)
-
- # upgrade to migration and test
- self.upgrade(91)
- self.assertTableCountsMatch(user_table_name, local_user_table_name)
- self.assertTableCountsMatch(local_user_table_name, password_table_name)
- user_table = sqlalchemy.Table(
- user_table_name, self.metadata, autoload=True)
- local_user_table = sqlalchemy.Table(
- local_user_table_name, self.metadata, autoload=True)
- password_table = sqlalchemy.Table(
- password_table_name, self.metadata, autoload=True)
- actual_users = get_users_from_db(user_table, local_user_table,
- password_table)
- self.assertCountEqual(expected_users, actual_users)
-
- def test_migrate_user_with_null_password_to_password_tables(self):
- USER_TABLE_NAME = 'user'
- LOCAL_USER_TABLE_NAME = 'local_user'
- PASSWORD_TABLE_NAME = 'password'
- self.upgrade(90)
- user_ref = unit.new_user_ref(uuid.uuid4().hex)
- user_ref.pop('password')
- # pop extra attribute which doesn't recognized by SQL expression
- # layer.
- user_ref.pop('email')
- session = self.sessionmaker()
- self.insert_dict(session, USER_TABLE_NAME, user_ref)
- self.upgrade(91)
- # migration should be successful.
- self.assertTableCountsMatch(USER_TABLE_NAME, LOCAL_USER_TABLE_NAME)
- # no new entry was added to the password table because the
- # user doesn't have a password.
- rows = self.calc_table_row_count(PASSWORD_TABLE_NAME)
- self.assertEqual(0, rows)
-
- def test_migrate_user_skip_user_already_exist_in_local_user(self):
- USER_TABLE_NAME = 'user'
- LOCAL_USER_TABLE_NAME = 'local_user'
- self.upgrade(90)
- user1_ref = unit.new_user_ref(uuid.uuid4().hex)
- # pop extra attribute which doesn't recognized by SQL expression
- # layer.
- user1_ref.pop('email')
- user2_ref = unit.new_user_ref(uuid.uuid4().hex)
- user2_ref.pop('email')
- session = self.sessionmaker()
- self.insert_dict(session, USER_TABLE_NAME, user1_ref)
- self.insert_dict(session, USER_TABLE_NAME, user2_ref)
- user_id = user1_ref.pop('id')
- user_name = user1_ref.pop('name')
- domain_id = user1_ref.pop('domain_id')
- local_user_ref = {'user_id': user_id, 'name': user_name,
- 'domain_id': domain_id}
- self.insert_dict(session, LOCAL_USER_TABLE_NAME, local_user_ref)
- self.upgrade(91)
- # migration should be successful and user2_ref has been migrated to
- # `local_user` table.
- self.assertTableCountsMatch(USER_TABLE_NAME, LOCAL_USER_TABLE_NAME)
-
- def test_implied_roles_fk_on_delete_cascade(self):
- if self.engine.name == 'sqlite':
- self.skipTest('sqlite backend does not support foreign keys')
-
- self.upgrade(92)
-
- session = self.sessionmaker()
-
- ROLE_TABLE_NAME = 'role'
- role_table = sqlalchemy.Table(ROLE_TABLE_NAME, self.metadata,
- autoload=True)
- IMPLIED_ROLE_TABLE_NAME = 'implied_role'
- implied_role_table = sqlalchemy.Table(
- IMPLIED_ROLE_TABLE_NAME, self.metadata, autoload=True)
-
- def _create_three_roles():
- id_list = []
- for _ in range(3):
- new_role_fields = {
- 'id': uuid.uuid4().hex,
- 'name': uuid.uuid4().hex,
- }
- self.insert_dict(session, ROLE_TABLE_NAME, new_role_fields,
- table=role_table)
- id_list.append(new_role_fields['id'])
- return id_list
-
- role_id_list = _create_three_roles()
- implied_role_fields = {
- 'prior_role_id': role_id_list[0],
- 'implied_role_id': role_id_list[1],
- }
- self.insert_dict(session, IMPLIED_ROLE_TABLE_NAME, implied_role_fields,
- table=implied_role_table)
-
- implied_role_fields = {
- 'prior_role_id': role_id_list[0],
- 'implied_role_id': role_id_list[2],
- }
- self.insert_dict(session, IMPLIED_ROLE_TABLE_NAME, implied_role_fields,
- table=implied_role_table)
-
- # assert that there are two roles implied by role 0.
- implied_roles = session.query(implied_role_table).filter_by(
- prior_role_id=role_id_list[0]).all()
- self.assertThat(implied_roles, matchers.HasLength(2))
-
- session.execute(
- role_table.delete().where(role_table.c.id == role_id_list[0]))
- # assert the cascade deletion is effective.
- implied_roles = session.query(implied_role_table).filter_by(
- prior_role_id=role_id_list[0]).all()
- self.assertThat(implied_roles, matchers.HasLength(0))
-
- def test_domain_as_project_upgrade(self):
- self.skipTest('Domain as Project Upgrade Test is no longer needed and '
- 'unfortunately broken by the resource options code.')
-
- def _populate_domain_and_project_tables(session):
- # Three domains, with various different attributes
- self.domains = [{'id': uuid.uuid4().hex,
- 'name': uuid.uuid4().hex,
- 'enabled': True,
- 'extra': {'description': uuid.uuid4().hex,
- 'another_attribute': True}},
- {'id': uuid.uuid4().hex,
- 'name': uuid.uuid4().hex,
- 'enabled': True,
- 'extra': {'description': uuid.uuid4().hex}},
- {'id': uuid.uuid4().hex,
- 'name': uuid.uuid4().hex,
- 'enabled': False}]
- # Four projects, two top level, two children
- self.projects = []
- self.projects.append(unit.new_project_ref(
- domain_id=self.domains[0]['id'],
- parent_id=None))
- self.projects.append(unit.new_project_ref(
- domain_id=self.domains[0]['id'],
- parent_id=self.projects[0]['id']))
- self.projects.append(unit.new_project_ref(
- domain_id=self.domains[1]['id'],
- parent_id=None))
- self.projects.append(unit.new_project_ref(
- domain_id=self.domains[1]['id'],
- parent_id=self.projects[2]['id']))
-
- for domain in self.domains:
- this_domain = domain.copy()
- if 'extra' in this_domain:
- this_domain['extra'] = json.dumps(this_domain['extra'])
- self.insert_dict(session, 'domain', this_domain)
- for project in self.projects:
- # Tags are done via relationship, not column
- project.pop('tags', None)
- self.insert_dict(session, 'project', project)
-
- def _check_projects(projects):
-
- def _assert_domain_matches_project(project):
- for domain in self.domains:
- if project.id == domain['id']:
- self.assertEqual(domain['name'], project.name)
- self.assertEqual(domain['enabled'], project.enabled)
- if domain['id'] == self.domains[0]['id']:
- self.assertEqual(domain['extra']['description'],
- project.description)
- self.assertEqual({'another_attribute': True},
- json.loads(project.extra))
- elif domain['id'] == self.domains[1]['id']:
- self.assertEqual(domain['extra']['description'],
- project.description)
- self.assertEqual({}, json.loads(project.extra))
-
- # We had domains 3 we created, which should now be projects acting
- # as domains, To this we add the 4 original projects, plus the root
- # of all domains row.
- self.assertEqual(8, projects.count())
-
- project_ids = []
- for project in projects:
- if project.is_domain:
- self.assertEqual(NULL_DOMAIN_ID, project.domain_id)
- self.assertIsNone(project.parent_id)
- else:
- self.assertIsNotNone(project.domain_id)
- self.assertIsNotNone(project.parent_id)
- project_ids.append(project.id)
-
- for domain in self.domains:
- self.assertIn(domain['id'], project_ids)
- for project in self.projects:
- self.assertIn(project['id'], project_ids)
-
- # Now check the attributes of the domains came across OK
- for project in projects:
- _assert_domain_matches_project(project)
-
- NULL_DOMAIN_ID = '<<keystone.domain.root>>'
- self.upgrade(92)
-
- session = self.sessionmaker()
-
- _populate_domain_and_project_tables(session)
-
- self.upgrade(93)
- proj_table = sqlalchemy.Table('project', self.metadata, autoload=True)
-
- projects = session.query(proj_table)
- _check_projects(projects)
-
- def test_add_federated_user_table(self):
- federated_user_table = 'federated_user'
- self.upgrade(93)
- self.assertTableDoesNotExist(federated_user_table)
- self.upgrade(94)
- self.assertTableColumns(federated_user_table,
- ['id',
- 'user_id',
- 'idp_id',
- 'protocol_id',
- 'unique_id',
- 'display_name'])
-
- def test_add_int_pkey_to_revocation_event_table(self):
- REVOCATION_EVENT_TABLE_NAME = 'revocation_event'
- self.upgrade(94)
- revocation_event_table = sqlalchemy.Table(REVOCATION_EVENT_TABLE_NAME,
- self.metadata, autoload=True)
- # assert id column is a string (before)
- self.assertEqual('VARCHAR(64)', str(revocation_event_table.c.id.type))
- self.upgrade(95)
- revocation_event_table = sqlalchemy.Table(REVOCATION_EVENT_TABLE_NAME,
- self.metadata, autoload=True)
- # assert id column is an integer (after)
- self.assertIsInstance(revocation_event_table.c.id.type, sql.Integer)
-
- def _add_unique_constraint_to_role_name(self,
- constraint_name='ixu_role_name'):
- role_table = sqlalchemy.Table('role', self.metadata, autoload=True)
- migrate.UniqueConstraint(role_table.c.name,
- name=constraint_name).create()
-
- def _drop_unique_constraint_to_role_name(self,
- constraint_name='ixu_role_name'):
- role_table = sqlalchemy.Table('role', self.metadata, autoload=True)
- migrate.UniqueConstraint(role_table.c.name,
- name=constraint_name).drop()
-
- def _add_unique_constraint_to_user_name_domainid(
- self,
- constraint_name='ixu_role_name'):
- user_table = sqlalchemy.Table('user', self.metadata, autoload=True)
- migrate.UniqueConstraint(user_table.c.name, user_table.c.domain_id,
- name=constraint_name).create()
-
- def _add_name_domain_id_columns_to_user(self):
- user_table = sqlalchemy.Table('user', self.metadata, autoload=True)
- column_name = sqlalchemy.Column('name', sql.String(255))
- column_domain_id = sqlalchemy.Column('domain_id', sql.String(64))
- user_table.create_column(column_name)
- user_table.create_column(column_domain_id)
-
- def _drop_unique_constraint_to_user_name_domainid(
- self,
- constraint_name='ixu_user_name_domain_id'):
- user_table = sqlalchemy.Table('user', self.metadata, autoload=True)
- migrate.UniqueConstraint(user_table.c.name, user_table.c.domain_id,
- name=constraint_name).drop()
-
- def test_migration_88_drops_unique_constraint(self):
- self.upgrade(87)
- if self.engine.name == 'mysql':
- self.assertTrue(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertTrue(self.does_constraint_exist('role',
- 'ixu_role_name'))
- self.upgrade(88)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertFalse(self.does_constraint_exist('role',
- 'ixu_role_name'))
-
- def test_migration_88_inconsistent_constraint_name(self):
- self.upgrade(87)
- self._drop_unique_constraint_to_role_name()
-
- constraint_name = uuid.uuid4().hex
- self._add_unique_constraint_to_role_name(
- constraint_name=constraint_name)
-
- if self.engine.name == 'mysql':
- self.assertTrue(self.does_index_exist('role', constraint_name))
- self.assertFalse(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertTrue(self.does_constraint_exist('role',
- constraint_name))
- self.assertFalse(self.does_constraint_exist('role',
- 'ixu_role_name'))
-
- self.upgrade(88)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist('role', constraint_name))
- self.assertFalse(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertFalse(self.does_constraint_exist('role',
- constraint_name))
- self.assertFalse(self.does_constraint_exist('role',
- 'ixu_role_name'))
-
- def test_migration_91_drops_unique_constraint(self):
- self.upgrade(90)
- if self.engine.name == 'mysql':
- self.assertTrue(self.does_index_exist('user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertTrue(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- self.upgrade(91)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertFalse(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
-
- def test_migration_91_inconsistent_constraint_name(self):
- self.upgrade(90)
- self._drop_unique_constraint_to_user_name_domainid()
-
- constraint_name = uuid.uuid4().hex
- self._add_unique_constraint_to_user_name_domainid(
- constraint_name=constraint_name)
-
- if self.engine.name == 'mysql':
- self.assertTrue(self.does_index_exist('user', constraint_name))
- self.assertFalse(self.does_index_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertTrue(self.does_constraint_exist('user',
- constraint_name))
- self.assertFalse(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
-
- self.upgrade(91)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist('user', constraint_name))
- self.assertFalse(self.does_index_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertFalse(self.does_constraint_exist('user',
- constraint_name))
- self.assertFalse(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
-
- def test_migration_96(self):
- self.upgrade(95)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertFalse(self.does_constraint_exist('role',
- 'ixu_role_name'))
-
- self.upgrade(96)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertFalse(self.does_constraint_exist('role',
- 'ixu_role_name'))
-
- def test_migration_96_constraint_exists(self):
- self.upgrade(95)
- self._add_unique_constraint_to_role_name()
-
- if self.engine.name == 'mysql':
- self.assertTrue(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertTrue(self.does_constraint_exist('role',
- 'ixu_role_name'))
-
- self.upgrade(96)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertFalse(self.does_constraint_exist('role',
- 'ixu_role_name'))
-
- def test_migration_97(self):
- self.upgrade(96)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertFalse(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
-
- self.upgrade(97)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertFalse(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
-
- def test_migration_97_constraint_exists(self):
- self.upgrade(96)
- self._add_name_domain_id_columns_to_user()
- self._add_unique_constraint_to_user_name_domainid(
- constraint_name='ixu_user_name_domain_id')
-
- if self.engine.name == 'mysql':
- self.assertTrue(self.does_index_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertTrue(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
-
- self.upgrade(97)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertFalse(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
-
- def test_migration_97_inconsistent_constraint_exists(self):
- self.upgrade(96)
- constraint_name = uuid.uuid4().hex
- self._add_name_domain_id_columns_to_user()
- self._add_unique_constraint_to_user_name_domainid(
- constraint_name=constraint_name)
-
- if self.engine.name == 'mysql':
- self.assertTrue(self.does_index_exist('user', constraint_name))
- else:
- self.assertTrue(self.does_constraint_exist('user',
- constraint_name))
-
- self.upgrade(97)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist('user', constraint_name))
- else:
- self.assertFalse(self.does_constraint_exist('user',
- constraint_name))
-
- def test_migration_101(self):
- self.upgrade(100)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertFalse(self.does_constraint_exist('role',
- 'ixu_role_name'))
- self.upgrade(101)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertFalse(self.does_constraint_exist('role',
- 'ixu_role_name'))
-
- def test_migration_101_constraint_exists(self):
- self.upgrade(100)
- self._add_unique_constraint_to_role_name()
-
- if self.engine.name == 'mysql':
- self.assertTrue(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertTrue(self.does_constraint_exist('role',
- 'ixu_role_name'))
- self.upgrade(101)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist('role', 'ixu_role_name'))
- else:
- self.assertFalse(self.does_constraint_exist('role',
- 'ixu_role_name'))
-
- def test_drop_domain_table(self):
- self.upgrade(101)
- self.assertTableExists('domain')
- self.upgrade(102)
- self.assertTableDoesNotExist('domain')
-
- def test_add_nonlocal_user_table(self):
- nonlocal_user_table = 'nonlocal_user'
- self.upgrade(102)
- self.assertTableDoesNotExist(nonlocal_user_table)
- self.upgrade(103)
- self.assertTableColumns(nonlocal_user_table,
- ['domain_id',
- 'name',
- 'user_id'])
-
- def test_migration_104(self):
- self.upgrade(103)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertFalse(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
-
- self.upgrade(104)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertFalse(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
-
- def test_migration_104_constraint_exists(self):
- self.upgrade(103)
- self._add_name_domain_id_columns_to_user()
- self._add_unique_constraint_to_user_name_domainid(
- constraint_name='ixu_user_name_domain_id')
-
- if self.engine.name == 'mysql':
- self.assertTrue(self.does_index_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertTrue(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
-
- self.upgrade(104)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist(
- 'user',
- 'ixu_user_name_domain_id'))
- else:
- self.assertFalse(self.does_constraint_exist(
- 'user',
- 'ixu_user_name_domain_id'))
-
- def test_migration_104_inconsistent_constraint_exists(self):
- self.upgrade(103)
- constraint_name = uuid.uuid4().hex
- self._add_name_domain_id_columns_to_user()
- self._add_unique_constraint_to_user_name_domainid(
- constraint_name=constraint_name)
-
- if self.engine.name == 'mysql':
- self.assertTrue(self.does_index_exist('user', constraint_name))
- else:
- self.assertTrue(self.does_constraint_exist('user',
- constraint_name))
-
- self.upgrade(104)
- if self.engine.name == 'mysql':
- self.assertFalse(self.does_index_exist('user', constraint_name))
- else:
- self.assertFalse(self.does_constraint_exist('user',
- constraint_name))
-
- def test_migration_105_add_password_date_columns(self):
- def add_user_model_record(session):
- # add a user
- user = {'id': uuid.uuid4().hex}
- self.insert_dict(session, 'user', user)
- # add a local user
- local_user = {
- 'id': 1,
- 'user_id': user['id'],
- 'domain_id': 'default',
- 'name': uuid.uuid4().hex
- }
- self.insert_dict(session, 'local_user', local_user)
- # add a password
- password = {
- 'local_user_id': local_user['id'],
- 'password': uuid.uuid4().hex
- }
- self.insert_dict(session, 'password', password)
- self.upgrade(104)
- session = self.sessionmaker()
- password_name = 'password'
- # columns before
- self.assertTableColumns(password_name,
- ['id',
- 'local_user_id',
- 'password'])
- # add record and verify table count is greater than zero
- add_user_model_record(session)
- password_table = sqlalchemy.Table(password_name, self.metadata,
- autoload=True)
- cnt = session.query(password_table).count()
- self.assertGreater(cnt, 0)
- self.upgrade(105)
- # columns after
- self.assertTableColumns(password_name,
- ['id',
- 'local_user_id',
- 'password',
- 'created_at',
- 'expires_at'])
- password_table = sqlalchemy.Table(password_name, self.metadata,
- autoload=True)
- # verify created_at is not null
- null_created_at_cnt = (
- session.query(password_table).filter_by(created_at=None).count())
- self.assertEqual(null_created_at_cnt, 0)
- # verify expires_at is null
- null_expires_at_cnt = (
- session.query(password_table).filter_by(expires_at=None).count())
- self.assertGreater(null_expires_at_cnt, 0)
-
- def test_migration_106_allow_password_column_to_be_nullable(self):
- password_table_name = 'password'
- self.upgrade(105)
- password_table = sqlalchemy.Table(password_table_name, self.metadata,
- autoload=True)
- self.assertFalse(password_table.c.password.nullable)
- self.upgrade(106)
- password_table = sqlalchemy.Table(password_table_name, self.metadata,
- autoload=True)
- self.assertTrue(password_table.c.password.nullable)
-
- def test_migration_107_add_user_date_columns(self):
- user_table = 'user'
- self.upgrade(106)
- self.assertTableColumns(user_table,
- ['id',
- 'extra',
- 'enabled',
- 'default_project_id'])
- self.upgrade(107)
- self.assertTableColumns(user_table,
- ['id',
- 'extra',
- 'enabled',
- 'default_project_id',
- 'created_at',
- 'last_active_at'])
-
- def test_migration_108_add_failed_auth_columns(self):
- self.upgrade(107)
- table_name = 'local_user'
- self.assertTableColumns(table_name,
- ['id',
- 'user_id',
- 'domain_id',
- 'name'])
- self.upgrade(108)
- self.assertTableColumns(table_name,
- ['id',
- 'user_id',
- 'domain_id',
- 'name',
- 'failed_auth_count',
- 'failed_auth_at'])
-
- def test_migration_109_add_password_self_service_column(self):
- password_table = 'password'
- self.upgrade(108)
- self.assertTableColumns(password_table,
- ['id',
- 'local_user_id',
- 'password',
- 'created_at',
- 'expires_at'])
- self.upgrade(109)
- self.assertTableColumns(password_table,
- ['id',
- 'local_user_id',
- 'password',
- 'created_at',
- 'expires_at',
- 'self_service'])
-
-
-class MySQLOpportunisticUpgradeTestCase(SqlLegacyRepoUpgradeTests):
- FIXTURE = db_fixtures.MySQLOpportunisticFixture
-
-
-class PostgreSQLOpportunisticUpgradeTestCase(SqlLegacyRepoUpgradeTests):
- FIXTURE = db_fixtures.PostgresqlOpportunisticFixture
-
-
-class SqlExpandSchemaUpgradeTests(SqlMigrateBase):
-
- def setUp(self):
- # Make sure the main repo is fully upgraded for this release since the
- # expand phase is only run after such an upgrade
- super(SqlExpandSchemaUpgradeTests, self).setUp()
- self.upgrade()
-
- def test_start_version_db_init_version(self):
- self.assertEqual(
- self.repos[EXPAND_REPO].min_version,
- self.repos[EXPAND_REPO].version)
-
class MySQLOpportunisticExpandSchemaUpgradeTestCase(
- SqlExpandSchemaUpgradeTests):
+ ExpandSchemaUpgradeTests,
+):
FIXTURE = db_fixtures.MySQLOpportunisticFixture
class PostgreSQLOpportunisticExpandSchemaUpgradeTestCase(
- SqlExpandSchemaUpgradeTests):
+ ExpandSchemaUpgradeTests,
+):
FIXTURE = db_fixtures.PostgresqlOpportunisticFixture
-class SqlDataMigrationUpgradeTests(SqlMigrateBase):
+class DataMigrationUpgradeTests(MigrateBase):
def setUp(self):
- # Make sure the legacy and expand repos are fully upgraded, since the
- # data migration phase is only run after these are upgraded
- super(SqlDataMigrationUpgradeTests, self).setUp()
- self.upgrade()
+ # Make sure the expand repo is fully upgraded, since the data migration
+ # phase is only run after this is upgraded
+ super().setUp()
self.expand()
def test_start_version_db_init_version(self):
self.assertEqual(
- self.repos[DATA_MIGRATION_REPO].min_version,
- self.repos[DATA_MIGRATION_REPO].version)
+ self.repos[upgrades.DATA_MIGRATION_BRANCH].min_version,
+ self.repos[upgrades.DATA_MIGRATION_BRANCH].version,
+ )
class MySQLOpportunisticDataMigrationUpgradeTestCase(
- SqlDataMigrationUpgradeTests):
+ DataMigrationUpgradeTests,
+):
FIXTURE = db_fixtures.MySQLOpportunisticFixture
class PostgreSQLOpportunisticDataMigrationUpgradeTestCase(
- SqlDataMigrationUpgradeTests):
+ DataMigrationUpgradeTests,
+):
FIXTURE = db_fixtures.PostgresqlOpportunisticFixture
-class SqlContractSchemaUpgradeTests(SqlMigrateBase, unit.TestCase):
+class ContractSchemaUpgradeTests(MigrateBase, unit.TestCase):
def setUp(self):
- # Make sure the legacy, expand and data migration repos are fully
+ # Make sure the expand and data migration repos are fully
# upgraded, since the contract phase is only run after these are
# upgraded.
- super(SqlContractSchemaUpgradeTests, self).setUp()
+ super().setUp()
self.useFixture(
ksfixtures.KeyRepository(
self.config_fixture,
@@ -1577,64 +430,29 @@ class SqlContractSchemaUpgradeTests(SqlMigrateBase, unit.TestCase):
credential_fernet.MAX_ACTIVE_KEYS
)
)
- self.upgrade()
self.expand()
self.migrate()
def test_start_version_db_init_version(self):
self.assertEqual(
- self.repos[CONTRACT_REPO].min_version,
- self.repos[CONTRACT_REPO].version)
+ self.repos[upgrades.CONTRACT_BRANCH].min_version,
+ self.repos[upgrades.CONTRACT_BRANCH].version,
+ )
class MySQLOpportunisticContractSchemaUpgradeTestCase(
- SqlContractSchemaUpgradeTests):
+ ContractSchemaUpgradeTests,
+):
FIXTURE = db_fixtures.MySQLOpportunisticFixture
class PostgreSQLOpportunisticContractSchemaUpgradeTestCase(
- SqlContractSchemaUpgradeTests):
+ ContractSchemaUpgradeTests,
+):
FIXTURE = db_fixtures.PostgresqlOpportunisticFixture
-class VersionTests(SqlMigrateBase):
- def test_core_initial(self):
- """Get the version before migrated, it's the initial DB version."""
- self.assertEqual(
- self.repos[LEGACY_REPO].min_version,
- self.repos[LEGACY_REPO].version)
-
- def test_core_max(self):
- """When get the version after upgrading, it's the new version."""
- self.upgrade()
- self.assertEqual(
- self.repos[LEGACY_REPO].max_version,
- self.repos[LEGACY_REPO].version)
-
- def test_assert_not_schema_downgrade(self):
- self.upgrade()
- self.assertRaises(
- db_exception.DBMigrationError,
- upgrades._sync_common_repo,
- self.repos[LEGACY_REPO].max_version - 1)
-
- def test_these_are_not_the_migrations_you_are_looking_for(self):
- """Keystone has shifted to rolling upgrades.
-
- New database migrations should no longer land in the legacy migration
- repository. Instead, new database migrations should be divided into
- three discrete steps: schema expansion, data migration, and schema
- contraction. These migrations live in a new set of database migration
- repositories, called ``expand_repo``, ``data_migration_repo``, and
- ``contract_repo``.
-
- For more information, see "Database Migrations" here:
-
- https://docs.openstack.org/keystone/latest/contributor/database-migrations.html
-
- """
- # Note to reviewers: this version number should never change.
- self.assertEqual(109, self.repos[LEGACY_REPO].max_version)
+class VersionTests(MigrateBase):
def test_migrate_repos_stay_in_lockstep(self):
"""Rolling upgrade repositories should always stay in lockstep.
@@ -1658,11 +476,13 @@ class VersionTests(SqlMigrateBase):
"""
# Transitive comparison: expand == data migration == contract
self.assertEqual(
- self.repos[EXPAND_REPO].max_version,
- self.repos[DATA_MIGRATION_REPO].max_version)
+ self.repos[upgrades.EXPAND_BRANCH].max_version,
+ self.repos[upgrades.DATA_MIGRATION_BRANCH].max_version,
+ )
self.assertEqual(
- self.repos[DATA_MIGRATION_REPO].max_version,
- self.repos[CONTRACT_REPO].max_version)
+ self.repos[upgrades.DATA_MIGRATION_BRANCH].max_version,
+ self.repos[upgrades.CONTRACT_BRANCH].max_version,
+ )
def test_migrate_repos_file_names_have_prefix(self):
"""Migration files should be unique to avoid caching errors.
@@ -1674,17 +494,20 @@ class VersionTests(SqlMigrateBase):
"""
versions_path = '/versions'
+
# test for expand prefix, e.g. 001_expand_new_fk_constraint.py
- expand_list = glob.glob(
- self.repos[EXPAND_REPO].repo_path + versions_path + '/*.py')
+ repo_path = self.repos[upgrades.EXPAND_BRANCH].repo_path
+ expand_list = glob.glob(repo_path + versions_path + '/*.py')
self.assertRepoFileNamePrefix(expand_list, 'expand')
+
# test for migrate prefix, e.g. 001_migrate_new_fk_constraint.py
- repo_path = self.repos[DATA_MIGRATION_REPO].repo_path
+ repo_path = self.repos[upgrades.DATA_MIGRATION_BRANCH].repo_path
migrate_list = glob.glob(repo_path + versions_path + '/*.py')
self.assertRepoFileNamePrefix(migrate_list, 'migrate')
+
# test for contract prefix, e.g. 001_contract_new_fk_constraint.py
- contract_list = glob.glob(
- self.repos[CONTRACT_REPO].repo_path + versions_path + '/*.py')
+ repo_path = self.repos[upgrades.CONTRACT_BRANCH].repo_path
+ contract_list = glob.glob(repo_path + versions_path + '/*.py')
self.assertRepoFileNamePrefix(contract_list, 'contract')
def assertRepoFileNamePrefix(self, repo_list, prefix):
@@ -1699,58 +522,45 @@ class VersionTests(SqlMigrateBase):
self.assertRegex(file_name, pattern, msg)
-class MigrationValidation(SqlMigrateBase, unit.TestCase):
+class MigrationValidation(MigrateBase, unit.TestCase):
"""Test validation of database between database phases."""
def _set_db_sync_command_versions(self):
- self.expand(1)
- self.migrate(1)
- self.contract(1)
- self.assertEqual(upgrades.get_db_version('expand_repo'), 1)
- self.assertEqual(upgrades.get_db_version('data_migration_repo'), 1)
- self.assertEqual(upgrades.get_db_version('contract_repo'), 1)
-
- def test_running_db_sync_expand_without_up_to_date_legacy_fails(self):
- # Set Legacy version and then test that running expand fails if Legacy
- # isn't at the latest version.
- self.upgrade(67)
- latest_version = self.repos[EXPAND_REPO].max_version
- self.assertRaises(
- db_exception.DBMigrationError,
- self.expand,
- latest_version,
- "You are attempting to upgrade migrate ahead of expand")
+ self.expand(upgrades.INITIAL_VERSION + 1)
+ self.migrate(upgrades.INITIAL_VERSION + 1)
+ self.contract(upgrades.INITIAL_VERSION + 1)
+ for version in (
+ upgrades.get_db_version('expand'),
+ upgrades.get_db_version('data_migration'),
+ upgrades.get_db_version('contract'),
+ ):
+ self.assertEqual(upgrades.INITIAL_VERSION + 1, version)
def test_running_db_sync_migrate_ahead_of_expand_fails(self):
- self.upgrade()
self._set_db_sync_command_versions()
self.assertRaises(
db_exception.DBMigrationError,
self.migrate,
- 2,
- "You are attempting to upgrade migrate ahead of expand")
+ upgrades.INITIAL_VERSION + 2,
+ "You are attempting to upgrade migrate ahead of expand",
+ )
def test_running_db_sync_contract_ahead_of_migrate_fails(self):
- self.upgrade()
self._set_db_sync_command_versions()
self.assertRaises(
db_exception.DBMigrationError,
self.contract,
- 2,
- "You are attempting to upgrade contract ahead of migrate")
+ upgrades.INITIAL_VERSION + 2,
+ "You are attempting to upgrade contract ahead of migrate",
+ )
-class FullMigration(SqlMigrateBase, unit.TestCase):
+class FullMigration(MigrateBase, unit.TestCase):
"""Test complete orchestration between all database phases."""
- def setUp(self):
- super(FullMigration, self).setUp()
- # Upgrade the legacy repository
- self.upgrade()
-
def test_db_sync_check(self):
checker = cli.DbSync()
- latest_version = self.repos[EXPAND_REPO].max_version
+ latest_version = self.repos[upgrades.EXPAND_BRANCH].max_version
# If the expand repository doesn't exist yet, then we need to make sure
# we advertise that `--expand` must be run first.
@@ -1761,7 +571,7 @@ class FullMigration(SqlMigrateBase, unit.TestCase):
# Assert the correct message is printed when expand is the first step
# that needs to run
- self.expand(1)
+ self.expand(upgrades.INITIAL_VERSION + 1)
log_info = self.useFixture(fixtures.FakeLogger(level=log.INFO))
status = checker.check_db_sync_status()
self.assertIn("keystone-manage db_sync --expand", log_info.output)
@@ -1795,1709 +605,13 @@ class FullMigration(SqlMigrateBase, unit.TestCase):
# We shouldn't allow for operators to accidentally run migration out of
# order. This test ensures we fail if we attempt to upgrade the
# contract repository ahead of the expand or migrate repositories.
- self.expand(3)
- self.migrate(3)
- self.assertRaises(db_exception.DBMigrationError, self.contract, 4)
-
- def test_migration_002_password_created_at_not_nullable(self):
- # upgrade each repository to 001
- self.expand(1)
- self.migrate(1)
- self.contract(1)
-
- password = sqlalchemy.Table('password', self.metadata, autoload=True)
- self.assertTrue(password.c.created_at.nullable)
- # upgrade each repository to 002
- self.expand(2)
- self.migrate(2)
- self.contract(2)
- password = sqlalchemy.Table('password', self.metadata, autoload=True)
- if self.engine.name != 'sqlite':
- self.assertFalse(password.c.created_at.nullable)
-
- def test_migration_003_migrate_unencrypted_credentials(self):
- self.useFixture(
- ksfixtures.KeyRepository(
- self.config_fixture,
- 'credential',
- credential_fernet.MAX_ACTIVE_KEYS
- )
- )
-
- session = self.sessionmaker()
- credential_table_name = 'credential'
-
- # upgrade each repository to 002
- self.expand(2)
- self.migrate(2)
- self.contract(2)
-
- # populate the credential table with some sample credentials
- credentials = list()
- for i in range(5):
- credential = {'id': uuid.uuid4().hex,
- 'blob': uuid.uuid4().hex,
- 'user_id': uuid.uuid4().hex,
- 'type': 'cert'}
- credentials.append(credential)
- self.insert_dict(session, credential_table_name, credential)
-
- # verify the current schema
- self.assertTableColumns(
- credential_table_name,
- ['id', 'user_id', 'project_id', 'type', 'blob', 'extra']
- )
-
- # upgrade expand repo to 003 to add new columns
- self.expand(3)
-
- # verify encrypted_blob and key_hash columns have been added and verify
- # the original blob column is still there
- self.assertTableColumns(
- credential_table_name,
- ['id', 'user_id', 'project_id', 'type', 'blob', 'extra',
- 'key_hash', 'encrypted_blob']
- )
-
- # verify triggers by making sure we can't write to the credential table
- credential = {'id': uuid.uuid4().hex,
- 'blob': uuid.uuid4().hex,
- 'user_id': uuid.uuid4().hex,
- 'type': 'cert'}
- self.assertRaises(db_exception.DBError,
- self.insert_dict,
- session,
- credential_table_name,
- credential)
-
- # upgrade migrate repo to 003 to migrate existing credentials
- self.migrate(3)
-
- # make sure we've actually updated the credential with the
- # encrypted blob and the corresponding key hash
- credential_table = sqlalchemy.Table(
- credential_table_name,
- self.metadata,
- autoload=True
- )
- for credential in credentials:
- filter = credential_table.c.id == credential['id']
- cols = [credential_table.c.key_hash, credential_table.c.blob,
- credential_table.c.encrypted_blob]
- q = sqlalchemy.select(cols).where(filter)
- result = session.execute(q).fetchone()
-
- self.assertIsNotNone(result.encrypted_blob)
- self.assertIsNotNone(result.key_hash)
- # verify the original blob column is still populated
- self.assertEqual(result.blob, credential['blob'])
-
- # verify we can't make any writes to the credential table
- credential = {'id': uuid.uuid4().hex,
- 'blob': uuid.uuid4().hex,
- 'user_id': uuid.uuid4().hex,
- 'key_hash': uuid.uuid4().hex,
- 'type': 'cert'}
- self.assertRaises(db_exception.DBError,
- self.insert_dict,
- session,
- credential_table_name,
- credential)
-
- # upgrade contract repo to 003 to remove triggers and blob column
- self.contract(3)
-
- # verify the new schema doesn't have a blob column anymore
- self.assertTableColumns(
- credential_table_name,
- ['id', 'user_id', 'project_id', 'type', 'extra', 'key_hash',
- 'encrypted_blob']
- )
-
- # verify that the triggers are gone by writing to the database
- credential = {'id': uuid.uuid4().hex,
- 'encrypted_blob': uuid.uuid4().hex,
- 'key_hash': uuid.uuid4().hex,
- 'user_id': uuid.uuid4().hex,
- 'type': 'cert'}
- self.insert_dict(session, credential_table_name, credential)
-
- def test_migration_004_reset_password_created_at(self):
- # upgrade each repository to 003 and test
- self.expand(3)
- self.migrate(3)
- self.contract(3)
- password = sqlalchemy.Table('password', self.metadata, autoload=True)
- # postgresql returns 'TIMESTAMP WITHOUT TIME ZONE'
- self.assertTrue(
- str(password.c.created_at.type).startswith('TIMESTAMP'))
- # upgrade each repository to 004 and test
- self.expand(4)
- self.migrate(4)
- self.contract(4)
- password = sqlalchemy.Table('password', self.metadata, autoload=True)
- # type would still be TIMESTAMP with postgresql
- if self.engine.name == 'postgresql':
- self.assertTrue(
- str(password.c.created_at.type).startswith('TIMESTAMP'))
- else:
- self.assertEqual('DATETIME', str(password.c.created_at.type))
- self.assertFalse(password.c.created_at.nullable)
-
- 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)
- self.migrate(23)
- self.contract(23)
-
- password_table_name = 'password'
-
- self.assertTableColumns(
- password_table_name,
- ['id', 'local_user_id', 'password', 'password_hash', 'created_at',
- 'expires_at', 'self_service']
- )
-
- self.expand(24)
-
- self.assertTableColumns(
- password_table_name,
- ['id', 'local_user_id', 'password', 'password_hash', 'created_at',
- 'expires_at', 'created_at_int', 'expires_at_int', 'self_service']
- )
-
- # 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_table.insert().values(password_data).execute()
-
- self.migrate(24)
- self.contract(24)
- passwords = list(password_table.select().execute())
-
- epoch = datetime.datetime.fromtimestamp(0, tz=pytz.UTC)
-
- for p in passwords:
- c = (p.created_at.replace(tzinfo=pytz.UTC) - epoch).total_seconds()
- e = (p.expires_at.replace(tzinfo=pytz.UTC) - epoch).total_seconds()
- self.assertEqual(p.created_at_int, int(c * 1000000))
- self.assertEqual(p.expires_at_int, int(e * 1000000))
-
- # Test contract phase and ensure data can not be null
- self.contract(24)
- meta = sqlalchemy.MetaData(self.engine)
- pw_table = sqlalchemy.Table('password', meta, autoload=True)
- self.assertFalse(pw_table.c.created_at_int.nullable)
-
- def test_migration_30_expand_add_project_tags_table(self):
- self.expand(29)
- self.migrate(29)
- self.contract(29)
-
- table_name = 'project_tag'
- self.assertTableDoesNotExist(table_name)
-
- self.expand(30)
- self.migrate(30)
- self.contract(30)
-
- self.assertTableExists(table_name)
- self.assertTableColumns(
- table_name,
- ['project_id', 'name'])
-
- def test_migration_030_project_tags_works_correctly_after_migration(self):
- if self.engine.name == 'sqlite':
- self.skipTest('sqlite backend does not support foreign keys')
-
- self.expand(30)
- self.migrate(30)
- self.contract(30)
-
- project_table = sqlalchemy.Table(
- 'project', self.metadata, autoload=True)
- tag_table = sqlalchemy.Table(
- 'project_tag', self.metadata, autoload=True)
-
- session = self.sessionmaker()
- project_id = uuid.uuid4().hex
-
- project = {
- 'id': project_id,
- 'name': uuid.uuid4().hex,
- 'enabled': True,
- 'domain_id': resource_base.NULL_DOMAIN_ID,
- 'is_domain': False
- }
-
- tag = {
- 'project_id': project_id,
- 'name': uuid.uuid4().hex
- }
-
- self.insert_dict(session, 'project', project)
- self.insert_dict(session, 'project_tag', tag)
-
- tags_query = session.query(tag_table).filter_by(
- project_id=project_id).all()
- self.assertThat(tags_query, matchers.HasLength(1))
-
- # Adding duplicate tags should cause error.
- self.assertRaises(db_exception.DBDuplicateEntry,
- self.insert_dict,
- session, 'project_tag', tag)
-
- session.execute(
- project_table.delete().where(project_table.c.id == project_id)
- )
-
- tags_query = session.query(tag_table).filter_by(
- project_id=project_id).all()
- self.assertThat(tags_query, matchers.HasLength(0))
-
- session.close()
-
- def test_migration_031_adds_system_assignment_table(self):
- self.expand(30)
- self.migrate(30)
- self.contract(30)
-
- system_assignment_table_name = 'system_assignment'
- self.assertTableDoesNotExist(system_assignment_table_name)
-
- self.expand(31)
- self.migrate(31)
- self.contract(31)
-
- self.assertTableExists(system_assignment_table_name)
- self.assertTableColumns(
- system_assignment_table_name,
- ['type', 'actor_id', 'target_id', 'role_id', 'inherited']
- )
-
- system_assignment_table = sqlalchemy.Table(
- system_assignment_table_name, self.metadata, autoload=True
- )
-
- system_user = {
- 'type': 'UserSystem',
- 'target_id': uuid.uuid4().hex,
- 'actor_id': uuid.uuid4().hex,
- 'role_id': uuid.uuid4().hex,
- 'inherited': False
- }
- system_assignment_table.insert().values(system_user).execute()
-
- system_group = {
- 'type': 'GroupSystem',
- 'target_id': uuid.uuid4().hex,
- 'actor_id': uuid.uuid4().hex,
- 'role_id': uuid.uuid4().hex,
- 'inherited': False
- }
- system_assignment_table.insert().values(system_group).execute()
-
- def test_migration_032_add_expires_at_int_column_trust(self):
-
- self.expand(31)
- self.migrate(31)
- self.contract(31)
-
- trust_table_name = 'trust'
-
- self.assertTableColumns(
- trust_table_name,
- ['id', 'trustor_user_id', 'trustee_user_id', 'project_id',
- 'impersonation', 'deleted_at', 'expires_at', 'remaining_uses',
- 'extra'],
- )
-
- self.expand(32)
-
- self.assertTableColumns(
- trust_table_name,
- ['id', 'trustor_user_id', 'trustee_user_id', 'project_id',
- 'impersonation', 'deleted_at', 'expires_at', 'expires_at_int',
- 'remaining_uses', 'extra'],
- )
-
- # Create Trust
- trust_table = sqlalchemy.Table('trust', self.metadata,
- autoload=True)
- trust_1_data = {
- 'id': uuid.uuid4().hex,
- 'trustor_user_id': uuid.uuid4().hex,
- 'trustee_user_id': uuid.uuid4().hex,
- 'project_id': uuid.uuid4().hex,
- 'impersonation': False,
- 'expires_at': datetime.datetime.utcnow()
- }
- trust_2_data = {
- 'id': uuid.uuid4().hex,
- 'trustor_user_id': uuid.uuid4().hex,
- 'trustee_user_id': uuid.uuid4().hex,
- 'project_id': uuid.uuid4().hex,
- 'impersonation': False,
- 'expires_at': None
- }
- trust_table.insert().values(trust_1_data).execute()
- trust_table.insert().values(trust_2_data).execute()
-
- self.migrate(32)
- self.contract(32)
- trusts = list(trust_table.select().execute())
-
- epoch = datetime.datetime.fromtimestamp(0, tz=pytz.UTC)
-
- for t in trusts:
- if t.expires_at:
- e = t.expires_at.replace(tzinfo=pytz.UTC) - epoch
- e = e.total_seconds()
- self.assertEqual(t.expires_at_int, int(e * 1000000))
-
- def test_migration_033_adds_limits_table(self):
- self.expand(32)
- self.migrate(32)
- self.contract(32)
-
- registered_limit_table_name = 'registered_limit'
- limit_table_name = 'limit'
- self.assertTableDoesNotExist(registered_limit_table_name)
- self.assertTableDoesNotExist(limit_table_name)
-
- self.expand(33)
- self.migrate(33)
- self.contract(33)
-
- self.assertTableExists(registered_limit_table_name)
- self.assertTableColumns(
- registered_limit_table_name,
- ['id', 'service_id', 'resource_name', 'region_id', 'default_limit']
- )
- self.assertTableExists(limit_table_name)
- self.assertTableColumns(
- limit_table_name,
- ['id', 'project_id', 'service_id', 'resource_name', 'region_id',
- 'resource_limit']
- )
-
- 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)
-
- # Insert one registered limit
- registered_limit_table = sqlalchemy.Table(
- registered_limit_table_name, self.metadata, autoload=True)
- registered_limit = {
- 'id': uuid.uuid4().hex,
- 'service_id': service_id,
- 'region_id': 'RegionOne',
- 'resource_name': 'cores',
- 'default_limit': 10
- }
- registered_limit_table.insert().values(registered_limit).execute()
-
- # It will raise error if insert another one with same service_id,
- # region_id and resource name.
- registered_limit['id'] = uuid.uuid4().hex
- registered_limit['default_limit'] = 20
- self.assertRaises(db_exception.DBDuplicateEntry,
- registered_limit_table.insert().values(
- registered_limit).execute)
-
- # Insert one without region_id
- registered_limit_without_region = {
- 'id': uuid.uuid4().hex,
- 'service_id': service_id,
- 'resource_name': 'cores',
- 'default_limit': 10
- }
- registered_limit_table.insert().values(
- registered_limit_without_region).execute()
-
- # It will not raise error if insert another one with same service_id
- # and resource_name but the region_id is None. Because that
- # UniqueConstraint doesn't work if one of the columns is None. This
- # should be controlled at the Manager layer to forbid this behavior.
- registered_limit_without_region['id'] = uuid.uuid4().hex
- registered_limit_table.insert().values(
- registered_limit_without_region).execute()
-
- # Insert one limit
- limit_table = sqlalchemy.Table(
- limit_table_name, self.metadata, autoload=True)
- 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()
-
- # Insert another one with the same project_id, service_id, region_id
- # and resource_name, then raise error.
- limit['id'] = uuid.uuid4().hex
- limit['resource_limit'] = 10
- self.assertRaises(db_exception.DBDuplicateEntry,
- limit_table.insert().values(limit).execute)
-
- # Insert one without region_id
- limit_without_region = {
- 'id': uuid.uuid4().hex,
- 'project_id': project_id,
- 'service_id': service_id,
- 'resource_name': 'cores',
- 'resource_limit': 5
- }
- limit_table.insert().values(limit_without_region).execute()
-
- def test_migration_034_adds_application_credential_table(self):
- self.expand(33)
- self.migrate(33)
- self.contract(33)
-
- application_credential_table_name = 'application_credential'
- self.assertTableDoesNotExist(application_credential_table_name)
- application_credential_role_table_name = 'application_credential_role'
- self.assertTableDoesNotExist(application_credential_role_table_name)
-
- self.expand(34)
- self.migrate(34)
- self.contract(34)
-
- self.assertTableExists(application_credential_table_name)
- self.assertTableColumns(
- application_credential_table_name,
- ['internal_id', 'id', 'name', 'secret_hash',
- 'description', 'user_id', 'project_id', 'expires_at',
- 'allow_application_credential_creation']
- )
- if self.engine.name == 'mysql':
- self.assertTrue(self.does_index_exist(
- 'application_credential', 'duplicate_app_cred_constraint'))
- else:
- self.assertTrue(self.does_constraint_exist(
- 'application_credential', 'duplicate_app_cred_constraint'))
- self.assertTableExists(application_credential_role_table_name)
- self.assertTableColumns(
- application_credential_role_table_name,
- ['application_credential_id', 'role_id']
- )
-
- app_cred_table = sqlalchemy.Table(
- application_credential_table_name, self.metadata, autoload=True
- )
- app_cred_role_table = sqlalchemy.Table(
- application_credential_role_table_name,
- self.metadata, autoload=True
- )
- self.assertTrue(self.does_fk_exist('application_credential_role',
- 'application_credential_id'))
-
- expires_at = datetime.datetime.utcnow().replace(tzinfo=pytz.UTC)
- epoch = datetime.datetime.fromtimestamp(0, tz=pytz.UTC)
- expires_at_int = (expires_at - epoch).total_seconds()
- app_cred = {
- 'internal_id': 1,
- 'id': uuid.uuid4().hex,
- 'name': uuid.uuid4().hex,
- 'secret_hash': uuid.uuid4().hex,
- 'description': uuid.uuid4().hex,
- 'user_id': uuid.uuid4().hex,
- 'project_id': uuid.uuid4().hex,
- 'expires_at': expires_at_int,
- 'allow_application_credential_creation': False
- }
- app_cred_table.insert().values(app_cred).execute()
-
- # Exercise unique constraint
- dup_app_cred = {
- 'internal_id': 2,
- 'id': uuid.uuid4().hex,
- 'name': app_cred['name'],
- 'secret_hash': uuid.uuid4().hex,
- 'user_id': app_cred['user_id'],
- 'project_id': uuid.uuid4().hex
- }
- insert = app_cred_table.insert().values(dup_app_cred)
- self.assertRaises(db_exception.DBDuplicateEntry,
- insert.execute)
-
- role_rel = {
- 'application_credential_id': app_cred['internal_id'],
- 'role_id': uuid.uuid4().hex
- }
- app_cred_role_table.insert().values(role_rel).execute()
-
- # Exercise role table primary keys
- insert = app_cred_role_table.insert().values(role_rel)
- self.assertRaises(db_exception.DBDuplicateEntry, insert.execute)
-
- def test_migration_035_add_system_column_to_credential_table(self):
- self.expand(34)
- self.migrate(34)
- self.contract(34)
-
- application_credential_table_name = 'application_credential'
- self.assertTableExists(application_credential_table_name)
- self.assertTableColumns(
- application_credential_table_name,
- ['internal_id', 'id', 'name', 'secret_hash',
- 'description', 'user_id', 'project_id', 'expires_at',
- 'allow_application_credential_creation']
- )
-
- self.expand(35)
- self.migrate(35)
- self.contract(35)
-
- self.assertTableColumns(
- application_credential_table_name,
- ['internal_id', 'id', 'name', 'secret_hash',
- 'description', 'user_id', 'project_id', 'system', 'expires_at',
- 'allow_application_credential_creation']
- )
-
- application_credential_table = sqlalchemy.Table(
- application_credential_table_name, self.metadata, autoload=True
- )
-
- # Test that we can insert an application credential without project_id
- # defined.
- expires_at = datetime.datetime.utcnow().replace(tzinfo=pytz.UTC)
- epoch = datetime.datetime.fromtimestamp(0, tz=pytz.UTC)
- expires_at_int = (expires_at - epoch).total_seconds()
- app_cred = {
- 'internal_id': 1,
- 'id': uuid.uuid4().hex,
- 'name': uuid.uuid4().hex,
- 'secret_hash': uuid.uuid4().hex,
- 'description': uuid.uuid4().hex,
- 'user_id': uuid.uuid4().hex,
- 'system': uuid.uuid4().hex,
- 'expires_at': expires_at_int,
- 'allow_application_credential_creation': False
- }
- application_credential_table.insert().values(app_cred).execute()
-
- # Test that we can insert an application credential with a project_id
- # and without system defined.
- app_cred = {
- 'internal_id': 2,
- 'id': uuid.uuid4().hex,
- 'name': uuid.uuid4().hex,
- 'secret_hash': uuid.uuid4().hex,
- 'description': uuid.uuid4().hex,
- 'user_id': uuid.uuid4().hex,
- 'project_id': uuid.uuid4().hex,
- 'expires_at': expires_at_int,
- 'allow_application_credential_creation': False
- }
- application_credential_table.insert().values(app_cred).execute()
-
- # Test that we can create an application credential without a project
- # or a system defined. Technically, project_id and system should be
- # mutually exclusive, which will be handled by the application and not
- # the data layer.
- app_cred = {
- 'internal_id': 3,
- 'id': uuid.uuid4().hex,
- 'name': uuid.uuid4().hex,
- 'secret_hash': uuid.uuid4().hex,
- 'description': uuid.uuid4().hex,
- 'user_id': uuid.uuid4().hex,
- 'expires_at': expires_at_int,
- 'allow_application_credential_creation': False
- }
- application_credential_table.insert().values(app_cred).execute()
-
- def test_migration_036_rename_application_credentials_column(self):
- self.expand(35)
- self.migrate(35)
- self.contract(35)
-
- application_credential_table_name = 'application_credential'
- application_credential_role_table_name = 'application_credential_role'
-
- self.expand(36)
- self.migrate(36)
- self.contract(36)
-
- self.assertTableColumns(
- application_credential_table_name,
- ['internal_id', 'id', 'name', 'secret_hash',
- 'description', 'user_id', 'project_id', 'system', 'expires_at',
- 'unrestricted']
- )
-
- application_credential_table = sqlalchemy.Table(
- application_credential_table_name, self.metadata, autoload=True
- )
- app_cred_role_table = sqlalchemy.Table(
- application_credential_role_table_name,
- self.metadata, autoload=True
- )
-
- # Test that the new column works
- app_cred = {
- 'internal_id': 1,
- 'id': uuid.uuid4().hex,
- 'name': uuid.uuid4().hex,
- 'secret_hash': uuid.uuid4().hex,
- 'description': uuid.uuid4().hex,
- 'user_id': uuid.uuid4().hex,
- 'system': uuid.uuid4().hex,
- 'expires_at': None,
- 'unrestricted': False
- }
- application_credential_table.insert().values(app_cred).execute()
- role_rel = {
- 'application_credential_id': app_cred['internal_id'],
- 'role_id': uuid.uuid4().hex
- }
- app_cred_role_table.insert().values(role_rel).execute()
-
- def test_migration_037_remove_service_and_region_fk_for_registered_limit(
- self):
- self.expand(37)
- self.migrate(37)
- self.contract(37)
-
- registered_limit_table_name = 'registered_limit'
- registered_limit_table = sqlalchemy.Table(registered_limit_table_name,
- self.metadata, autoload=True)
- self.assertEqual(set([]), registered_limit_table.foreign_keys)
-
- 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)
- self.contract(52)
-
- role_table_name = 'role'
- self.assertTableColumns(
- role_table_name,
- ['id', 'name', 'domain_id', 'extra']
- )
-
- self.expand(53)
- self.migrate(53)
- self.contract(53)
-
- self.assertTableColumns(
- role_table_name,
- ['id', 'name', 'domain_id', 'extra', 'description']
- )
-
- role_table = sqlalchemy.Table(
- role_table_name, self.metadata, autoload=True
- )
-
- role = {
- 'id': uuid.uuid4().hex,
- 'name': "test",
- 'domain_id': resource_base.NULL_DOMAIN_ID,
- 'description': "This is a string"
- }
- role_table.insert().values(role).execute()
-
- role_without_description = {
- 'id': uuid.uuid4().hex,
- 'name': "test1",
- 'domain_id': resource_base.NULL_DOMAIN_ID
- }
- role_table.insert().values(role_without_description).execute()
-
- def test_migration_054_drop_old_password_column(self):
- self.expand(53)
- self.migrate(53)
- self.contract(53)
-
- password_table = 'password'
- self.assertTableColumns(
- password_table,
- ['id', 'local_user_id', 'password', 'password_hash',
- 'self_service', 'created_at_int', 'created_at', 'expires_at_int',
- 'expires_at']
- )
-
- self.expand(54)
- self.migrate(54)
- self.contract(54)
-
- self.assertTableColumns(
- password_table,
- ['id', 'local_user_id', 'password_hash', 'self_service',
- 'created_at_int', 'created_at', 'expires_at_int', 'expires_at']
- )
-
- def test_migration_055_add_domain_to_limit(self):
- self.expand(54)
- self.migrate(54)
- self.contract(54)
-
- limit_table_name = 'limit'
- limit_table = sqlalchemy.Table(limit_table_name, self.metadata,
- autoload=True)
- self.assertFalse(hasattr(limit_table.c, 'domain_id'))
-
- self.expand(55)
- self.migrate(55)
- self.contract(55)
-
- self.assertTableColumns(
- limit_table_name,
- ['id', 'project_id', 'service_id', 'region_id', 'resource_name',
- 'resource_limit', 'description', 'internal_id',
- 'registered_limit_id', 'domain_id'])
- self.assertTrue(limit_table.c.project_id.nullable)
-
- def test_migration_056_add_application_credential_access_rules(self):
- self.expand(55)
- self.migrate(55)
- self.contract(55)
-
- self.assertTableDoesNotExist('access_rule')
- self.assertTableDoesNotExist('application_credential_access_rule')
-
- self.expand(56)
- self.migrate(56)
- self.contract(56)
-
- self.assertTableExists('access_rule')
- self.assertTableExists('application_credential_access_rule')
- self.assertTableColumns(
- 'access_rule',
- ['id', 'service', 'path', 'method']
- )
- self.assertTableColumns(
- 'application_credential_access_rule',
- ['application_credential_id', 'access_rule_id']
- )
- self.assertTrue(self.does_fk_exist(
- 'application_credential_access_rule', 'application_credential_id'))
- self.assertTrue(self.does_fk_exist(
- 'application_credential_access_rule', 'access_rule_id'))
-
- app_cred_table = sqlalchemy.Table(
- 'application_credential', self.metadata, autoload=True
- )
- access_rule_table = sqlalchemy.Table(
- 'access_rule', self.metadata, autoload=True
- )
- app_cred_access_rule_table = sqlalchemy.Table(
- 'application_credential_access_rule',
- self.metadata, autoload=True
- )
- app_cred = {
- 'internal_id': 1,
- 'id': uuid.uuid4().hex,
- 'name': uuid.uuid4().hex,
- 'secret_hash': uuid.uuid4().hex,
- 'user_id': uuid.uuid4().hex,
- 'project_id': uuid.uuid4().hex
- }
- app_cred_table.insert().values(app_cred).execute()
- access_rule = {
- 'id': 1,
- 'service': uuid.uuid4().hex,
- 'path': '/v2.1/servers',
- 'method': 'GET'
- }
- access_rule_table.insert().values(access_rule).execute()
- app_cred_access_rule_rel = {
- 'application_credential_id': app_cred['internal_id'],
- 'access_rule_id': access_rule['id']
- }
- app_cred_access_rule_table.insert().values(
- app_cred_access_rule_rel).execute()
-
- def test_migration_062_add_trust_redelegation(self):
- # ensure initial schema
- self.expand(61)
- self.migrate(61)
- self.contract(61)
- self.assertTableColumns('trust', ['id',
- 'trustor_user_id',
- 'trustee_user_id',
- 'project_id',
- 'impersonation',
- 'expires_at',
- 'expires_at_int',
- 'remaining_uses',
- 'deleted_at',
- 'extra'])
-
- # fixture
- trust = {
- 'id': uuid.uuid4().hex,
- 'trustor_user_id': uuid.uuid4().hex,
- 'trustee_user_id': uuid.uuid4().hex,
- 'project_id': uuid.uuid4().hex,
- 'impersonation': True,
- 'expires_at': datetime.datetime.now(),
- 'remaining_uses': 10,
- 'deleted_at': datetime.datetime.now(),
- 'redelegated_trust_id': uuid.uuid4().hex,
- 'redelegation_count': 3,
- 'other': uuid.uuid4().hex
- }
- old_trust = trust.copy()
- old_extra = {
- 'redelegated_trust_id': old_trust.pop('redelegated_trust_id'),
- 'redelegation_count': old_trust.pop('redelegation_count'),
- 'other': old_trust.pop('other')
- }
- old_trust['extra'] = jsonutils.dumps(old_extra)
- # load fixture
- session = self.sessionmaker()
- self.insert_dict(session, 'trust', old_trust)
-
- # ensure redelegation data is in extra
- stored_trust = list(
- session.execute(self.load_table('trust').select())
- )[0]
- self.assertDictEqual({
- 'redelegated_trust_id': trust['redelegated_trust_id'],
- 'redelegation_count': trust['redelegation_count'],
- 'other': trust['other']},
- jsonutils.loads(stored_trust.extra))
-
- # upgrade and ensure expected schema
- self.expand(62)
- self.migrate(62)
- self.contract(62)
- self.assertTableColumns('trust', ['id',
- 'trustor_user_id',
- 'trustee_user_id',
- 'project_id',
- 'impersonation',
- 'expires_at',
- 'expires_at_int',
- 'remaining_uses',
- 'deleted_at',
- 'redelegated_trust_id',
- 'redelegation_count',
- 'extra'])
-
- trust_table = sqlalchemy.Table('trust', self.metadata, autoload=True)
- self.assertTrue(trust_table.c.redelegated_trust_id.nullable)
- self.assertTrue(trust_table.c.redelegation_count.nullable)
-
- # test target data layout
- upgraded_trust = list(
- session.execute(self.load_table('trust').select())
- )[0]
- self.assertDictEqual({'other': trust['other']},
- jsonutils.loads(upgraded_trust.extra))
- self.assertEqual(trust['redelegated_trust_id'],
- upgraded_trust.redelegated_trust_id)
- self.assertEqual(trust['redelegation_count'],
- upgraded_trust.redelegation_count)
-
- def test_migration_063_drop_limit_columns(self):
- self.expand(62)
- self.migrate(62)
- self.contract(62)
-
- limit_table = 'limit'
- self.assertTableColumns(
- limit_table,
- ['id', 'project_id', 'service_id', 'region_id', 'resource_name',
- 'resource_limit', 'description', 'internal_id',
- 'registered_limit_id', 'domain_id'])
-
- self.expand(63)
- self.migrate(63)
- self.contract(63)
-
- self.assertTableColumns(
- limit_table,
- ['id', 'project_id', 'resource_limit', 'description',
- 'internal_id', 'registered_limit_id', 'domain_id'])
-
- def test_migration_064_add_remote_id_attribute_federation_protocol(self):
- self.expand(63)
- self.migrate(63)
- self.contract(63)
-
- federation_protocol_table_name = 'federation_protocol'
- self.assertTableColumns(
- federation_protocol_table_name,
- ['id', 'idp_id', 'mapping_id']
- )
-
- self.expand(64)
- self.migrate(64)
- self.contract(64)
-
- self.assertTableColumns(
- federation_protocol_table_name,
- ['id', 'idp_id', 'mapping_id', 'remote_id_attribute']
- )
-
- def test_migration_065_add_user_external_id_to_access_rule(self):
- self.expand(64)
- self.migrate(64)
- self.contract(64)
-
- self.assertTableColumns(
- 'access_rule',
- ['id', 'service', 'path', 'method']
- )
-
- self.expand(65)
- self.migrate(65)
- self.contract(65)
-
- self.assertTableColumns(
- 'access_rule',
- ['id', 'external_id', 'user_id', 'service', 'path', 'method']
+ self.expand(upgrades.INITIAL_VERSION + 1)
+ self.migrate(upgrades.INITIAL_VERSION + 1)
+ self.assertRaises(
+ db_exception.DBMigrationError,
+ self.contract,
+ upgrades.INITIAL_VERSION + 2,
)
- self.assertTrue(self.does_index_exist('access_rule', 'external_id'))
- self.assertTrue(self.does_index_exist('access_rule', 'user_id'))
- self.assertTrue(self.does_unique_constraint_exist(
- 'access_rule', 'external_id'))
- self.assertTrue(self.does_unique_constraint_exist(
- 'access_rule', ['user_id', 'service', 'path', 'method']))
-
- def test_migration_066_add_role_and_project_options_tables(self):
- self.expand(65)
- self.migrate(65)
- self.contract(65)
-
- role_option = 'role_option'
- project_option = 'project_option'
- self.assertTableDoesNotExist(role_option)
- self.assertTableDoesNotExist(project_option)
-
- self.expand(66)
- self.migrate(66)
- self.contract(66)
-
- self.assertTableColumns(
- project_option,
- ['project_id', 'option_id', 'option_value'])
-
- self.assertTableColumns(
- role_option,
- ['role_id', 'option_id', 'option_value'])
-
- def test_migration_072_drop_domain_id_fk(self):
- self.expand(71)
- self.migrate(71)
- self.contract(71)
-
- self.assertTrue(self.does_fk_exist('user', 'domain_id'))
- self.assertTrue(self.does_fk_exist('identity_provider', 'domain_id'))
-
- self.expand(72)
- self.migrate(72)
- self.contract(72)
-
- self.assertFalse(self.does_fk_exist('user', 'domain_id'))
- self.assertFalse(self.does_fk_exist('identity_provider', 'domain_id'))
-
- def test_migration_073_contract_expiring_group_membership(self):
- self.expand(72)
- self.migrate(72)
- self.contract(72)
-
- membership_table = 'expiring_user_group_membership'
- self.assertTableDoesNotExist(membership_table)
-
- idp_table = 'identity_provider'
- self.assertTableColumns(
- idp_table,
- ['id', 'domain_id', 'enabled', 'description'])
-
- self.expand(73)
- self.migrate(73)
- self.contract(73)
-
- self.assertTableColumns(
- membership_table,
- ['user_id', 'group_id', 'idp_id', 'last_verified'])
- self.assertTableColumns(
- idp_table,
- ['id', 'domain_id', 'enabled', 'description',
- 'authorization_ttl'])
def test_migration_079_expand_update_local_id_limit(self):
self.expand(78)
@@ -3522,14 +636,6 @@ class FullMigration(SqlMigrateBase, unit.TestCase):
class MySQLOpportunisticFullMigration(FullMigration):
FIXTURE = db_fixtures.MySQLOpportunisticFixture
- def test_migration_003_migrate_unencrypted_credentials(self):
- self.skip_test_overrides('skipped to update u-c for PyMySql version'
- 'to 0.10.0')
-
- 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
diff --git a/lower-constraints.txt b/lower-constraints.txt
index 3ceae8a1d..71f497fbd 100644
--- a/lower-constraints.txt
+++ b/lower-constraints.txt
@@ -32,7 +32,7 @@ oslo.i18n==3.15.3
oslo.log==3.44.0
oslo.messaging==5.29.0
oslo.middleware==3.31.0
-oslo.policy==3.7.0
+oslo.policy==3.10.0
oslo.serialization==2.18.0
oslo.upgradecheck==1.3.0
oslo.utils==3.33.0
diff --git a/releasenotes/notes/change_min_pool_retry_max-f5e7c8d315401426.yaml b/releasenotes/notes/change_min_pool_retry_max-f5e7c8d315401426.yaml
new file mode 100644
index 000000000..44109b144
--- /dev/null
+++ b/releasenotes/notes/change_min_pool_retry_max-f5e7c8d315401426.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ Change the min value of pool_retry_max to 1. Setting this value to 0
+ caused the pool to fail before connecting to ldap, always raising
+ MaxConnectionReachedError.
diff --git a/releasenotes/notes/remove-db_sync-extension-opt-2ab1f29340281215.yaml b/releasenotes/notes/remove-db_sync-extension-opt-2ab1f29340281215.yaml
new file mode 100644
index 000000000..249a16ec3
--- /dev/null
+++ b/releasenotes/notes/remove-db_sync-extension-opt-2ab1f29340281215.yaml
@@ -0,0 +1,6 @@
+---
+upgrade:
+ - |
+ The ``--extension`` option of ``keystone-manage db_sync`` has been
+ deprecated since 10.0.0 (Newton) and raised an error when provided. It
+ has now been removed entirely.
diff --git a/releasenotes/notes/remove-legacy-migrations-647f60019c8dd9e8.yaml b/releasenotes/notes/remove-legacy-migrations-647f60019c8dd9e8.yaml
new file mode 100644
index 000000000..11f33886b
--- /dev/null
+++ b/releasenotes/notes/remove-legacy-migrations-647f60019c8dd9e8.yaml
@@ -0,0 +1,7 @@
+---
+upgrade:
+ - |
+ The legacy migrations that existed before the split into separate expand
+ schema, contract schema, and data migration migration have now been
+ removed. These have been deprecated since 10.0.0 (Newton). This should
+ have no user-facing impact.
diff --git a/requirements.txt b/requirements.txt
index f77c24665..c7e4605f3 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -23,7 +23,7 @@ oslo.db>=6.0.0 # Apache-2.0
oslo.i18n>=3.15.3 # Apache-2.0
oslo.log>=3.44.0 # Apache-2.0
oslo.middleware>=3.31.0 # Apache-2.0
-oslo.policy>=3.7.0 # Apache-2.0
+oslo.policy>=3.10.0 # Apache-2.0
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
oslo.upgradecheck>=1.3.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0
diff --git a/tools/generate-schemas b/tools/generate-schemas
new file mode 100755
index 000000000..59fbb226c
--- /dev/null
+++ b/tools/generate-schemas
@@ -0,0 +1,134 @@
+#!/usr/bin/env bash
+#
+# Script to generate schemas for the various versions.
+#
+# Some setup is required, similar to the opportunistic tests.
+#
+# MySQL ->
+#
+# $ mysql -uroot
+# MariaDB [(none)]> CREATE DATABASE keystone
+# MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'password';
+# MariaDB [(none)]> quit;
+#
+# Postgres ->
+#
+# $ sudo -u postgres psql
+# postgres=# create user keystone with createdb login password 'password';
+# postgres=# create database keystone with owner keystone;
+# postgres=# quit;
+#
+# Note that you may also have to configure 'pg_hba.conf' to use password-based
+# auth instead of "ident", if you haven't done so already. You can locate this
+# with 'locate pg_hba.conf'. More details at
+# https://ubuntu.com/server/docs/databases-postgresql
+
+set -o xtrace
+set -e
+
+source .tox/py38/bin/activate
+
+INIT_VERSION=$(ls -1 keystone/common/sql/legacy_migrations/expand_repo/versions/ | head -1 | awk -F_ '{print $1}' | sed 's/^0*//')
+INIT_VERSION=$(($INIT_VERSION-1))
+
+echo "Detected init version of $INIT_VERSION"
+
+mkdir -p /tmp/keystone-schemas
+rm -f "/tmp/keystone-schemas/$INIT_VERSION-*.sql"
+
+#
+# functions
+#
+
+function sync () {
+ DB_URL=$1
+
+ python keystone/common/sql/legacy_migrations/expand_repo/manage.py version_control \
+ --database "$DB_URL" \
+ --version "$INIT_VERSION" \
+ --repository keystone/common/sql/legacy_migrations/expand_repo/
+ python keystone/common/sql/legacy_migrations/data_migration_repo/manage.py version_control \
+ --database "$DB_URL" \
+ --version "$INIT_VERSION" \
+ --repository keystone/common/sql/legacy_migrations/data_migration_repo/
+ python keystone/common/sql/legacy_migrations/contract_repo/manage.py version_control \
+ --database "$DB_URL" \
+ --version "$INIT_VERSION" \
+ --repository keystone/common/sql/legacy_migrations/contract_repo/
+
+ python keystone/common/sql/legacy_migrations/expand_repo/manage.py upgrade \
+ --database "$DB_URL" \
+ --repository keystone/common/sql/legacy_migrations/expand_repo/
+ python keystone/common/sql/legacy_migrations/data_migration_repo/manage.py upgrade \
+ --database "$DB_URL" \
+ --repository keystone/common/sql/legacy_migrations/data_migration_repo/
+ python keystone/common/sql/legacy_migrations/contract_repo/manage.py upgrade \
+ --database "$DB_URL" \
+ --repository keystone/common/sql/legacy_migrations/contract_repo/
+}
+
+#
+# sqlite
+#
+
+# cleanup from previous runs
+
+rm -f /tmp/keystone.db
+
+# sync schema
+
+sync 'sqlite:////tmp/keystone.db'
+
+# dump the schema
+
+sqlite3 /tmp/keystone.db << EOF
+.output "/tmp/keystone-schemas/${INIT_VERSION}-sqlite.sql"
+.schema
+.quit
+EOF
+
+rm -f /tmp/keystone.db
+
+#
+# mysql
+#
+
+# cleanup from previous runs
+
+mysql -u keystone -ppassword << EOF
+DROP DATABASE IF EXISTS keystone;
+CREATE DATABASE keystone;
+EOF
+
+# sync schema
+
+sync 'mysql+pymysql://keystone:password@localhost/keystone'
+
+# dump the schema
+
+mysqldump --no-data --skip-comments -u keystone -ppassword \
+ keystone > "/tmp/keystone-schemas/${INIT_VERSION}-mysql.sql"
+
+mysql -u keystone -ppassword << EOF
+DROP DATABASE IF EXISTS keystone;
+EOF
+
+#
+# postgres
+#
+
+# cleanup from previous runs
+
+sudo -u postgres dropdb --if-exists keystone
+sudo -u postgres createdb --owner=keystone keystone
+
+# sync to initial version
+
+sync 'postgresql://keystone:password@localhost/keystone'
+
+# dump the schema
+
+pg_dump postgresql://keystone:password@localhost/keystone \
+ --schema-only > "/tmp/keystone-schemas/${INIT_VERSION}-postgres.sql"
+
+sudo -u postgres dropdb --if-exists keystone
diff --git a/tox.ini b/tox.ini
index a0ef4070d..402cea905 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,16 +1,16 @@
[tox]
minversion = 3.2.0
-skipsdist = True
envlist = py37,pep8,api-ref,docs,genconfig,genpolicy,releasenotes,protection
+ignore_basepython_conflict = true
[testenv]
usedevelop = True
basepython = python3
setenv = VIRTUAL_ENV={envdir}
-deps = -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
- -r{toxinidir}/test-requirements.txt
- -r{toxinidir}/requirements.txt
- .[ldap,memcache,mongodb]
+deps =
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -r{toxinidir}/test-requirements.txt
+ .[ldap,memcache,mongodb]
commands =
find keystone -type f -name "*.pyc" -delete
stestr run {posargs}
@@ -19,16 +19,10 @@ whitelist_externals =
find
passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY PBR_VERSION
-[testenv:api-ref]
-deps = -r{toxinidir}/doc/requirements.txt
-commands =
- bash -c "rm -rf api-ref/build"
- sphinx-build -W -b html -d api-ref/build/doctrees api-ref/source api-ref/build/html
-
[testenv:pep8]
deps =
- .[bandit]
- {[testenv]deps}
+ .[bandit]
+ {[testenv]deps}
commands =
flake8 --ignore=D100,D101,D102,D103,D104,E305,E402,W503,W504,W605
# Run bash8 during pep8 runs to ensure violations are caught by
@@ -39,6 +33,7 @@ commands =
[testenv:fast8]
envdir = {toxworkdir}/pep8
+deps = {[testenv:pep8]deps}
commands =
{toxinidir}/tools/fast8.sh
passenv = FAST8_NUM_COMMITS
@@ -46,9 +41,10 @@ passenv = FAST8_NUM_COMMITS
[testenv:bandit]
# NOTE(browne): This is required for the integration test job of the bandit
# project. Please do not remove.
-deps = -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
- -r{toxinidir}/requirements.txt
- .[bandit]
+deps =
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -r{toxinidir}/requirements.txt
+ .[bandit]
commands = bandit -r keystone -x 'keystone/tests/*'
[testenv:cover]
@@ -87,7 +83,9 @@ passenv =
KSTEST_PROJECT_ID
[testenv:functional]
-deps = -r{toxinidir}/test-requirements.txt
+deps =
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -r{toxinidir}/test-requirements.txt
setenv = OS_TEST_PATH=./keystone/tests/functional
commands =
find keystone -type f -name "*.pyc" -delete
@@ -108,7 +106,6 @@ passenv =
filename= *.py,keystone-manage
show-source = true
enable-extensions = H203,H904
-
# D100: Missing docstring in public module
# D101: Missing docstring in public class
# D102: Missing docstring in public method
@@ -120,7 +117,6 @@ enable-extensions = H203,H904
# W503: line break before binary operator
# W504 line break after binary operator
ignore = D100,D101,D102,D103,D104,D203,E402,W503,W504
-
exclude=.venv,.git,.tox,build,dist,*lib/python*,*egg,tools,vendor,.update-venv,*.ini,*.po,*.pot
max-complexity=24
@@ -154,9 +150,17 @@ commands =
make -C doc/build/pdf
[testenv:releasenotes]
-deps = -r{toxinidir}/doc/requirements.txt
+envdir = {toxworkdir}/docs
+deps = {[testenv:docs]deps}
commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
+[testenv:api-ref]
+envdir = {toxworkdir}/docs
+deps = {[testenv:docs]deps}
+commands =
+ bash -c "rm -rf api-ref/build"
+ sphinx-build -W -b html -d api-ref/build/doctrees api-ref/source api-ref/build/html
+
[testenv:genconfig]
commands = oslo-config-generator --config-file=config-generator/keystone.conf