Add database migration for project tags
This change adds the SQL database migration for adding a new project_tag table that consists of an project_id and name. The project_id is the id of a project that the tag is mapped to and the name is the string value of the tag. Partially-Implements: bp project-tags Co-Authored-By: Pilla, Samuel (sp516w) <sp516w@att.com> Co-Authored-By: Tin Lam <tin@irrational.io> Change-Id: Ib3db74cb08e7fdec01d55d8988e0906948d80a32
This commit is contained in:
parent
400259f58a
commit
99ad40ef94
|
@ -0,0 +1,15 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# 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
|
|
@ -71,6 +71,7 @@ PrimaryKeyConstraint = sql.PrimaryKeyConstraint
|
|||
joinedload = sql.orm.joinedload
|
||||
# Suppress flake8's unused import warning for flag_modified:
|
||||
flag_modified = flag_modified
|
||||
Unicode = sql.Unicode
|
||||
|
||||
|
||||
def initialize():
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# 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
|
|
@ -0,0 +1,44 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# 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)
|
|
@ -2421,6 +2421,74 @@ class FullMigration(SqlMigrateBase, unit.TestCase):
|
|||
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()
|
||||
|
||||
|
||||
class MySQLOpportunisticFullMigration(FullMigration):
|
||||
FIXTURE = test_base.MySQLOpportunisticFixture
|
||||
|
|
Loading…
Reference in New Issue