fix(storage): do not open/download blobs when validating manifests (#1566)

when pushing manifests, zot will validate blobs (layers + config blob) are
present in repo, currently it opens(in case of filesystem storage) or download(
in case of cloud storage) each blob.

fixed that by adding a new method ImageStore.CheckBlobPresence() on storage
to check blobs presence without checking the cache like ImageStore.CheckBlob() method does.

Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
This commit is contained in:
peusebiu
2023-07-06 20:33:36 +03:00
committed by GitHub
parent f3aa855405
commit 5494a1b8d6
9 changed files with 136 additions and 18 deletions
+28 -9
View File
@@ -1087,7 +1087,11 @@ func (is *ImageStoreLocal) BlobPath(repo string, digest godigest.Digest) string
return path.Join(is.rootDir, repo, "blobs", digest.Algorithm().String(), digest.Encoded())
}
// CheckBlob verifies a blob and returns true if the blob is correct.
/*
CheckBlob verifies a blob and returns true if the blob is correct
If the blob is not found but it's found in cache then it will be copied over.
*/
func (is *ImageStoreLocal) CheckBlob(repo string, digest godigest.Digest) (bool, int64, error) {
var lockLatency time.Time
@@ -1095,8 +1099,6 @@ func (is *ImageStoreLocal) CheckBlob(repo string, digest godigest.Digest) (bool,
return false, -1, err
}
blobPath := is.BlobPath(repo, digest)
if is.dedupe && fmt.Sprintf("%v", is.cache) != fmt.Sprintf("%v", nil) {
is.Lock(&lockLatency)
defer is.Unlock(&lockLatency)
@@ -1105,14 +1107,13 @@ func (is *ImageStoreLocal) CheckBlob(repo string, digest godigest.Digest) (bool,
defer is.RUnlock(&lockLatency)
}
binfo, err := os.Stat(blobPath)
if err == nil {
is.log.Debug().Str("blob path", blobPath).Msg("blob path found")
return true, binfo.Size(), nil
if ok, size, err := is.StatBlob(repo, digest); err == nil || ok {
return true, size, nil
}
is.log.Debug().Err(err).Str("blob", blobPath).Msg("failed to find blob, searching it in cache")
blobPath := is.BlobPath(repo, digest)
is.log.Debug().Str("blob", blobPath).Msg("failed to find blob, searching it in cache")
// Check blobs in cache
dstRecord, err := is.checkCacheBlob(digest)
@@ -1135,6 +1136,24 @@ func (is *ImageStoreLocal) CheckBlob(repo string, digest godigest.Digest) (bool,
return true, blobSize, nil
}
// StatBlob verifies if a blob is present inside a repository. The caller function SHOULD lock from outside.
func (is *ImageStoreLocal) StatBlob(repo string, digest godigest.Digest) (bool, int64, error) {
if err := digest.Validate(); err != nil {
return false, -1, err
}
blobPath := is.BlobPath(repo, digest)
binfo, err := os.Stat(blobPath)
if err != nil {
is.log.Debug().Str("blob path", blobPath).Msg("failed to find blob")
return false, -1, zerr.ErrBlobNotFound
}
return true, binfo.Size(), nil
}
func (is *ImageStoreLocal) checkCacheBlob(digest godigest.Digest) (string, error) {
if err := digest.Validate(); err != nil {
return "", err
+8
View File
@@ -2191,10 +2191,18 @@ func TestGarbageCollect(t *testing.T) {
So(err, ShouldNotBeNil)
So(hasBlob, ShouldEqual, false)
hasBlob, _, err = imgStore.StatBlob(repoName, odigest)
So(err, ShouldNotBeNil)
So(hasBlob, ShouldEqual, false)
hasBlob, _, err = imgStore.CheckBlob(repoName, bdigest)
So(err, ShouldBeNil)
So(hasBlob, ShouldEqual, true)
hasBlob, _, err = imgStore.StatBlob(repoName, bdigest)
So(err, ShouldBeNil)
So(hasBlob, ShouldEqual, true)
// sleep so orphan blob can be GC'ed
time.Sleep(5 * time.Second)