Fixes failure when password is null

This patch allows the password column to be null which is the expected
behavior.

Note: We do have tests in place that should have caught this. However,
the SQL model for Password did not explicitly set the nullable column
attribute, so it defaulted to true, even though the migration set it to
false.

Closes-Bug: #1595819

Change-Id: I487072a5b1aeabebd1d2006781fa5dc568160ec5
This commit is contained in:
Ronald De Rose 2016-06-24 14:06:06 +00:00 committed by Ron De Rose
parent f6f4eb2df1
commit e04c561437
5 changed files with 41 additions and 4 deletions

View File

@ -0,0 +1,21 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# 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)

View File

@ -154,7 +154,7 @@ class Password(sql.ModelBase, sql.DictBase):
id = sql.Column(sql.Integer, primary_key=True)
local_user_id = sql.Column(sql.Integer, sql.ForeignKey('local_user.id',
ondelete='CASCADE'))
password = sql.Column(sql.String(128))
password = sql.Column(sql.String(128), nullable=True)
# created_at default set here to safe guard in case it gets missed
created_at = sql.Column(sql.DateTime, nullable=False,
default=datetime.datetime.utcnow)

View File

@ -234,7 +234,7 @@ class SqlIdentity(SqlTests,
with sql.session_for_read() as session:
new_user_ref = self.identity_api._get_user(session,
new_user_dict['id'])
self.assertFalse(new_user_ref.password)
self.assertIsNone(new_user_ref.password)
def test_update_user_with_null_password(self):
user_dict = unit.new_user_ref(
@ -247,7 +247,7 @@ class SqlIdentity(SqlTests,
with sql.session_for_read() as session:
new_user_ref = self.identity_api._get_user(session,
new_user_dict['id'])
self.assertFalse(new_user_ref.password)
self.assertIsNone(new_user_ref.password)
def test_delete_user_with_project_association(self):
user = unit.new_user_ref(domain_id=CONF.identity.default_domain_id)

View File

@ -134,7 +134,11 @@ class KeystoneMigrationsCheckers(test_migrations.WalkVersionsMixin):
# 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
102,
# Migration 106 simply allows the password column to be nullable.
# This change would not impact a rolling upgrade.
106
]
# NOTE(xek): We start requiring things be additive in Newton, so

View File

@ -1434,6 +1434,18 @@ class SqlUpgradeTests(SqlMigrateBase):
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.metadata.clear()
self.upgrade(106)
password_table = sqlalchemy.Table(password_table_name, self.metadata,
autoload=True)
self.assertTrue(password_table.c.password.nullable)
class MySQLOpportunisticUpgradeTestCase(SqlUpgradeTests):
FIXTURE = test_base.MySQLOpportunisticFixture