Use processed bool as key in introspection_data DB table

When using store_data=database with sqlalchemy, running introspection results
in a DBDuplicateEntry error.  This happens because the query when adding an
entry uses both the primary key (uuid) and the processed flag, but the
processed flag is not a key.  This change makes it a key so that both
unprocessed and processed data can be stored in the table.

Note - since the previous migration hasn't been released yet this fixes it
without creating a new one.

Change-Id: I052594d529ae363fce50b1726169d86583bb1439
Story: #2004992
Task: #29463
This commit is contained in:
Bob Fournier 2019-02-13 12:33:42 -05:00
parent 73cbfc744b
commit b76f84d4c1
3 changed files with 21 additions and 2 deletions

View File

@ -137,7 +137,7 @@ class RuleAction(Base):
class IntrospectionData(Base): class IntrospectionData(Base):
__tablename__ = 'introspection_data' __tablename__ = 'introspection_data'
uuid = Column(String(36), ForeignKey('nodes.uuid'), primary_key=True) uuid = Column(String(36), ForeignKey('nodes.uuid'), primary_key=True)
processed = Column(Boolean, default=False) processed = Column(Boolean, default=False, primary_key=True)
data = Column(db_types.JsonEncodedDict(mysql_as_long=True), data = Column(db_types.JsonEncodedDict(mysql_as_long=True),
nullable=True) nullable=True)

View File

@ -34,7 +34,7 @@ def upgrade():
'introspection_data', 'introspection_data',
sa.Column('uuid', sa.String(36), sa.ForeignKey('nodes.uuid'), sa.Column('uuid', sa.String(36), sa.ForeignKey('nodes.uuid'),
primary_key=True), primary_key=True),
sa.Column('processed', sa.Boolean, default=False), sa.Column('processed', sa.Boolean, default=False, primary_key=True),
sa.Column('data', db_types.JsonEncodedDict(mysql_as_long=True).impl, sa.Column('data', db_types.JsonEncodedDict(mysql_as_long=True).impl,
nullable=True), nullable=True),
mysql_ENGINE='InnoDB', mysql_ENGINE='InnoDB',

View File

@ -1285,3 +1285,22 @@ class TestIntrospectionDataDbStore(test_base.NodeTest):
def test_get_no_data_available(self): def test_get_no_data_available(self):
self.assertRaises(utils.IntrospectionDataNotFound, self.assertRaises(utils.IntrospectionDataNotFound,
node_cache.get_introspection_data, self.node.uuid) node_cache.get_introspection_data, self.node.uuid)
def test_store_proc_and_unproc(self):
unproc_data = {'s': 'value', 'b': True, 'i': 42}
node_cache.store_introspection_data(self.node.uuid,
unproc_data,
processed=False)
proc_data = {'foo': 'bar'}
node_cache.store_introspection_data(self.node.uuid,
proc_data,
processed=True)
stored_data = node_cache.get_introspection_data(self.node.uuid,
True)
self.assertEqual(stored_data, proc_data)
stored_data = node_cache.get_introspection_data(self.node.uuid,
False)
self.assertEqual(stored_data, unproc_data)