Use a consistent concept of tag liveness everywhere. Fix the tests.

This commit is contained in:
Jake Moshenko 2015-02-11 15:02:50 -05:00
parent 90c0a9c1e0
commit f32bd748e4
2 changed files with 58 additions and 54 deletions

View file

@ -1530,15 +1530,20 @@ def get_repository_images(namespace_name, repository_name):
return _get_repository_images_base(namespace_name, repository_name, lambda q: q)
def _tag_alive(query):
return query.where((RepositoryTag.lifetime_end >> None) |
(RepositoryTag.lifetime_end > datetime.utcnow()))
def list_repository_tags(namespace_name, repository_name):
return (RepositoryTag
return _tag_alive(RepositoryTag
.select(RepositoryTag, Image)
.join(Repository)
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
.switch(RepositoryTag)
.join(Image)
.where(Repository.name == repository_name, Namespace.username == namespace_name,
RepositoryTag.lifetime_end >> None))
.where(Repository.name == repository_name,
Namespace.username == namespace_name))
def _garbage_collect_tags(namespace_name, repository_name):
@ -1688,7 +1693,7 @@ def _garbage_collect_storage(storage_id_whitelist):
def get_tag_image(namespace_name, repository_name, tag_name):
def limit_to_tag(query):
return (query
return _tag_alive(query
.switch(Image)
.join(RepositoryTag)
.where(RepositoryTag.name == tag_name))
@ -1744,8 +1749,10 @@ def create_or_update_tag(namespace_name, repository_name, tag_name,
try:
# When we move a tag, we really end the timeline of the old one and create a new one
tag = RepositoryTag.get(RepositoryTag.repository == repo, RepositoryTag.name == tag_name,
RepositoryTag.lifetime_end >> None)
query = _tag_alive(RepositoryTag
.select()
.where(RepositoryTag.repository == repo, RepositoryTag.name == tag_name))
tag = query.get()
tag.lifetime_end = now
tag.save()
except RepositoryTag.DoesNotExist:
@ -1760,12 +1767,13 @@ def create_or_update_tag(namespace_name, repository_name, tag_name,
def delete_tag(namespace_name, repository_name, tag_name):
with config.app_config['DB_TRANSACTION_FACTORY'](db):
try:
query = (RepositoryTag
query = _tag_alive(RepositoryTag
.select(RepositoryTag, Repository)
.join(Repository)
.join(Namespace, on=(Repository.namespace_user == Namespace.id))
.where(Repository.name == repository_name, Namespace.username == namespace_name,
RepositoryTag.name == tag_name, RepositoryTag.lifetime_end >> None))
.where(Repository.name == repository_name,
Namespace.username == namespace_name,
RepositoryTag.name == tag_name))
found = db_for_update(query).get()
except RepositoryTag.DoesNotExist:

View file

@ -1,8 +1,5 @@
import unittest
import json as py_json
from flask import url_for
from endpoints.api import api
from app import app, storage
from initdb import setup_database_for_testing, finished_database_for_testing
from data import model, database
@ -14,12 +11,16 @@ REPO = 'somerepo'
class TestGarbageColection(unittest.TestCase):
def setUp(self):
self._old_tm_expiration = app.config['TIME_MACHINE_DELTA_SECONDS']
app.config['TIME_MACHINE_DELTA_SECONDS'] = 0
setup_database_for_testing(self)
self.app = app.test_client()
self.ctx = app.test_request_context()
self.ctx.__enter__()
def tearDown(self):
app.config['TIME_MACHINE_DELTA_SECONDS'] = self._old_tm_expiration
finished_database_for_testing(self)
self.ctx.__exit__(True, None, None)
@ -77,19 +78,21 @@ class TestGarbageColection(unittest.TestCase):
model.garbage_collect_repository(repository.namespace_user.username, repository.name)
def moveTag(self, repository, tag, docker_image_id):
model.create_or_update_tag(repository.namespace_user.username, repository.name, tag, docker_image_id)
model.create_or_update_tag(repository.namespace_user.username, repository.name, tag,
docker_image_id)
model.garbage_collect_repository(repository.namespace_user.username, repository.name)
def assertNotDeleted(self, repository, *args):
for docker_image_id in args:
self.assertTrue(bool(model.get_image_by_id(repository.namespace_user.username, repository.name, docker_image_id)))
self.assertTrue(bool(model.get_image_by_id(repository.namespace_user.username,
repository.name, docker_image_id)))
def assertDeleted(self, repository, *args):
for docker_image_id in args:
try:
# Verify the image is missing when accessed by the repository.
model.get_image_by_id(repository.namespace_user.username, repository.name, docker_image_id)
except model.DataModelException as ex:
except model.DataModelException:
return
self.fail('Expected image %s to be deleted' % docker_image_id)
@ -158,8 +161,7 @@ class TestGarbageColection(unittest.TestCase):
""" Repository has multiple tags with shared images. Selectively deleting the tags, and
verifying at each step.
"""
repository = self.createRepository(
latest = ['i1', 'i2', 'i3'],
repository = self.createRepository(latest=['i1', 'i2', 'i3'],
other=['i1', 'f1', 'f2'],
third=['t1', 't2', 't3'],
fourth=['i1', 'f1'])
@ -197,17 +199,11 @@ class TestGarbageColection(unittest.TestCase):
self.assertDeleted(repository, 'i1')
def test_empty_gc(self):
repository = self.createRepository(
latest = ['i1', 'i2', 'i3'],
other = ['i1', 'f1', 'f2'],
third = ['t1', 't2', 't3'],
fourth = ['i1', 'f1'])
repository = self.createRepository(latest=['i1', 'i2', 'i3'], other=['i1', 'f1', 'f2'],
third=['t1', 't2', 't3'], fourth=['i1', 'f1'])
self.gcNow(repository)
self.assertNotDeleted(repository, 'i1', 'i2', 'i3', 't1', 't2', 't3', 'f1', 'f2')
def test_gc_storage_empty(self):
model._garbage_collect_storage(set())
if __name__ == '__main__':
unittest.main()