From d69b2d34c20137eceffc3f5182541da4379f12b2 Mon Sep 17 00:00:00 2001 From: David Moreau Simard Date: Tue, 26 Jun 2018 16:50:52 -0400 Subject: [PATCH] Improve self-healing of missing playbook file references Another way the issue of a missing playbook file reference could manifest itself was if the file had been created but is_playbook would not have yet been set. Since we already have a unique constraint on file paths per playbook.id, we are able to recover from this as well. Change-Id: I271a6c3733972ee74ed5e709516c168a1ee66f55 --- ara/models.py | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/ara/models.py b/ara/models.py index d0a1556c..2ceacfdf 100644 --- a/ara/models.py +++ b/ara/models.py @@ -205,24 +205,38 @@ class Playbook(db.Model, TimedEntity): .filter(File.playbook_id == self.id) .filter(File.is_playbook)).one() except NoResultFound: # noqa - log.debug('NoResultFound for the file of playbook %s' % self.id) - # Doing this in the model is kind of ugly, sorry. - file = File( - path=self.path, - playbook=self, - is_playbook=True, + log.warn( + 'Recovering from NoResultFound file on playbook %s' % self.id ) - msg = 'Playbook file could not be recovered' - sha1 = content_sha1(msg) - content = FileContent.query.get(sha1) - if content is None: - content = FileContent(content=msg) - file.content = content - db.session.add(file) - db.session.commit() - log.warn('Recovered file reference for playbook %s' % self.id) - return file + # Option #1, file was created but is_playbook did not have time to + # be set + try: + playbook_file = (self.files + .filter(File.playbook_id == self.id) + .filter(File.path == self.path)).one() + playbook_file.is_playbook = True + log.warn('Recovered file reference for playbook %s' % self.id) + return playbook_file + except NoResultFound: # noqa + # Option #2: The playbook was created but was interrupted + # before the file was created. Create it. + playbook_file = File( + path=self.path, + playbook=self, + is_playbook=True + ) + msg = 'Playbook file could not be recovered' + sha1 = content_sha1(msg) + content = FileContent.query.get(sha1) + + if content is None: + content = FileContent(content=msg) + playbook_file.content = content + db.session.add(playbook_file) + db.session.commit() + log.warn('Recovered file reference for playbook %s' % self.id) + return playbook_file def __repr__(self): return '' % self.path