From 8cfb3f4fe88dd5911592225c3981a552bc57f022 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Thu, 20 Sep 2018 15:49:20 -0400 Subject: [PATCH] Add interface function for deleting tags pointing to a manifest --- data/registry_model/interface.py | 10 +++++++++- data/registry_model/registry_pre_oci_model.py | 15 +++++++++++++++ data/registry_model/test/test_pre_oci_model.py | 13 +++++++++++-- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/data/registry_model/interface.py b/data/registry_model/interface.py index 748a8bcc0..3324f360d 100644 --- a/data/registry_model/interface.py +++ b/data/registry_model/interface.py @@ -82,7 +82,8 @@ class RegistryDataInterface(object): """ @abstractmethod - def list_repository_tag_history(self, repository_ref, page=1, size=100, specific_tag_name=None, active_tags_only=False): + def list_repository_tag_history(self, repository_ref, page=1, size=100, specific_tag_name=None, + active_tags_only=False): """ Returns the history of all tags in the repository (unless filtered). This includes tags that have been made in-active due to newer versions of those tags coming into service. @@ -110,6 +111,13 @@ class RegistryDataInterface(object): Deletes the latest, *active* tag with the given name in the repository. """ + @abstractmethod + def delete_tags_for_manifest(self, manifest): + """ + Deletes all tags pointing to the given manifest, making the manifest inaccessible for pulling. + Returns the tags deleted, if any. Returns None on error. + """ + @abstractmethod def change_repository_tag_expiration(self, tag, expiration_date): """ Sets the expiration date of the tag under the matching repository to that given. If the diff --git a/data/registry_model/registry_pre_oci_model.py b/data/registry_model/registry_pre_oci_model.py index bba644df3..d26c3af07 100644 --- a/data/registry_model/registry_pre_oci_model.py +++ b/data/registry_model/registry_pre_oci_model.py @@ -241,6 +241,21 @@ class PreOCIModel(RegistryDataInterface): deleted_tag = model.tag.delete_tag(repo.namespace_user.username, repo.name, tag_name) return Tag.for_repository_tag(deleted_tag) + def delete_tags_for_manifest(self, manifest): + """ + Deletes all tags pointing to the given manifest, making the manifest inaccessible for pulling. + Returns the tags deleted, if any. Returns None on error. + """ + try: + tagmanifest = database.TagManifest.get(id=manifest._db_id) + except database.TagManifest.DoesNotExist: + return None + + namespace_name = tagmanifest.tag.repository.namespace_user.username + repo_name = tagmanifest.tag.repository.name + tags = model.tag.delete_manifest_by_digest(namespace_name, repo_name, manifest.digest) + return [Tag.for_repository_tag(tag) for tag in tags] + def change_repository_tag_expiration(self, tag, expiration_date): """ Sets the expiration date of the tag under the matching repository to that given. If the expiration date is None, then the tag will not expire. Returns a tuple of the previous diff --git a/data/registry_model/test/test_pre_oci_model.py b/data/registry_model/test/test_pre_oci_model.py index cdeec9f45..5a1b5df15 100644 --- a/data/registry_model/test/test_pre_oci_model.py +++ b/data/registry_model/test/test_pre_oci_model.py @@ -209,7 +209,11 @@ def test_repository_tag_history(pre_oci_model): ('devtable', 'history'), ('buynlarge', 'orgrepo'), ]) -def test_delete_tags(repo_namespace, repo_name, pre_oci_model): +@pytest.mark.parametrize('via_manifest', [ + False, + True, +]) +def test_delete_tags(repo_namespace, repo_name, via_manifest, pre_oci_model): repository_ref = pre_oci_model.lookup_repository(repo_namespace, repo_name) tags = pre_oci_model.list_repository_tags(repository_ref) assert len(tags) @@ -220,7 +224,12 @@ def test_delete_tags(repo_namespace, repo_name, pre_oci_model): # Delete every tag in the repository. for tag in tags: - assert pre_oci_model.delete_tag(repository_ref, tag.name) + if via_manifest: + assert pre_oci_model.delete_tag(repository_ref, tag.name) + else: + manifest = pre_oci_model.get_manifest_for_tag(tag) + if manifest is not None: + assert pre_oci_model.delete_tags_for_manifest(manifest) # Make sure the tag is no longer found. with assert_query_count(1):