From de84b4c081919405026d4d691c018e9403269418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A3=D1=81=D1=82=D1=8E=D0=B6=D0=B0=D0=BD=D0=B8=D0=BD=20?= =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=90=D0=BB=D0=B5=D0=BA=D1=81?= =?UTF-8?q?=D0=B0=D0=BD=D0=B4=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Wed, 23 Dec 2020 22:25:29 +0500 Subject: [PATCH] fix: cache tags for check manifests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Устюжанин Антон Александрович --- registry/storage/garbagecollect.go | 44 ++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/registry/storage/garbagecollect.go b/registry/storage/garbagecollect.go index 317c792da..729db57fd 100644 --- a/registry/storage/garbagecollect.go +++ b/registry/storage/garbagecollect.go @@ -27,6 +27,17 @@ type ManifestDel struct { Tags []string } +func getTags(manifest distribution.Descriptor, tagsDescriptors []distribution.Descriptor) []distribution.Descriptor { + var result []distribution.Descriptor + for _, tag := range tagsDescriptors { + if tag.Digest == manifest.Digest { + result = append(result, tag) + } + } + + return result +} + // MarkAndSweep performs a mark and sweep of registry data func MarkAndSweep(ctx context.Context, storageDriver driver.StorageDriver, registry distribution.Namespace, opts GCOpts) error { repositoryEnumerator, ok := registry.(distribution.RepositoryEnumerator) @@ -60,22 +71,39 @@ func MarkAndSweep(ctx context.Context, storageDriver driver.StorageDriver, regis return fmt.Errorf("unable to convert ManifestService into ManifestEnumerator") } + allTags, err := repository.Tags(ctx).All(ctx) + switch err.(type) { + case distribution.ErrRepositoryUnknown: + // This tag store has been initialized but not yet populated + break + case nil: + break + default: + return fmt.Errorf("failed to get tags for repository %s: %v", repoName, err) + } + + var tagsDescriptors []distribution.Descriptor + for _, tagName := range allTags { + tagDescriptor, err := repository.Tags(ctx).Get(ctx, tagName) + switch err.(type) { + case distribution.ErrTagUnknown: + continue + case nil: + break + default: + return fmt.Errorf("failed to get tag %s in repository %s: %v", tagName, repoName, err) + } + tagsDescriptors = append(tagsDescriptors, tagDescriptor) + } err = manifestEnumerator.Enumerate(ctx, func(dgst digest.Digest) error { if opts.RemoveUntagged { // fetch all tags where this manifest is the latest one - tags, err := repository.Tags(ctx).Lookup(ctx, distribution.Descriptor{Digest: dgst}) - if err != nil { - return fmt.Errorf("failed to retrieve tags for digest %v: %v", dgst, err) - } + tags := getTags(distribution.Descriptor{Digest: dgst}, tagsDescriptors) if len(tags) == 0 { emit("manifest eligible for deletion: %s", dgst) // fetch all tags from repository // all of these tags could contain manifest in history // which means that we need check (and delete) those references when deleting manifest - allTags, err := repository.Tags(ctx).All(ctx) - if err != nil { - return fmt.Errorf("failed to retrieve tags %v", err) - } manifestArr = append(manifestArr, ManifestDel{Name: repoName, Digest: dgst, Tags: allTags}) return nil }