From 3c5b90d3e91fa8497605080711480110cd7fcce4 Mon Sep 17 00:00:00 2001 From: Koen Wilde Date: Tue, 17 Dec 2019 17:02:50 +0100 Subject: [PATCH 1/2] Always keep tags passed in `--keep-tags` Fixes #84. --- registry.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/registry.py b/registry.py index dbc82d1..1d3ed8c 100755 --- a/registry.py +++ b/registry.py @@ -811,9 +811,11 @@ def main_loop(args): print(" layer: {0}".format( layer['blobSum'])) - # add tags to "tags_to_keep" list, if we have regexp "tags_to_keep" - # entries or a number of hours for "keep_by_hours": + # add tags to "tags_to_keep" list if we have regexp "tags_to_keep" + # entries, a number of hours for "keep_by_hours" or if the user + # explicitly specified tags to always keep. keep_tags = [] + keep_tags.extend(args.keep_tags) if args.keep_tags_like: keep_tags.extend(get_tags_like(args.keep_tags_like, tags_list)) if args.keep_by_hours: @@ -842,7 +844,6 @@ def main_loop(args): # delete tags by age in hours if args.delete_by_hours: - keep_tags.extend(args.keep_tags) delete_tags_by_age(registry, image_name, args.dry_run, args.delete_by_hours, keep_tags) From 5d2e1a62922727d6ae53a3414690106bedd4d373 Mon Sep 17 00:00:00 2001 From: Koen Wilde Date: Wed, 18 Dec 2019 14:26:38 +0100 Subject: [PATCH 2/2] Add test for `keep-tags` --- registry.py | 1 + test.py | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/registry.py b/registry.py index 1d3ed8c..b0a24a2 100755 --- a/registry.py +++ b/registry.py @@ -838,6 +838,7 @@ def main_loop(args): tag for tag in tags_list if tag not in tags_list_to_delete] keep_tags.extend(tags_list_to_keep) + keep_tags.sort() # Make order deterministic for testing delete_tags( registry, image_name, args.dry_run, tags_list_to_delete, keep_tags) diff --git a/test.py b/test.py index ce3f757..861b318 100644 --- a/test.py +++ b/test.py @@ -853,6 +853,32 @@ class TestKeepImagesLike(unittest.TestCase): keep_images_like_patched.assert_not_called() +class TestKeepTags(unittest.TestCase): + @staticmethod + def create_mock_registry(host, login, no_validate_ssl, digest_method="HEAD"): + r = Registry._create(host, login, no_validate_ssl, digest_method) + r.http = MockRequests() + r.list_images = MagicMock(return_value=['a']) + r.list_tags = MagicMock(return_value=['1', '2', '3', '4', '5', '6', '7']) + return r + + # We store the actual mock registry here so we can later compare it in + # `assert_called_with()`. + mock_registry = create_mock_registry.__func__('localhost:8989', None, True) + + def return_mock_registry(self, host, login, no_validate_ssl, digest_method="HEAD"): + return TestKeepTags.mock_registry + + @patch('registry.Registry.create', return_mock_registry) + @patch('registry.get_auth_schemes') # called in main_loop, turn to noop + @patch('registry.delete_tags') + def test_keep_tags(self, delete_tags_patched, get_auth_schemes_patched): + # Check if delete_tags is called from main_loop (directly or indirectly + # through delete_tags_by_age) with `keep_tags` set to the tags we want to keep. + main_loop(parse_args(('--delete', '--num', '5', '-r', 'localhost:8989', '--keep-tags', '1'))) + delete_tags_patched.assert_called_with(TestKeepTags.mock_registry, 'a', False, ['1', '2'], ['1', '3', '4', '5', '6', '7']) + + class TestArgParser(unittest.TestCase): def test_no_args(self):