sql: Squash train migrations

Make the following changes to the new "initial" migrations.

- Add 'redelegated_trust_id' and 'redelegation_count' columns to
  'trust' table (062)
- Drop 'service_id', 'region_id', and 'resource_name' columns from
  'limit' table (063)
- Add 'remote_id_attribute' column to 'federation_protocol' table (064)
- Add 'external_id' and 'user_id' columns to 'access_rule' table (065)
- Add 'role_option' and 'project_option' tables (066)

Change-Id: Ifc71efb8609bc26ce998a9fa48b207abf8b9a38b
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2022-01-10 16:48:18 +00:00
parent 1639282e49
commit 10b67ba1f5
35 changed files with 75 additions and 804 deletions

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,15 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
def upgrade(migrate_engine):
pass

View File

@ -1,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()

View File

@ -1,15 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
def upgrade(migrate_engine):
pass

View File

@ -1,15 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
def upgrade(migrate_engine):
pass

View File

@ -1,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

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -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)

View File

@ -1,15 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
def upgrade(migrate_engine):
pass

View File

@ -1,15 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
def upgrade(migrate_engine):
pass

View File

@ -1,15 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# 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

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -1,18 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for Stein backports. Do not use this number for new
# Train work. New Train work starts after all the placeholders.
def upgrade(migrate_engine):
pass

View File

@ -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)

View File

@ -1,15 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
def upgrade(migrate_engine):
pass

View File

@ -1,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)

View File

@ -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()

View File

@ -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()

View File

@ -165,6 +165,7 @@ def upgrade(migrate_engine):
primary_key=True, primary_key=True,
), ),
sql.Column('mapping_id', sql.String(64), nullable=False), sql.Column('mapping_id', sql.String(64), nullable=False),
sql.Column('remote_id_attribute', sql.String(64)),
mysql_engine='InnoDB', mysql_engine='InnoDB',
mysql_charset='utf8', mysql_charset='utf8',
) )
@ -333,6 +334,24 @@ def upgrade(migrate_engine):
mysql_charset='utf8', mysql_charset='utf8',
) )
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' # NOTE(lamt) To allow tag name to be case sensitive for MySQL, the 'name'
# column needs to use collation, which is incompatible with Postgresql. # column needs to use collation, which is incompatible with Postgresql.
# Using unicode to mirror nova's server tag: # Using unicode to mirror nova's server tag:
@ -472,6 +491,24 @@ def upgrade(migrate_engine):
mysql_charset='utf8', 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',
)
service = sql.Table( service = sql.Table(
'service', 'service',
meta, meta,
@ -546,6 +583,16 @@ def upgrade(migrate_engine):
'expires_at_int', 'expires_at_int',
name='duplicate_trust_constraint_expanded', 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_engine='InnoDB',
mysql_charset='utf8', mysql_charset='utf8',
) )
@ -754,9 +801,6 @@ def upgrade(migrate_engine):
meta, meta,
sql.Column('id', sql.String(length=64), nullable=False), sql.Column('id', sql.String(length=64), nullable=False),
sql.Column('project_id', sql.String(64), nullable=True), sql.Column('project_id', sql.String(64), nullable=True),
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.Column('resource_limit', sql.Integer, nullable=False),
sql.Column('description', sql.Text), sql.Column('description', sql.Text),
sql.Column('internal_id', sql.Integer, primary_key=True), sql.Column('internal_id', sql.Integer, primary_key=True),
@ -823,6 +867,21 @@ def upgrade(migrate_engine):
sql.Column('service', sql.String(64)), sql.Column('service', sql.String(64)),
sql.Column('path', sql.String(128)), sql.Column('path', sql.String(128)),
sql.Column('method', sql.String(16)), 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_engine='InnoDB',
mysql_charset='utf8', mysql_charset='utf8',
) )
@ -857,8 +916,10 @@ def upgrade(migrate_engine):
group, group,
policy, policy,
project, project,
project_option,
project_tag, project_tag,
role, role,
role_option,
service, service,
token, token,
trust, trust,

View File

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

View File

@ -39,10 +39,8 @@ For further information, see `oslo.db documentation
all data will be lost. all data will be lost.
""" """
import datetime
import glob import glob
import os import os
import uuid
import fixtures import fixtures
from migrate.versioning import script from migrate.versioning import script
@ -51,7 +49,6 @@ from oslo_db.sqlalchemy import enginefacade
from oslo_db.sqlalchemy import test_fixtures as db_fixtures from oslo_db.sqlalchemy import test_fixtures as db_fixtures
from oslo_log import fixture as log_fixture from oslo_log import fixture as log_fixture
from oslo_log import log from oslo_log import log
from oslo_serialization import jsonutils
from oslotest import base as test_base from oslotest import base as test_base
import sqlalchemy.exc import sqlalchemy.exc
from sqlalchemy import inspect from sqlalchemy import inspect
@ -90,12 +87,18 @@ INITIAL_TABLE_STRUCTURE = {
'id', 'name', 'extra', 'description', 'enabled', 'domain_id', 'id', 'name', 'extra', 'description', 'enabled', 'domain_id',
'parent_id', 'is_domain', 'parent_id', 'is_domain',
], ],
'project_option': [
'project_id', 'option_id', 'option_value',
],
'project_tag': [ 'project_tag': [
'project_id', 'name', 'project_id', 'name',
], ],
'role': [ 'role': [
'id', 'name', 'extra', 'domain_id', 'description', 'id', 'name', 'extra', 'domain_id', 'description',
], ],
'role_option': [
'role_id', 'option_id', 'option_value',
],
'service': [ 'service': [
'id', 'type', 'extra', 'enabled', 'id', 'type', 'extra', 'enabled',
], ],
@ -105,7 +108,7 @@ INITIAL_TABLE_STRUCTURE = {
'trust': [ 'trust': [
'id', 'trustor_user_id', 'trustee_user_id', 'project_id', 'id', 'trustor_user_id', 'trustee_user_id', 'project_id',
'impersonation', 'deleted_at', 'expires_at', 'remaining_uses', 'extra', 'impersonation', 'deleted_at', 'expires_at', 'remaining_uses', 'extra',
'expires_at_int', 'expires_at_int', 'redelegated_trust_id', 'redelegation_count',
], ],
'trust_role': [ 'trust_role': [
'trust_id', 'role_id', 'trust_id', 'role_id',
@ -142,7 +145,7 @@ INITIAL_TABLE_STRUCTURE = {
'id', 'enabled', 'description', 'domain_id', 'id', 'enabled', 'description', 'domain_id',
], ],
'federation_protocol': [ 'federation_protocol': [
'id', 'idp_id', 'mapping_id', 'id', 'idp_id', 'mapping_id', 'remote_id_attribute',
], ],
'mapping': [ 'mapping': [
'id', 'rules', 'id', 'rules',
@ -204,8 +207,7 @@ INITIAL_TABLE_STRUCTURE = {
'default_limit', 'description', 'default_limit', 'description',
], ],
'limit': [ 'limit': [
'internal_id', 'id', 'project_id', 'service_id', 'region_id', 'internal_id', 'id', 'project_id', 'resource_limit', 'description',
'resource_name', 'resource_limit', 'description',
'registered_limit_id', 'domain_id', 'registered_limit_id', 'domain_id',
], ],
'application_credential': [ 'application_credential': [
@ -216,7 +218,7 @@ INITIAL_TABLE_STRUCTURE = {
'application_credential_id', 'role_id', 'application_credential_id', 'role_id',
], ],
'access_rule': [ 'access_rule': [
'id', 'service', 'path', 'method', 'id', 'service', 'path', 'method', 'external_id', 'user_id',
], ],
'application_credential_access_rule': [ 'application_credential_access_rule': [
'application_credential_id', 'access_rule_id', 'application_credential_id', 'access_rule_id',
@ -631,177 +633,6 @@ class FullMigration(MigrateBase, unit.TestCase):
upgrades.INITIAL_VERSION + 2, upgrades.INITIAL_VERSION + 2,
) )
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.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): def test_migration_072_drop_domain_id_fk(self):
self.expand(71) self.expand(71)
self.migrate(71) self.migrate(71)