Use a consistent concept of tag liveness everywhere. Fix the tests.
This commit is contained in:
parent
90c0a9c1e0
commit
f32bd748e4
2 changed files with 58 additions and 54 deletions
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
|
Reference in a new issue