Move oauth1 sql migrations to common

This is the most basic way to move the oauth1 migrations into
the keystone core migrations path. Check to see if the migration was
performed already via the extension and if so skip performing it again.

DocImpact: You should no longer run the migrations for the oauth extension

Change-Id: I8cea6748e7a5ae2b01320b4d6a9866e60ff2ea74
Implements: bp move-extensions
This commit is contained in:
Steve Martinelli 2015-10-15 02:59:43 -04:00 committed by Dave Chen
parent 78e256273a
commit a83b6b29e8
9 changed files with 138 additions and 157 deletions

View File

@ -0,0 +1,75 @@
# 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 migration_helpers
def upgrade(migrate_engine):
try:
extension_version = migration_helpers.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)

View File

@ -35,12 +35,12 @@ from keystone.i18n import _
CONF = cfg.CONF
DEFAULT_EXTENSIONS = ['endpoint_filter',
'oauth1',
'revoke',
]
MIGRATED_EXTENSIONS = ['endpoint_policy',
'federation',
'oauth1',
]

View File

@ -12,46 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import sqlalchemy as sql
from keystone import exception
def upgrade(migrate_engine):
# Upgrade operations go here. Don't create your own engine; bind
# migrate_engine to your metadata
meta = sql.MetaData()
meta.bind = migrate_engine
consumer_table = sql.Table(
'consumer',
meta,
sql.Column('id', sql.String(64), primary_key=True, nullable=False),
sql.Column('description', sql.String(64), nullable=False),
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('requested_roles', sql.Text(), nullable=False),
sql.Column('consumer_id', sql.String(64), 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('requested_roles', sql.Text(), nullable=False),
sql.Column('consumer_id', sql.String(64), nullable=False),
sql.Column('expires_at', sql.String(64), nullable=True))
access_token_table.create(migrate_engine, checkfirst=True)
raise exception.MigrationMovedFailure(extension='oauth1')

View File

@ -12,26 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import sqlalchemy as sql
from keystone.common.sql import migration_helpers
from keystone import exception
def upgrade(migrate_engine):
# Upgrade operations go here. Don't create your own engine; bind
# migrate_engine to your metadata
meta = sql.MetaData()
meta.bind = migrate_engine
consumer_table = sql.Table('consumer', meta, autoload=True)
request_token_table = sql.Table('request_token', meta, autoload=True)
access_token_table = sql.Table('access_token', meta, autoload=True)
constraints = [{'table': request_token_table,
'fk_column': 'consumer_id',
'ref_column': consumer_table.c.id},
{'table': access_token_table,
'fk_column': 'consumer_id',
'ref_column': consumer_table.c.id}]
if meta.bind != 'sqlite':
migration_helpers.add_constraints(constraints)
raise exception.MigrationMovedFailure(extension='oauth1')

View File

@ -12,11 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import sqlalchemy as sql
from keystone import exception
def upgrade(migrate_engine):
meta = sql.MetaData()
meta.bind = migrate_engine
user_table = sql.Table('consumer', meta, autoload=True)
user_table.c.description.alter(nullable=True)
raise exception.MigrationMovedFailure(extension='oauth1')

View File

@ -12,14 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import sqlalchemy as sql
from keystone import exception
def upgrade(migrate_engine):
meta = sql.MetaData()
meta.bind = migrate_engine
request_token_table = sql.Table('request_token', meta, autoload=True)
request_token_table.c.requested_roles.alter(nullable=True)
request_token_table.c.requested_roles.alter(name="role_ids")
access_token_table = sql.Table('access_token', meta, autoload=True)
access_token_table.c.requested_roles.alter(name="role_ids")
raise exception.MigrationMovedFailure(extension='oauth1')

View File

@ -13,23 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import sqlalchemy as sa
from keystone import exception
def upgrade(migrate_engine):
if migrate_engine.name == 'mysql':
meta = sa.MetaData(bind=migrate_engine)
table = sa.Table('access_token', meta, autoload=True)
# NOTE(i159): MySQL requires indexes on referencing columns, and those
# indexes create automatically. That those indexes will have different
# names, depending on version of MySQL used. We should make this naming
# consistent, by reverting index name to a consistent condition.
if any(i for i in table.indexes if
list(i.columns.keys()) == ['consumer_id']
and i.name != 'consumer_id'):
# NOTE(i159): by this action will be made re-creation of an index
# with the new name. This can be considered as renaming under the
# MySQL rules.
sa.Index('consumer_id', table.c.consumer_id).create()
raise exception.MigrationMovedFailure(extension='oauth1')

View File

@ -53,73 +53,13 @@ class SqlUpgradeOAuth1Extension(test_sql_upgrade.SqlMigrateBase):
def repo_package(self):
return oauth1
def upgrade(self, version):
super(SqlUpgradeOAuth1Extension, self).upgrade(
version, repository=self.repo_path)
def _assert_v1_3_tables(self):
self.assertTableColumns('consumer',
['id',
'description',
'secret',
'extra'])
self.assertTableColumns('request_token',
['id',
'request_secret',
'verifier',
'authorizing_user_id',
'requested_project_id',
'requested_roles',
'consumer_id',
'expires_at'])
self.assertTableColumns('access_token',
['id',
'access_secret',
'authorizing_user_id',
'project_id',
'requested_roles',
'consumer_id',
'expires_at'])
def _assert_v4_later_tables(self):
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'])
def test_upgrade(self):
self.assertTableDoesNotExist('consumer')
self.assertTableDoesNotExist('request_token')
self.assertTableDoesNotExist('access_token')
self.upgrade(1)
self._assert_v1_3_tables()
# NOTE(blk-u): Migrations 2-3 don't modify the tables in a way that we
# can easily test for.
self.upgrade(4)
self._assert_v4_later_tables()
self.upgrade(5)
self._assert_v4_later_tables()
# We have 5 oauth1 migrations, each should fail
for version in range(5):
v = version + 1
self.assertRaises(exception.MigrationMovedFailure,
self.upgrade, version=v,
repository=self.repo_path)
class EndpointFilterExtension(test_sql_upgrade.SqlMigrateBase):

View File

@ -623,6 +623,52 @@ class SqlUpgradeTests(SqlMigrateBase):
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(migration_helpers, '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_fixup_service_name_value_upgrade(self):
"""Update service name data from `extra` to empty string."""
def add_service(**extra_data):