From 28c30808719a806f1ec25e3430a7c7cd926d69f0 Mon Sep 17 00:00:00 2001 From: xificurC Date: Thu, 16 Aug 2018 16:07:37 +0200 Subject: [PATCH 1/2] adds --images-like - select images with regexp --- registry.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/registry.py b/registry.py index 0218528..f90033f 100755 --- a/registry.py +++ b/registry.py @@ -457,6 +457,13 @@ for more detail on garbage collection read here: nargs='+', metavar="IMAGE:[TAG]") + parser.add_argument( + '--images-like', + nargs='+', + help="List of images (regexp check) that will be handled", + required=False, + default=[]) + parser.add_argument( '--keep-tags', nargs='+', @@ -636,6 +643,17 @@ def get_newer_tags(registry, image_name, hours, tags_list): return newer_tags +def keep_images_like(image_list, regexp_list): + result = [] + regexp_list = list(map(re.compile, regexp_list)) + for image in image_list: + for regexp in regexp_list: + if re.search(regexp, image): + result.append(image) + break + return result + + def main_loop(args): global DEBUG @@ -685,6 +703,8 @@ def main_loop(args): image_list = args.image else: image_list = registry.list_images() + if args.images_like: + image_list = keep_images_like(image_list, args.images_like) # loop through registry's images # or through the ones given in command line From ca6e6af25f57e7316349f6545b44d0cad7994ffb Mon Sep 17 00:00:00 2001 From: xificurC Date: Thu, 16 Aug 2018 16:08:11 +0200 Subject: [PATCH 2/2] use ThreadPools to speed up searching and deleting --- registry.py | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/registry.py b/registry.py index f90033f..e49d706 100755 --- a/registry.py +++ b/registry.py @@ -13,6 +13,7 @@ import argparse import www_authenticate from datetime import timedelta, datetime as dt from getpass import getpass +from multiprocessing.pool import ThreadPool # this is a registry manipulator, can do following: # - list all images (including layers) @@ -550,11 +551,20 @@ def delete_tags( keep_tag_digests.append(digest) + def delete(tag): + print(" deleting tag {0}".format(tag)) + registry.delete_tag(image_name, tag, dry_run, keep_tag_digests) + + p = ThreadPool(4) + tasks = [] for tag in tags_to_delete: if tag in tags_to_keep: continue - - print(" deleting tag {0}".format(tag)) + tasks.append(p.apply_async(delete, args=(tag,))) + for task in tasks: + task.get() + p.close() + p.join() # deleting layers is disabled because # it also deletes shared layers @@ -563,8 +573,6 @@ def delete_tags( # layer_digest = layer['digest'] # registry.delete_tag_layer(image_name, layer_digest, dry_run) - registry.delete_tag(image_name, tag, dry_run, keep_tag_digests) - def get_tags_like(args_tags_like, tags_list): result = set() @@ -620,27 +628,30 @@ def delete_tags_by_age(registry, image_name, dry_run, hours, tags_to_keep): def get_newer_tags(registry, image_name, hours, tags_list): - newer_tags = [] - print('---------------------------------') - for tag in tags_list: + def newer(tag): image_config = registry.get_tag_config(image_name, tag) - if image_config == []: print("tag not found") - continue - + return None image_age = registry.get_image_age(image_name, image_config) - if image_age == []: print("timestamp not found") - continue - + return None if dt.strptime(image_age[:-4], "%Y-%m-%dT%H:%M:%S.%f") >= dt.now() - timedelta(hours=int(hours)): print("Keeping tag: {0} timestamp: {1}".format( tag, image_age)) - newer_tags.append(tag) + return tag + else: + print("Will delete tag: {0} timestamp: {1}".format( + tag, image_age)) + return None - return newer_tags + print('---------------------------------') + p = ThreadPool(4) + result = list(x for x in p.map(newer, tags_list) if x) + p.close() + p.join() + return result def keep_images_like(image_list, regexp_list):