Garbage collect repositories on push and on tag deletion.
This commit is contained in:
parent
732ce83795
commit
ef68982728
3 changed files with 38 additions and 16 deletions
|
@ -973,6 +973,39 @@ def delete_tag_and_images(namespace_name, repository_name, tag_name):
|
|||
store.remove(repository_path)
|
||||
|
||||
|
||||
def garbage_collect_repository(namespace_name, repository_name):
|
||||
# Get a list of all images used by tags in the repository
|
||||
tag_query = (RepositoryTag
|
||||
.select(RepositoryTag, Image)
|
||||
.join(Image)
|
||||
.switch(RepositoryTag)
|
||||
.join(Repository)
|
||||
.where(Repository.name == repository_name,
|
||||
Repository.namespace == namespace_name))
|
||||
|
||||
referenced_anscestors = set()
|
||||
for tag in tag_query:
|
||||
ancestor_list = [int(img) for img in tag.image.ancestors.split('/')[1:-1]]
|
||||
referenced_anscestors = referenced_anscestors.union(set(ancestor_list))
|
||||
referenced_anscestors.add(tag.image.id)
|
||||
|
||||
all_repo_images = get_repository_images(namespace_name, repository_name)
|
||||
all_images = {int(img.id):img for img in all_repo_images}
|
||||
to_remove = set(all_images.keys()).difference(referenced_anscestors)
|
||||
|
||||
logger.info('Cleaning up unreferenced images: %s', to_remove)
|
||||
|
||||
for image_id_to_remove in to_remove:
|
||||
image_to_remove = all_images[image_id_to_remove]
|
||||
image_path = store.image_path(namespace_name, repository_name,
|
||||
image_to_remove.docker_image_id)
|
||||
logger.debug('Recursively deleting image path: %s' % image_path)
|
||||
image_to_remove.delete_instance()
|
||||
store.remove(image_path)
|
||||
|
||||
return len(to_remove)
|
||||
|
||||
|
||||
def get_tag_image(namespace_name, repository_name, tag_name):
|
||||
joined = Image.select().join(RepositoryTag).join(Repository)
|
||||
fetched = list(joined.where(Repository.name == repository_name,
|
||||
|
|
|
@ -222,6 +222,8 @@ def update_images(namespace, repository):
|
|||
updated_tags[image['Tag']] = image['id']
|
||||
model.set_image_checksum(image['id'], repo, image['checksum'])
|
||||
|
||||
num_removed = model.garbage_collect_repository(namespace, repository)
|
||||
|
||||
# Generate a job for each webhook that has been added to this repo
|
||||
webhooks = model.list_webhooks(namespace, repository)
|
||||
for webhook in webhooks:
|
||||
|
@ -237,7 +239,8 @@ def update_images(namespace, repository):
|
|||
'homepage': 'https://quay.io/repository/%s' % repo_string,
|
||||
'visibility': repo.visibility.name,
|
||||
'updated_tags': updated_tags,
|
||||
'pushed_image_count': len(image_with_checksums),
|
||||
'pushed_image_count': len(image_with_checksums),
|
||||
'pruned_image_count': num_removed,
|
||||
}
|
||||
webhook_queue.put(json.dumps(webhook_data))
|
||||
|
||||
|
|
|
@ -73,21 +73,7 @@ def delete_tag(namespace, repository, tag):
|
|||
|
||||
if permission.can():
|
||||
model.delete_tag(namespace, repository, tag)
|
||||
|
||||
return make_response('Deleted', 204)
|
||||
|
||||
abort(403)
|
||||
|
||||
|
||||
@tags.route('/repositories/<path:repository>/tags',
|
||||
methods=['DELETE'])
|
||||
@process_auth
|
||||
@parse_repository_name
|
||||
def delete_repository_tags(namespace, repository):
|
||||
permission = ModifyRepositoryPermission(namespace, repository)
|
||||
|
||||
if permission.can():
|
||||
model.delete_all_repository_tags(namespace, repository)
|
||||
model.garbage_collect_repository(namespace, repository)
|
||||
|
||||
return make_response('Deleted', 204)
|
||||
|
||||
|
|
Reference in a new issue