0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-23 22:27:35 -05:00
zot/pkg/extensions/search/convert/convert_test.go
2023-04-18 11:07:47 -07:00

387 lines
10 KiB
Go

package convert_test
import (
"context"
"encoding/json"
"errors"
"testing"
"time"
"github.com/99designs/gqlgen/graphql"
godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
. "github.com/smartystreets/goconvey/convey"
"zotregistry.io/zot/pkg/extensions/search/convert"
cveinfo "zotregistry.io/zot/pkg/extensions/search/cve"
"zotregistry.io/zot/pkg/extensions/search/gql_generated"
"zotregistry.io/zot/pkg/log"
"zotregistry.io/zot/pkg/meta/bolt"
"zotregistry.io/zot/pkg/meta/repodb"
boltdb_wrapper "zotregistry.io/zot/pkg/meta/repodb/boltdb-wrapper"
"zotregistry.io/zot/pkg/test/mocks"
)
var ErrTestError = errors.New("TestError")
func TestConvertErrors(t *testing.T) {
Convey("Convert Errors", t, func() {
params := bolt.DBParameters{
RootDir: t.TempDir(),
}
boltDB, err := bolt.GetBoltDriver(params)
So(err, ShouldBeNil)
repoDB, err := boltdb_wrapper.NewBoltDBWrapper(boltDB, log.NewLogger("debug", ""))
So(err, ShouldBeNil)
configBlob, err := json.Marshal(ispec.Image{})
So(err, ShouldBeNil)
manifestBlob, err := json.Marshal(ispec.Manifest{
Layers: []ispec.Descriptor{
{
MediaType: ispec.MediaTypeImageLayerGzip,
Size: 0,
Digest: godigest.NewDigestFromEncoded(godigest.SHA256, "digest"),
},
},
})
So(err, ShouldBeNil)
repoMeta11 := repodb.ManifestMetadata{
ManifestBlob: manifestBlob,
ConfigBlob: configBlob,
}
digest11 := godigest.FromString("abc1")
err = repoDB.SetManifestMeta("repo1", digest11, repoMeta11)
So(err, ShouldBeNil)
err = repoDB.SetRepoReference("repo1", "0.1.0", digest11, ispec.MediaTypeImageManifest)
So(err, ShouldBeNil)
repoMetas, manifestMetaMap, _, _, err := repoDB.SearchRepos(context.Background(), "", repodb.Filter{},
repodb.PageInput{})
So(err, ShouldBeNil)
ctx := graphql.WithResponseContext(context.Background(),
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
_ = convert.RepoMeta2RepoSummary(
ctx,
repoMetas[0],
manifestMetaMap,
map[string]repodb.IndexData{},
convert.SkipQGLField{},
mocks.CveInfoMock{
GetCVESummaryForImageFn: func(repo string, reference string,
) (cveinfo.ImageCVESummary, error) {
return cveinfo.ImageCVESummary{}, ErrTestError
},
},
)
So(graphql.GetErrors(ctx).Error(), ShouldContainSubstring, "unable to run vulnerability scan on tag")
})
Convey("ImageIndex2ImageSummary errors", t, func() {
ctx := graphql.WithResponseContext(context.Background(),
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
_, _, err := convert.ImageIndex2ImageSummary(
ctx,
"repo",
"tag",
godigest.FromString("indexDigest"),
true,
repodb.RepoMetadata{},
repodb.IndexData{
IndexBlob: []byte("bad json"),
},
map[string]repodb.ManifestMetadata{},
mocks.CveInfoMock{},
)
So(err, ShouldNotBeNil)
})
Convey("ImageIndex2ImageSummary cve scanning", t, func() {
ctx := graphql.WithResponseContext(context.Background(),
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
_, _, err := convert.ImageIndex2ImageSummary(
ctx,
"repo",
"tag",
godigest.FromString("indexDigest"),
false,
repodb.RepoMetadata{},
repodb.IndexData{
IndexBlob: []byte("{}"),
},
map[string]repodb.ManifestMetadata{},
mocks.CveInfoMock{
GetCVESummaryForImageFn: func(repo, reference string,
) (cveinfo.ImageCVESummary, error) {
return cveinfo.ImageCVESummary{}, ErrTestError
},
},
)
So(err, ShouldBeNil)
})
Convey("ImageManifest2ImageSummary", t, func() {
ctx := graphql.WithResponseContext(context.Background(),
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
configBlob, err := json.Marshal(ispec.Image{
Platform: ispec.Platform{
OS: "os",
Architecture: "arch",
Variant: "var",
},
})
So(err, ShouldBeNil)
_, _, err = convert.ImageManifest2ImageSummary(
ctx,
"repo",
"tag",
godigest.FromString("manifestDigest"),
false,
repodb.RepoMetadata{},
repodb.ManifestMetadata{
ManifestBlob: []byte("{}"),
ConfigBlob: configBlob,
},
mocks.CveInfoMock{
GetCVESummaryForImageFn: func(repo, reference string,
) (cveinfo.ImageCVESummary, error) {
return cveinfo.ImageCVESummary{}, ErrTestError
},
},
)
So(err, ShouldBeNil)
})
Convey("ImageManifest2ManifestSummary", t, func() {
ctx := graphql.WithResponseContext(context.Background(),
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
// with bad config json, error while unmarshaling
_, _, err := convert.ImageManifest2ManifestSummary(
ctx,
"repo",
"tag",
ispec.Descriptor{
Digest: "dig",
MediaType: ispec.MediaTypeImageManifest,
},
false,
repodb.RepoMetadata{
Tags: map[string]repodb.Descriptor{},
Statistics: map[string]repodb.DescriptorStatistics{},
Signatures: map[string]repodb.ManifestSignatures{},
Referrers: map[string][]repodb.ReferrerInfo{},
},
repodb.ManifestMetadata{
ManifestBlob: []byte("{}"),
ConfigBlob: []byte("bad json"),
},
nil,
mocks.CveInfoMock{
GetCVESummaryForImageFn: func(repo, reference string,
) (cveinfo.ImageCVESummary, error) {
return cveinfo.ImageCVESummary{}, ErrTestError
},
},
)
So(err, ShouldNotBeNil)
// CVE scan using platform
configBlob, err := json.Marshal(ispec.Image{
Platform: ispec.Platform{
OS: "os",
Architecture: "arch",
Variant: "var",
},
})
So(err, ShouldBeNil)
_, _, err = convert.ImageManifest2ManifestSummary(
ctx,
"repo",
"tag",
ispec.Descriptor{
Digest: "dig",
MediaType: ispec.MediaTypeImageManifest,
},
false,
repodb.RepoMetadata{
Tags: map[string]repodb.Descriptor{},
Statistics: map[string]repodb.DescriptorStatistics{},
Signatures: map[string]repodb.ManifestSignatures{"dig": {"cosine": []repodb.SignatureInfo{{}}}},
Referrers: map[string][]repodb.ReferrerInfo{},
},
repodb.ManifestMetadata{
ManifestBlob: []byte("{}"),
ConfigBlob: configBlob,
},
nil,
mocks.CveInfoMock{
GetCVESummaryForImageFn: func(repo, reference string,
) (cveinfo.ImageCVESummary, error) {
return cveinfo.ImageCVESummary{}, ErrTestError
},
},
)
So(err, ShouldBeNil)
})
Convey("RepoMeta2ExpandedRepoInfo", t, func() {
ctx := graphql.WithResponseContext(context.Background(),
graphql.DefaultErrorPresenter, graphql.DefaultRecover)
// with bad config json, error while unmarshaling
_, imageSummaries := convert.RepoMeta2ExpandedRepoInfo(
ctx,
repodb.RepoMetadata{
Tags: map[string]repodb.Descriptor{
"tag1": {Digest: "dig", MediaType: ispec.MediaTypeImageManifest},
},
},
map[string]repodb.ManifestMetadata{
"dig": {
ManifestBlob: []byte("{}"),
ConfigBlob: []byte("bad json"),
},
},
map[string]repodb.IndexData{},
convert.SkipQGLField{
Vulnerabilities: false,
},
mocks.CveInfoMock{
GetCVESummaryForImageFn: func(repo, reference string,
) (cveinfo.ImageCVESummary, error) {
return cveinfo.ImageCVESummary{}, ErrTestError
},
}, log.NewLogger("debug", ""),
)
So(len(imageSummaries), ShouldEqual, 0)
// cveInfo present no error
_, imageSummaries = convert.RepoMeta2ExpandedRepoInfo(
ctx,
repodb.RepoMetadata{
Tags: map[string]repodb.Descriptor{
"tag1": {Digest: "dig", MediaType: ispec.MediaTypeImageManifest},
},
},
map[string]repodb.ManifestMetadata{
"dig": {
ManifestBlob: []byte("{}"),
ConfigBlob: []byte("{}"),
},
},
map[string]repodb.IndexData{},
convert.SkipQGLField{
Vulnerabilities: false,
},
mocks.CveInfoMock{
GetCVESummaryForImageFn: func(repo, reference string,
) (cveinfo.ImageCVESummary, error) {
return cveinfo.ImageCVESummary{}, ErrTestError
},
}, log.NewLogger("debug", ""),
)
So(len(imageSummaries), ShouldEqual, 1)
})
}
func TestUpdateLastUpdatedTimestam(t *testing.T) {
Convey("Image summary is the first image checked for the repo", t, func() {
before := time.Time{}
after := time.Date(2023, time.April, 1, 11, 0, 0, 0, time.UTC)
img := convert.UpdateLastUpdatedTimestamp(
&before,
&gql_generated.ImageSummary{LastUpdated: &before},
&gql_generated.ImageSummary{LastUpdated: &after},
)
So(*img.LastUpdated, ShouldResemble, after)
})
Convey("Image summary is updated after the current latest image", t, func() {
before := time.Date(2022, time.April, 1, 11, 0, 0, 0, time.UTC)
after := time.Date(2023, time.April, 1, 11, 0, 0, 0, time.UTC)
img := convert.UpdateLastUpdatedTimestamp(
&before,
&gql_generated.ImageSummary{LastUpdated: &before},
&gql_generated.ImageSummary{LastUpdated: &after},
)
So(*img.LastUpdated, ShouldResemble, after)
})
Convey("Image summary is updated before the current latest image", t, func() {
before := time.Date(2022, time.April, 1, 11, 0, 0, 0, time.UTC)
after := time.Date(2023, time.April, 1, 11, 0, 0, 0, time.UTC)
img := convert.UpdateLastUpdatedTimestamp(
&after,
&gql_generated.ImageSummary{LastUpdated: &after},
&gql_generated.ImageSummary{LastUpdated: &before},
)
So(*img.LastUpdated, ShouldResemble, after)
})
}
func TestLabels(t *testing.T) {
Convey("Test labels", t, func() {
// Test various labels
labels := make(map[string]string)
desc := convert.GetDescription(labels)
So(desc, ShouldEqual, "")
license := convert.GetLicenses(labels)
So(license, ShouldEqual, "")
vendor := convert.GetVendor(labels)
So(vendor, ShouldEqual, "")
categories := convert.GetCategories(labels)
So(categories, ShouldEqual, "")
labels[ispec.AnnotationVendor] = "zot"
labels[ispec.AnnotationDescription] = "zot-desc"
labels[ispec.AnnotationLicenses] = "zot-license"
labels[convert.AnnotationLabels] = "zot-labels"
desc = convert.GetDescription(labels)
So(desc, ShouldEqual, "zot-desc")
license = convert.GetLicenses(labels)
So(license, ShouldEqual, "zot-license")
vendor = convert.GetVendor(labels)
So(vendor, ShouldEqual, "zot")
categories = convert.GetCategories(labels)
So(categories, ShouldEqual, "zot-labels")
labels = make(map[string]string)
// Use diff key
labels[convert.LabelAnnotationVendor] = "zot-vendor"
labels[convert.LabelAnnotationDescription] = "zot-label-desc"
labels[ispec.AnnotationLicenses] = "zot-label-license"
desc = convert.GetDescription(labels)
So(desc, ShouldEqual, "zot-label-desc")
license = convert.GetLicenses(labels)
So(license, ShouldEqual, "zot-label-license")
vendor = convert.GetVendor(labels)
So(vendor, ShouldEqual, "zot-vendor")
})
}