mirror of
https://github.com/project-zot/zot.git
synced 2026-06-17 12:58:02 +08:00
replace dependency of tagsInfo and repoInfo with just a list of manifests
- replace dependency of tagsInfo and repoInfo with a list of manifests, since it provides all the needed data - Mock tests added Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro>
This commit is contained in:
committed by
Ramkumar Chinchani
parent
86401de3b0
commit
a5ed99178e
@@ -33,6 +33,7 @@ type OciLayoutUtils interface {
|
|||||||
GetRepoLastUpdated(repo string) (TagInfo, error)
|
GetRepoLastUpdated(repo string) (TagInfo, error)
|
||||||
GetExpandedRepoInfo(name string) (RepoInfo, error)
|
GetExpandedRepoInfo(name string) (RepoInfo, error)
|
||||||
GetImageConfigInfo(repo string, manifestDigest godigest.Digest) (ispec.Image, error)
|
GetImageConfigInfo(repo string, manifestDigest godigest.Digest) (ispec.Image, error)
|
||||||
|
CheckManifestSignature(name string, digest godigest.Digest) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// OciLayoutInfo ...
|
// OciLayoutInfo ...
|
||||||
@@ -270,7 +271,7 @@ func (olu BaseOciLayoutUtils) checkCosignSignature(name string, digest godigest.
|
|||||||
// checks if manifest is signed or not
|
// checks if manifest is signed or not
|
||||||
// checks for notary or cosign signature
|
// checks for notary or cosign signature
|
||||||
// if cosign signature found it does not looks for notary signature.
|
// if cosign signature found it does not looks for notary signature.
|
||||||
func (olu BaseOciLayoutUtils) checkManifestSignature(name string, digest godigest.Digest) bool {
|
func (olu BaseOciLayoutUtils) CheckManifestSignature(name string, digest godigest.Digest) bool {
|
||||||
if !olu.checkCosignSignature(name, digest) {
|
if !olu.checkCosignSignature(name, digest) {
|
||||||
return olu.checkNotarySignature(name, digest)
|
return olu.checkNotarySignature(name, digest)
|
||||||
}
|
}
|
||||||
@@ -395,7 +396,7 @@ func (olu BaseOciLayoutUtils) GetExpandedRepoInfo(name string) (RepoInfo, error)
|
|||||||
return RepoInfo{}, err
|
return RepoInfo{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestInfo.IsSigned = olu.checkManifestSignature(name, man.Digest)
|
manifestInfo.IsSigned = olu.CheckManifestSignature(name, man.Digest)
|
||||||
|
|
||||||
manifestSize := olu.GetImageManifestSize(name, man.Digest)
|
manifestSize := olu.GetImageManifestSize(name, man.Digest)
|
||||||
olu.Log.Debug().Msg(fmt.Sprintf("%v", man.Digest))
|
olu.Log.Debug().Msg(fmt.Sprintf("%v", man.Digest))
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
"zotregistry.io/zot/pkg/log" // nolint: gci
|
"zotregistry.io/zot/pkg/log" // nolint: gci
|
||||||
|
|
||||||
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"zotregistry.io/zot/pkg/extensions/search/common"
|
"zotregistry.io/zot/pkg/extensions/search/common"
|
||||||
cveinfo "zotregistry.io/zot/pkg/extensions/search/cve"
|
cveinfo "zotregistry.io/zot/pkg/extensions/search/cve"
|
||||||
digestinfo "zotregistry.io/zot/pkg/extensions/search/digest"
|
digestinfo "zotregistry.io/zot/pkg/extensions/search/digest"
|
||||||
@@ -216,63 +217,57 @@ func globalSearch(repoList []string, name, tag string, olu common.OciLayoutUtils
|
|||||||
log.Error().Err(err).Msgf("can't find latest updated tag for repo: %s", repo)
|
log.Error().Err(err).Msgf("can't find latest updated tag for repo: %s", repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
tagsInfo, err := olu.GetImageTagsWithTimestamp(repo)
|
manifests, err := olu.GetImageManifests(repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msgf("can't get tags info for repo: %s", repo)
|
log.Error().Err(err).Msgf("can't get manifests for repo: %s", repo)
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
repoInfo, err := olu.GetExpandedRepoInfo(repo)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msgf("can't get repo info for repo: %s", repo)
|
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastUpdatedImageSummary gql_generated.ImageSummary
|
var lastUpdatedImageSummary gql_generated.ImageSummary
|
||||||
|
|
||||||
repoPlatforms := make([]*gql_generated.OsArch, 0, len(tagsInfo))
|
repoPlatforms := make([]*gql_generated.OsArch, 0, len(manifests))
|
||||||
repoVendors := make([]*string, 0, len(repoInfo.Manifests))
|
repoVendors := make([]*string, 0, len(manifests))
|
||||||
|
|
||||||
for i, manifest := range repoInfo.Manifests {
|
for i, manifest := range manifests {
|
||||||
imageLayersSize := int64(0)
|
imageLayersSize := int64(0)
|
||||||
|
|
||||||
imageBlobManifest, err := olu.GetImageBlobManifest(repo, godigest.Digest(tagsInfo[i].Digest))
|
manifestTag, ok := manifest.Annotations[ispec.AnnotationRefName]
|
||||||
if err != nil {
|
if !ok {
|
||||||
log.Error().Err(err).Msgf("can't read manifest for repo %s %s", repo, manifest.Tag)
|
log.Error().Msg("reference not found for this manifest")
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestSize := olu.GetImageManifestSize(repo, godigest.Digest(tagsInfo[i].Digest))
|
imageBlobManifest, err := olu.GetImageBlobManifest(repo, manifests[i].Digest)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msgf("can't read manifest for repo %s %s", repo, manifestTag)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
manifestSize := olu.GetImageManifestSize(repo, manifests[i].Digest)
|
||||||
configSize := imageBlobManifest.Config.Size
|
configSize := imageBlobManifest.Config.Size
|
||||||
|
|
||||||
repoBlob2Size[tagsInfo[i].Digest] = manifestSize
|
repoBlob2Size[manifests[i].Digest.String()] = manifestSize
|
||||||
repoBlob2Size[imageBlobManifest.Config.Digest.Hex] = configSize
|
repoBlob2Size[imageBlobManifest.Config.Digest.Hex] = configSize
|
||||||
|
|
||||||
for _, layer := range manifest.Layers {
|
for _, layer := range imageBlobManifest.Layers {
|
||||||
layer := layer
|
layer := layer
|
||||||
|
layerDigest := layer.Digest.String()
|
||||||
layerSize, err := strconv.ParseInt(layer.Size, 10, 64)
|
layerSizeStr := strconv.Itoa(int(layer.Size))
|
||||||
if err != nil {
|
repoBlob2Size[layer.Digest.String()] = layer.Size
|
||||||
log.Error().Err(err).Msg("invalid layer size")
|
imageLayersSize += layer.Size
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
repoBlob2Size[layer.Digest] = layerSize
|
|
||||||
imageLayersSize += layerSize
|
|
||||||
|
|
||||||
// if we have a tag we won't match a layer
|
// if we have a tag we won't match a layer
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if index := strings.Index(layer.Digest, name); index != -1 {
|
if index := strings.Index(layerDigest, name); index != -1 {
|
||||||
layers = append(layers, &gql_generated.LayerSummary{
|
layers = append(layers, &gql_generated.LayerSummary{
|
||||||
Digest: &layer.Digest,
|
Digest: &layerDigest,
|
||||||
Size: &layer.Size,
|
Size: &layerSizeStr,
|
||||||
Score: &index,
|
Score: &index,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -281,19 +276,18 @@ func globalSearch(repoList []string, name, tag string, olu common.OciLayoutUtils
|
|||||||
imageSize := imageLayersSize + manifestSize + configSize
|
imageSize := imageLayersSize + manifestSize + configSize
|
||||||
|
|
||||||
index := strings.Index(repo, name)
|
index := strings.Index(repo, name)
|
||||||
matchesTag := strings.HasPrefix(manifest.Tag, tag)
|
matchesTag := strings.HasPrefix(manifestTag, tag)
|
||||||
|
|
||||||
if index != -1 {
|
if index != -1 {
|
||||||
imageConfigInfo, err := olu.GetImageConfigInfo(repo, godigest.Digest(tagsInfo[i].Digest))
|
imageConfigInfo, err := olu.GetImageConfigInfo(repo, manifests[i].Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msgf("can't retrieve config info for the image %s %s", repo, manifest.Tag)
|
log.Error().Err(err).Msgf("can't retrieve config info for the image %s %s", repo, manifestTag)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
tag := manifest.Tag
|
|
||||||
size := strconv.Itoa(int(imageSize))
|
size := strconv.Itoa(int(imageSize))
|
||||||
isSigned := manifest.IsSigned
|
isSigned := olu.CheckManifestSignature(repo, manifests[i].Digest)
|
||||||
|
|
||||||
// update matching score
|
// update matching score
|
||||||
score := calculateImageMatchingScore(repo, index, matchesTag)
|
score := calculateImageMatchingScore(repo, index, matchesTag)
|
||||||
@@ -311,7 +305,7 @@ func globalSearch(repoList []string, name, tag string, olu common.OciLayoutUtils
|
|||||||
|
|
||||||
imageSummary := gql_generated.ImageSummary{
|
imageSummary := gql_generated.ImageSummary{
|
||||||
RepoName: &repo,
|
RepoName: &repo,
|
||||||
Tag: &tag,
|
Tag: &manifestTag,
|
||||||
LastUpdated: &lastUpdated,
|
LastUpdated: &lastUpdated,
|
||||||
IsSigned: &isSigned,
|
IsSigned: &isSigned,
|
||||||
Size: &size,
|
Size: &size,
|
||||||
@@ -320,7 +314,7 @@ func globalSearch(repoList []string, name, tag string, olu common.OciLayoutUtils
|
|||||||
Score: &score,
|
Score: &score,
|
||||||
}
|
}
|
||||||
|
|
||||||
if tagsInfo[i].Digest == lastUpdatedTag.Digest {
|
if manifests[i].Digest.String() == lastUpdatedTag.Digest {
|
||||||
lastUpdatedImageSummary = imageSummary
|
lastUpdatedImageSummary = imageSummary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
"zotregistry.io/zot/pkg/extensions/search/common"
|
"zotregistry.io/zot/pkg/extensions/search/common"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
@@ -36,49 +38,101 @@ func TestGlobalSearch(t *testing.T) {
|
|||||||
globalSearch([]string{"repo1"}, "name", "tag", mockOlum, log.NewLogger("debug", ""))
|
globalSearch([]string{"repo1"}, "name", "tag", mockOlum, log.NewLogger("debug", ""))
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("GetExpandedRepoInfo fail", func() {
|
Convey("GetImageManifests fail", func() {
|
||||||
mockOlum := mocks.OciLayoutUtilsMock{
|
mockOlum := mocks.OciLayoutUtilsMock{
|
||||||
GetExpandedRepoInfoFn: func(name string) (common.RepoInfo, error) {
|
GetImageManifestsFn: func(name string) ([]ispec.Descriptor, error) {
|
||||||
return common.RepoInfo{}, ErrTestError
|
return []ispec.Descriptor{}, ErrTestError
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
globalSearch([]string{"repo1"}, "name", "tag", mockOlum, log.NewLogger("debug", ""))
|
globalSearch([]string{"repo1"}, "name", "tag", mockOlum, log.NewLogger("debug", ""))
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Bad layer digest in manifest", func() {
|
Convey("Manifests given, bad image blob manifest", func() {
|
||||||
mockOlum := mocks.OciLayoutUtilsMock{
|
mockOlum := mocks.OciLayoutUtilsMock{
|
||||||
GetExpandedRepoInfoFn: func(name string) (common.RepoInfo, error) {
|
GetImageManifestsFn: func(name string) ([]ispec.Descriptor, error) {
|
||||||
return common.RepoInfo{
|
return []ispec.Descriptor{
|
||||||
Manifests: []common.Manifest{
|
{
|
||||||
{
|
Digest: "digest",
|
||||||
Tag: "latest",
|
Size: -1,
|
||||||
Layers: []common.Layer{
|
Annotations: map[string]string{
|
||||||
{
|
ispec.AnnotationRefName: "this is a bad format",
|
||||||
Size: "this is a bad size format",
|
|
||||||
Digest: "digest",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
GetImageManifestSizeFn: func(repo string, manifestDigest godigest.Digest) int64 {
|
GetImageBlobManifestFn: func(imageDir string, digest godigest.Digest) (v1.Manifest, error) {
|
||||||
return 100
|
return v1.Manifest{}, ErrTestError
|
||||||
},
|
},
|
||||||
GetImageConfigSizeFn: func(repo string, manifestDigest godigest.Digest) int64 {
|
}
|
||||||
return 100
|
globalSearch([]string{"repo1"}, "name", "tag", mockOlum, log.NewLogger("debug", ""))
|
||||||
},
|
})
|
||||||
GetImageTagsWithTimestampFn: func(repo string) ([]common.TagInfo, error) {
|
|
||||||
return []common.TagInfo{
|
Convey("Manifests given, no manifest tag", func() {
|
||||||
|
mockOlum := mocks.OciLayoutUtilsMock{
|
||||||
|
GetImageManifestsFn: func(name string) ([]ispec.Descriptor, error) {
|
||||||
|
return []ispec.Descriptor{
|
||||||
{
|
{
|
||||||
Name: "test",
|
Digest: "digest",
|
||||||
Digest: "test",
|
Size: -1,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
globalSearch([]string{"repo1"}, "name", "tag", mockOlum, log.NewLogger("debug", ""))
|
|
||||||
|
globalSearch([]string{"repo1"}, "test", "tag", mockOlum, log.NewLogger("debug", ""))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Global search success, no tag", func() {
|
||||||
|
mockOlum := mocks.OciLayoutUtilsMock{
|
||||||
|
GetRepoLastUpdatedFn: func(repo string) (common.TagInfo, error) {
|
||||||
|
return common.TagInfo{
|
||||||
|
Digest: "sha256:855b1556a45637abf05c63407437f6f305b4627c4361fb965a78e5731999c0c7",
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
GetImageManifestsFn: func(name string) ([]ispec.Descriptor, error) {
|
||||||
|
return []ispec.Descriptor{
|
||||||
|
{
|
||||||
|
Digest: "sha256:855b1556a45637abf05c63407437f6f305b4627c4361fb965a78e5731999c0c7",
|
||||||
|
Size: -1,
|
||||||
|
Annotations: map[string]string{
|
||||||
|
ispec.AnnotationRefName: "this is a bad format",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
GetImageBlobManifestFn: func(imageDir string, digest godigest.Digest) (v1.Manifest, error) {
|
||||||
|
return v1.Manifest{
|
||||||
|
Layers: []v1.Descriptor{
|
||||||
|
{
|
||||||
|
Size: 0,
|
||||||
|
Digest: v1.Hash{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
globalSearch([]string{"repo1/name"}, "name", "tag", mockOlum, log.NewLogger("debug", ""))
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Manifests given, bad image config info", func() {
|
||||||
|
mockOlum := mocks.OciLayoutUtilsMock{
|
||||||
|
GetImageManifestsFn: func(name string) ([]ispec.Descriptor, error) {
|
||||||
|
return []ispec.Descriptor{
|
||||||
|
{
|
||||||
|
Digest: "digest",
|
||||||
|
Size: -1,
|
||||||
|
Annotations: map[string]string{
|
||||||
|
ispec.AnnotationRefName: "this is a bad format",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
GetImageConfigInfoFn: func(repo string, manifestDigest godigest.Digest) (ispec.Image, error) {
|
||||||
|
return ispec.Image{}, ErrTestError
|
||||||
|
},
|
||||||
|
}
|
||||||
|
globalSearch([]string{"repo1/name"}, "name", "tag", mockOlum, log.NewLogger("debug", ""))
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Tag given, no layer match", func() {
|
Convey("Tag given, no layer match", func() {
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ type OciLayoutUtilsMock struct {
|
|||||||
GetRepoLastUpdatedFn func(repo string) (common.TagInfo, error)
|
GetRepoLastUpdatedFn func(repo string) (common.TagInfo, error)
|
||||||
GetExpandedRepoInfoFn func(name string) (common.RepoInfo, error)
|
GetExpandedRepoInfoFn func(name string) (common.RepoInfo, error)
|
||||||
GetImageConfigInfoFn func(repo string, manifestDigest godigest.Digest) (ispec.Image, error)
|
GetImageConfigInfoFn func(repo string, manifestDigest godigest.Digest) (ispec.Image, error)
|
||||||
|
CheckManifestSignatureFn func(name string, digest godigest.Digest) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (olum OciLayoutUtilsMock) GetImageManifests(image string) ([]ispec.Descriptor, error) {
|
func (olum OciLayoutUtilsMock) GetImageManifests(image string) ([]ispec.Descriptor, error) {
|
||||||
if olum.GetImageBlobManifestFn != nil {
|
if olum.GetImageManifestsFn != nil {
|
||||||
return olum.GetImageManifestsFn(image)
|
return olum.GetImageManifestsFn(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,3 +129,11 @@ func (olum OciLayoutUtilsMock) GetImageConfigInfo(repo string, manifestDigest go
|
|||||||
|
|
||||||
return ispec.Image{}, nil
|
return ispec.Image{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (olum OciLayoutUtilsMock) CheckManifestSignature(name string, digest godigest.Digest) bool {
|
||||||
|
if olum.CheckManifestSignatureFn != nil {
|
||||||
|
return olum.CheckManifestSignatureFn(name, digest)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user