0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-16 21:56:37 -05:00

fix: Sort tags returned by ExpendedRepoInfo in the Images property with the newest first (#1137)

Signed-off-by: Nicol Draghici <idraghic@cisco.com>
(cherry picked from commit e99ea64bd1b9699bcd6d72183c722d636772bbb1)

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
Signed-off-by: Nicol Draghici <idraghic@cisco.com>
This commit is contained in:
Andrei Aaron 2023-01-25 20:57:10 +02:00 committed by GitHub
parent 58ec62b3e4
commit 799f747429
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 137 additions and 1 deletions

View file

@ -297,6 +297,58 @@ func verifyImageSummaryFields(t *testing.T,
}
}
func uploadNewRepoTag(tag string, repoName string, baseURL string, layers [][]byte) error {
created := time.Now()
config := ispec.Image{
Created: &created,
Platform: ispec.Platform{
Architecture: "amd64",
OS: "linux",
},
RootFS: ispec.RootFS{
Type: "layers",
DiffIDs: []godigest.Digest{},
},
Author: "ZotUser",
}
configBlob, err := json.Marshal(config)
So(err, ShouldBeNil)
configDigest := godigest.FromBytes(configBlob)
manifest := ispec.Manifest{
Versioned: specs.Versioned{
SchemaVersion: 2,
},
Config: ispec.Descriptor{
MediaType: "application/vnd.oci.image.config.v1+json",
Digest: configDigest,
Size: int64(len(configBlob)),
},
Layers: []ispec.Descriptor{
{
MediaType: "application/vnd.oci.image.layer.v1.tar",
Digest: godigest.FromBytes(layers[0]),
Size: int64(len(layers[0])),
},
},
}
err = UploadImage(
Image{
Manifest: manifest,
Config: config,
Layers: layers,
Tag: tag,
},
baseURL,
repoName,
)
return err
}
func TestRepoListWithNewestImage(t *testing.T) {
Convey("Test repoListWithNewestImage by tag with HTTP", t, func() {
subpath := "/a"
@ -1081,6 +1133,68 @@ func TestExpandedRepoInfo(t *testing.T) {
err = json.Unmarshal(resp.Body(), responseStruct)
So(err, ShouldBeNil)
})
Convey("Test image tags order", t, func() {
port := GetFreePort()
baseURL := GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
conf.Storage.RootDirectory = t.TempDir()
defaultVal := true
conf.Extensions = &extconf.ExtensionConfig{
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
}
conf.Extensions.Search.CVE = nil
ctlr := api.NewController(conf)
ctlrManager := NewControllerManager(ctlr)
ctlrManager.StartAndWait(port)
defer ctlrManager.StopServer()
resp, err := resty.R().Get(baseURL + "/v2/")
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix)
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 422)
// create test images
repoName := "test-repo" //nolint:goconst
layers := [][]byte{
{10, 11, 10, 11},
}
err = uploadNewRepoTag("1.0", repoName, baseURL, layers)
So(err, ShouldBeNil)
err = uploadNewRepoTag("2.0", repoName, baseURL, layers)
So(err, ShouldBeNil)
err = uploadNewRepoTag("3.0", repoName, baseURL, layers)
So(err, ShouldBeNil)
responseStruct := &ExpandedRepoInfoResp{}
query := "{ExpandedRepoInfo(repo:\"test-repo\"){Images%20{RepoName%20Digest%20Tag%20LastUpdated%20Layers%20{Size%20Digest}}}}" //nolint: lll
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + query)
So(resp, ShouldNotBeNil)
So(err, ShouldBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
err = json.Unmarshal(resp.Body(), responseStruct)
So(err, ShouldBeNil)
So(len(responseStruct.ExpandedRepoInfo.RepoInfo.ImageSummaries), ShouldNotEqual, 0)
So(len(responseStruct.ExpandedRepoInfo.RepoInfo.ImageSummaries[0].Layers), ShouldNotEqual, 0)
So(responseStruct.ExpandedRepoInfo.RepoInfo.ImageSummaries[0].Tag, ShouldEqual, "3.0")
So(responseStruct.ExpandedRepoInfo.RepoInfo.ImageSummaries[1].Tag, ShouldEqual, "2.0")
So(responseStruct.ExpandedRepoInfo.RepoInfo.ImageSummaries[2].Tag, ShouldEqual, "1.0")
})
}
func TestUtilsMethod(t *testing.T) {

View file

@ -7,6 +7,7 @@ package search
import (
"context"
"encoding/json"
"sort"
"strings"
"github.com/99designs/gqlgen/graphql"
@ -706,7 +707,28 @@ func expandedRepoInfo(ctx context.Context, repo string, repoDB repodb.RepoDB, cv
repoSummary, imageSummaries := convert.RepoMeta2ExpandedRepoInfo(ctx, repoMeta, manifestMetaMap, skip, cveInfo)
return &gql_generated.RepoInfo{Summary: repoSummary, Images: imageSummaries}, nil
dateSortedImages := make(timeSlice, 0, len(imageSummaries))
for _, imgSummary := range imageSummaries {
dateSortedImages = append(dateSortedImages, imgSummary)
}
sort.Sort(dateSortedImages)
return &gql_generated.RepoInfo{Summary: repoSummary, Images: dateSortedImages}, nil
}
type timeSlice []*gql_generated.ImageSummary
func (p timeSlice) Len() int {
return len(p)
}
func (p timeSlice) Less(i, j int) bool {
return p[i].LastUpdated.After(*p[j].LastUpdated)
}
func (p timeSlice) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}
func safeDerefferencing[T any](pointer *T, defaultVal T) T {