Support rolling back to revision 0

This patch set allows revision rollback functionality to work
with revision 0 in order to allow Deckhand to create a blank
revision (without any documents), without having to delete every
revision in the database (which is currently done here: [1] for
example). This is less than ideal as revision history is lost.
Instead, Deckhand should just support rolling back to revision 0
which simulates a blank slate (though in reality the previous
revision history is retained).

[1] 18ed6674d2/src/bin/shipyard_airflow/shipyard_airflow/control/helpers/configdocs_helper.py (L159)

Change-Id: Ic94b25ca15f88ba492e08c907d4a330aeecca810
This commit is contained in:
Felipe Monteiro 2018-08-16 22:18:40 +01:00
parent 5979f7f93a
commit ca1997ec5d
2 changed files with 45 additions and 8 deletions

View File

@ -510,20 +510,22 @@ def revision_get_latest(session=None):
:param session: Database session object.
:returns: Dictionary representation of latest revision.
:raises RevisionNotFound: if the latest revision was not found.
"""
session = session or get_session()
latest_revision = session.query(models.Revision)\
.order_by(models.Revision.created_at.desc())\
.first()
if not latest_revision:
raise errors.RevisionNotFound(revision_id='latest')
latest_revision = latest_revision.to_dict()
latest_revision['documents'] = _update_revision_history(
latest_revision['documents'])
if latest_revision:
latest_revision = latest_revision.to_dict()
latest_revision['documents'] = _update_revision_history(
latest_revision['documents'])
else:
# If the latest revision doesn't exist, assume an empty revision
# history and return a dummy revision instead for the purposes of
# revision rollback.
latest_revision = {'documents': [], 'id': 0}
return latest_revision
@ -976,7 +978,11 @@ def revision_rollback(revision_id, latest_revision, session=None):
LOG.debug('The revision being rolled back to is the current revision.'
'Expect no meaningful changes.')
orig_revision = revision_get(revision_id, session=session)
if revision_id == 0:
# Placeholder revision as revision_id=0 doesn't exist.
orig_revision = {'documents': []}
else:
orig_revision = revision_get(revision_id, session=session)
# A mechanism for determining whether a particular document has changed
# between revisions. Keyed with the document_id, the value is True if

View File

@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from deckhand import errors
from deckhand.tests import test_utils
from deckhand.tests.unit.db import base
@ -98,3 +99,33 @@ class TestRevisionRollback(base.TestDbBase):
key=lambda d: d['created_at']),
ignore=['created_at', 'updated_at', 'revision_id',
'orig_revision_id', 'id'])
def test_rollback_to_revision_0_creates_blank_slate(self):
"""Rolling back to revision 0 should create an empty revision."""
payload = base.DocumentFixture.get_minimal_multi_fixture(count=4)
bucket_name = test_utils.rand_name('bucket')
created_documents = self.create_documents(bucket_name, payload)
orig_revision_id = created_documents[0]['revision_id']
rollback_revision = self.rollback_revision(0)
rollback_documents = self.list_revision_documents(
rollback_revision['id'], include_history=False)
self.assertEqual(orig_revision_id + 1, rollback_revision['id'])
self.assertEmpty(rollback_documents)
def test_rollback_to_revision_0_with_empty_revision_history(self):
"""Validate that rolling back to revision_id 0 should work with
an empty revision history (zero existing revisions in the DB).
"""
rollback_revision = self.rollback_revision(0)
rollback_documents = self.list_revision_documents(
rollback_revision['id'], include_history=False)
self.assertEqual(1, rollback_revision['id'])
self.assertEmpty(rollback_documents)
class TestRevisionRollbackNegative(base.TestDbBase):
def test_rollback_to_missing_revision_raises_exc(self):
# revision_id=1 doesn't exist yet since we start from an empty DB.
self.assertRaises(errors.RevisionNotFound, self.rollback_revision, 1)