diff --git a/pkg/extensions/search/common/common_test.go b/pkg/extensions/search/common/common_test.go index 5d778fd3..dbde9c1d 100644 --- a/pkg/extensions/search/common/common_test.go +++ b/pkg/extensions/search/common/common_test.go @@ -865,7 +865,7 @@ func TestBaseOciLayoutUtils(t *testing.T) { Convey("GetImageConfigSize: config GetBlobContent fail", t, func() { mockStoreController := mocks.MockedImageStore{ - GetBlobContentFn: func(repo, digest string) ([]byte, error) { + GetBlobContentFn: func(_, digest string) ([]byte, error) { if digest == manifestDigest { return []byte{}, ErrTestError } @@ -911,213 +911,4 @@ func TestBaseOciLayoutUtils(t *testing.T) { _, err := olu.GetRepoLastUpdated("") So(err, ShouldNotBeNil) }) - - Convey("GetImageLastUpdated: GetImageBlobManifest fails", t, func() { - mockStoreController := mocks.MockedImageStore{ - GetBlobContentFn: func(repo, digest string) ([]byte, error) { - return []byte{}, ErrTestError - }, - } - - storeController := storage.StoreController{DefaultStore: mockStoreController} - olu := common.NewBaseOciLayoutUtils(storeController, log.NewLogger("debug", "")) - - time := olu.GetImageLastUpdated("", "") - So(time, ShouldBeZeroValue) - }) - - Convey("GetImageLastUpdated: GetImageInfo fails", t, func() { - mockStoreController := mocks.MockedImageStore{ - GetBlobContentFn: func(repo, digest string) ([]byte, error) { - if digest == manifestDigest { - return []byte{}, ErrTestError - } - - return []byte( - ` - { - "schemaVersion": 2, - "mediaType": "application/vnd.oci.image.manifest.v1+json", - "config": { - "mediaType": "application/vnd.oci.image.config.v1+json", - "digest": manifestDigest, - "size": 1476 - }, - "layers": [ - { - "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", - "digest": "sha256:2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc", - "size": 76097157 - } - ] - }`), nil - }, - } - - storeController := storage.StoreController{DefaultStore: mockStoreController} - olu := common.NewBaseOciLayoutUtils(storeController, log.NewLogger("debug", "")) - - time := olu.GetImageLastUpdated("", "") - So(time, ShouldBeZeroValue) - }) - - Convey("GetImageLastUpdated: GetImageInfo history is empty", t, func() { - mockStoreController := mocks.MockedImageStore{ - GetBlobContentFn: func(repo, digest string) ([]byte, error) { - if digest == manifestDigest { - return []byte( - ` - { - "created": "2020-11-14T00:20:04.644613188Z", - "architecture": "amd64", - "os": "linux", - "config": { - "Env": [ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - ], - "Cmd": [ - "/bin/bash" - ], - "Labels": { - } - }, - "rootfs": { - "type": "layers", - "diff_ids": [ - "sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02" - ] - }, - "history": [ - ] - } - `), nil - } - - return []byte( - ` - { - "schemaVersion": 2, - "mediaType": "application/vnd.oci.image.manifest.v1+json", - "config": { - "mediaType": "application/vnd.oci.image.config.v1+json", - "digest": manifestDigest, - "size": 1476 - }, - "layers": [ - { - "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", - "digest": "sha256:2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc", - "size": 76097157 - } - ] - }`), nil - }, - } - - storeController := storage.StoreController{DefaultStore: mockStoreController} - olu := common.NewBaseOciLayoutUtils(storeController, log.NewLogger("debug", "")) - - time := olu.GetImageLastUpdated("", "") - So(time, ShouldBeZeroValue) - }) - - Convey("GetImagePlatform: GetImageBlobManifest fails", t, func() { - mockStoreController := mocks.MockedImageStore{ - GetBlobContentFn: func(repo, digest string) ([]byte, error) { - return []byte{}, ErrTestError - }, - } - - storeController := storage.StoreController{DefaultStore: mockStoreController} - olu := common.NewBaseOciLayoutUtils(storeController, log.NewLogger("debug", "")) - - os, arch := olu.GetImagePlatform("", "") - So(os, ShouldBeZeroValue) - So(arch, ShouldBeZeroValue) - }) - - Convey("GetImagePlatform: GetImageInfo fails", t, func() { - mockStoreController := mocks.MockedImageStore{ - GetBlobContentFn: func(repo, digest string) ([]byte, error) { - if digest == manifestDigest { - return []byte{}, ErrTestError - } - - return []byte( - ` - { - "schemaVersion": 2, - "mediaType": "application/vnd.oci.image.manifest.v1+json", - "config": { - "mediaType": "application/vnd.oci.image.config.v1+json", - "digest": manifestDigest, - "size": 1476 - }, - "layers": [ - { - "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", - "digest": "sha256:2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc", - "size": 76097157 - } - ] - }`), nil - }, - } - - storeController := storage.StoreController{DefaultStore: mockStoreController} - olu := common.NewBaseOciLayoutUtils(storeController, log.NewLogger("debug", "")) - - os, arch := olu.GetImagePlatform("", "") - So(os, ShouldBeZeroValue) - So(arch, ShouldBeZeroValue) - }) - - Convey("GetImageVendor: GetImageBlobManifest fails", t, func() { - mockStoreController := mocks.MockedImageStore{ - GetBlobContentFn: func(repo, digest string) ([]byte, error) { - return []byte{}, ErrTestError - }, - } - - storeController := storage.StoreController{DefaultStore: mockStoreController} - olu := common.NewBaseOciLayoutUtils(storeController, log.NewLogger("debug", "")) - - vendor := olu.GetImageVendor("", "") - So(vendor, ShouldBeZeroValue) - }) - - Convey("GetImageVendor: GetImageInfo fails", t, func() { - mockStoreController := mocks.MockedImageStore{ - GetBlobContentFn: func(repo, digest string) ([]byte, error) { - if digest == manifestDigest { - return []byte{}, ErrTestError - } - - return []byte( - ` - { - "schemaVersion": 2, - "mediaType": "application/vnd.oci.image.manifest.v1+json", - "config": { - "mediaType": "application/vnd.oci.image.config.v1+json", - "digest": manifestDigest, - "size": 1476 - }, - "layers": [ - { - "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", - "digest": "sha256:2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc", - "size": 76097157 - } - ] - }`), nil - }, - } - - storeController := storage.StoreController{DefaultStore: mockStoreController} - olu := common.NewBaseOciLayoutUtils(storeController, log.NewLogger("debug", "")) - - vendor := olu.GetImageVendor("", "") - So(vendor, ShouldBeZeroValue) - }) } diff --git a/pkg/extensions/search/common/oci_layout.go b/pkg/extensions/search/common/oci_layout.go index b450664b..2ee3c864 100644 --- a/pkg/extensions/search/common/oci_layout.go +++ b/pkg/extensions/search/common/oci_layout.go @@ -26,13 +26,14 @@ type OciLayoutUtils interface { GetImageInfo(imageDir string, hash v1.Hash) (ispec.Image, error) IsValidImageFormat(image string) (bool, error) GetImageTagsWithTimestamp(repo string) ([]TagInfo, error) - GetImageLastUpdated(repo string, manifestDigest godigest.Digest) time.Time - GetImagePlatform(repo string, manifestDigest godigest.Digest) (string, string) - GetImageVendor(repo string, manifestDigest godigest.Digest) string + GetImageLastUpdated(imageInfo ispec.Image) time.Time + GetImagePlatform(imageInfo ispec.Image) (string, string) + GetImageVendor(imageInfo ispec.Image) string GetImageManifestSize(repo string, manifestDigest godigest.Digest) int64 GetImageConfigSize(repo string, manifestDigest godigest.Digest) int64 GetRepoLastUpdated(repo string) (time.Time, error) GetExpandedRepoInfo(name string) (RepoInfo, error) + GetImageConfigInfo(repo string, manifestDigest godigest.Digest) (ispec.Image, error) } // OciLayoutInfo ... @@ -263,21 +264,7 @@ func (olu BaseOciLayoutUtils) checkManifestSignature(name string, digest godiges return true } -func (olu BaseOciLayoutUtils) GetImageLastUpdated(repo string, manifestDigest godigest.Digest) time.Time { - imageBlobManifest, err := olu.GetImageBlobManifest(repo, manifestDigest) - if err != nil { - olu.Log.Error().Err(err).Msg("unable to read image blob") - - return time.Time{} - } - - imageInfo, err := olu.GetImageInfo(repo, imageBlobManifest.Config.Digest) - if err != nil { - olu.Log.Error().Err(err).Msg("unable to read image info") - - return time.Time{} - } - +func (olu BaseOciLayoutUtils) GetImageLastUpdated(imageInfo ispec.Image) time.Time { var timeStamp time.Time if len(imageInfo.History) != 0 { @@ -289,41 +276,27 @@ func (olu BaseOciLayoutUtils) GetImageLastUpdated(repo string, manifestDigest go return timeStamp } -func (olu BaseOciLayoutUtils) GetImagePlatform(repo string, manifestDigest godigest.Digest) ( +func (olu BaseOciLayoutUtils) GetImagePlatform(imageConfig ispec.Image) ( string, string, ) { - imageBlobManifest, err := olu.GetImageBlobManifest(repo, manifestDigest) - if err != nil { - olu.Log.Error().Err(err).Msg("can't get image blob manifest") - - return "", "" - } - - imageConfig, err := olu.GetImageInfo(repo, imageBlobManifest.Config.Digest) - if err != nil { - olu.Log.Error().Err(err).Msg("extension api: error reading image config") - - return "", "" - } - return imageConfig.OS, imageConfig.Architecture } -func (olu BaseOciLayoutUtils) GetImageVendor(repo string, manifestDigest godigest.Digest) string { +func (olu BaseOciLayoutUtils) GetImageConfigInfo(repo string, manifestDigest godigest.Digest) (ispec.Image, error) { imageBlobManifest, err := olu.GetImageBlobManifest(repo, manifestDigest) if err != nil { - olu.Log.Error().Err(err).Msg("can't get image blob manifest") - - return "" + return ispec.Image{}, err } - imageConfig, err := olu.GetImageInfo(repo, imageBlobManifest.Config.Digest) + imageInfo, err := olu.GetImageInfo(repo, imageBlobManifest.Config.Digest) if err != nil { - olu.Log.Error().Err(err).Msg("extension api: error reading image config") - - return "" + return ispec.Image{}, err } + return imageInfo, nil +} + +func (olu BaseOciLayoutUtils) GetImageVendor(imageConfig ispec.Image) string { return imageConfig.Config.Labels["vendor"] } diff --git a/pkg/extensions/search/resolver.go b/pkg/extensions/search/resolver.go index 496e9ee4..d6c633e6 100644 --- a/pkg/extensions/search/resolver.go +++ b/pkg/extensions/search/resolver.go @@ -272,16 +272,23 @@ func globalSearch(repoList []string, name, tag string, olu common.OciLayoutUtils matchesTag := strings.HasPrefix(manifest.Tag, tag) if index != -1 { + imageConfigInfo, err := olu.GetImageConfigInfo(repo, godigest.Digest(tagsInfo[i].Digest)) + if err != nil { + log.Error().Err(err).Msgf("can't retrieve config info for the image %s %s", repo, manifest.Tag) + + continue + } + tag := manifest.Tag size := strconv.Itoa(int(imageSize)) - vendor := olu.GetImageVendor(repo, godigest.Digest(tagsInfo[i].Digest)) - lastUpdated := olu.GetImageLastUpdated(repo, godigest.Digest(tagsInfo[i].Digest)) - isSigned := manifest.IsSigned + // update matching score score := calculateImageMatchingScore(repo, index, matchesTag) - os, arch := olu.GetImagePlatform(repo, godigest.Digest(tagsInfo[i].Digest)) + vendor := olu.GetImageVendor(imageConfigInfo) + lastUpdated := olu.GetImageLastUpdated(imageConfigInfo) + os, arch := olu.GetImagePlatform(imageConfigInfo) osArch := &gql_generated.OsArch{ Os: &os, Arch: &arch, diff --git a/pkg/test/mocks/oci_mock.go b/pkg/test/mocks/oci_mock.go index cf7fe463..965017cd 100644 --- a/pkg/test/mocks/oci_mock.go +++ b/pkg/test/mocks/oci_mock.go @@ -15,13 +15,14 @@ type OciLayoutUtilsMock struct { GetImageInfoFn func(imageDir string, hash v1.Hash) (ispec.Image, error) IsValidImageFormatFn func(image string) (bool, error) GetImageTagsWithTimestampFn func(repo string) ([]common.TagInfo, error) - GetImageLastUpdatedFn func(repo string, manifestDigest godigest.Digest) time.Time - GetImagePlatformFn func(repo string, manifestDigest godigest.Digest) (string, string) - GetImageVendorFn func(repo string, manifestDigest godigest.Digest) string + GetImageLastUpdatedFn func(imageInfo ispec.Image) time.Time + GetImagePlatformFn func(imageInfo ispec.Image) (string, string) + GetImageVendorFn func(imageInfo ispec.Image) string GetImageManifestSizeFn func(repo string, manifestDigest godigest.Digest) int64 GetImageConfigSizeFn func(repo string, manifestDigest godigest.Digest) int64 GetRepoLastUpdatedFn func(repo string) (time.Time, error) GetExpandedRepoInfoFn func(name string) (common.RepoInfo, error) + GetImageConfigInfoFn func(repo string, manifestDigest godigest.Digest) (ispec.Image, error) } func (olum OciLayoutUtilsMock) GetImageManifests(image string) ([]ispec.Descriptor, error) { @@ -64,25 +65,25 @@ func (olum OciLayoutUtilsMock) GetImageTagsWithTimestamp(repo string) ([]common. return []common.TagInfo{}, nil } -func (olum OciLayoutUtilsMock) GetImageLastUpdated(repo string, manifestDigest godigest.Digest) time.Time { +func (olum OciLayoutUtilsMock) GetImageLastUpdated(imageInfo ispec.Image) time.Time { if olum.GetImageLastUpdatedFn != nil { - return olum.GetImageLastUpdatedFn(repo, manifestDigest) + return olum.GetImageLastUpdatedFn(imageInfo) } return time.Time{} } -func (olum OciLayoutUtilsMock) GetImagePlatform(repo string, manifestDigest godigest.Digest) (string, string) { +func (olum OciLayoutUtilsMock) GetImagePlatform(imageInfo ispec.Image) (string, string) { if olum.GetImagePlatformFn != nil { - return olum.GetImagePlatformFn(repo, manifestDigest) + return olum.GetImagePlatformFn(imageInfo) } return "", "" } -func (olum OciLayoutUtilsMock) GetImageVendor(repo string, manifestDigest godigest.Digest) string { +func (olum OciLayoutUtilsMock) GetImageVendor(imageInfo ispec.Image) string { if olum.GetImageVendorFn != nil { - return olum.GetImageVendorFn(repo, manifestDigest) + return olum.GetImageVendorFn(imageInfo) } return "" @@ -119,3 +120,11 @@ func (olum OciLayoutUtilsMock) GetExpandedRepoInfo(name string) (common.RepoInfo return common.RepoInfo{}, nil } + +func (olum OciLayoutUtilsMock) GetImageConfigInfo(repo string, manifestDigest godigest.Digest) (ispec.Image, error) { + if olum.GetImageConfigInfoFn != nil { + return olum.GetImageConfigInfoFn(repo, manifestDigest) + } + + return ispec.Image{}, nil +}