mirror of
https://github.com/project-zot/zot.git
synced 2026-06-17 04:48:26 +08:00
feat(repodb): add PageInfo to GlobalSearch and RepoListWithNewestImage results (#1121)
Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro> add page info to dynamo-> feat(repodb): add PageInfo to GlobalSearch and RepoListWithNewestImage results (cherry picked from commit 4fed42bb4bbc68199281d9d9a4e09b97fbd4759b) Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro> Signed-off-by: Andrei Aaron <aaaron@luxoft.com> Co-authored-by: Alex Stan <alexandrustan96@yahoo.ro>
This commit is contained in:
@@ -116,15 +116,21 @@ type GlobalSearch struct {
|
||||
Images []common.ImageSummary `json:"images"`
|
||||
Repos []common.RepoSummary `json:"repos"`
|
||||
Layers []common.LayerSummary `json:"layers"`
|
||||
Page repodb.PageInfo `json:"page"`
|
||||
}
|
||||
|
||||
type ExpandedRepoInfo struct {
|
||||
RepoInfo common.RepoInfo `json:"expandedRepoInfo"`
|
||||
}
|
||||
|
||||
type PaginatedReposResult struct {
|
||||
Results []common.RepoSummary `json:"results"`
|
||||
Page repodb.PageInfo `json:"page"`
|
||||
}
|
||||
|
||||
//nolint:tagliatelle // graphQL schema
|
||||
type RepoListWithNewestImage struct {
|
||||
Repos []common.RepoSummary `json:"RepoListWithNewestImage"`
|
||||
PaginatedReposResult `json:"RepoListWithNewestImage"`
|
||||
}
|
||||
|
||||
type ErrorGQL struct {
|
||||
@@ -332,136 +338,241 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 422)
|
||||
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query={RepoListWithNewestImage{Name%20NewestImage{Tag}}}")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
var responseStruct RepoWithNewestImageResponse
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(responseStruct.RepoListWithNewestImage.Repos), ShouldEqual, 4)
|
||||
|
||||
images := responseStruct.RepoListWithNewestImage.Repos
|
||||
So(images[0].NewestImage.Tag, ShouldEqual, "0.0.1")
|
||||
|
||||
query := `{
|
||||
RepoListWithNewestImage(requestedPage: {
|
||||
limit:1
|
||||
offset:0
|
||||
sortBy: UPDATE_TIME
|
||||
}){
|
||||
Name
|
||||
NewestImage{
|
||||
Tag
|
||||
Convey("Test repoListWithNewestImage with pagination", func() {
|
||||
query := `{
|
||||
RepoListWithNewestImage(requestedPage:{
|
||||
limit: 2
|
||||
offset: 0
|
||||
sortBy: UPDATE_TIME
|
||||
}){
|
||||
Page{
|
||||
ItemCount
|
||||
TotalCount
|
||||
}
|
||||
Results{
|
||||
Name
|
||||
NewestImage{
|
||||
Tag
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
var responseStruct RepoWithNewestImageResponse
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(responseStruct.RepoListWithNewestImage.PaginatedReposResult.Results), ShouldEqual, 2)
|
||||
So(responseStruct.RepoListWithNewestImage.PaginatedReposResult.Page.ItemCount, ShouldEqual, 2)
|
||||
So(responseStruct.RepoListWithNewestImage.PaginatedReposResult.Page.TotalCount, ShouldEqual, 4)
|
||||
})
|
||||
|
||||
Convey("Test repoListWithNewestImage with pagination, no limit or offset", func() {
|
||||
query := `{
|
||||
RepoListWithNewestImage(requestedPage:{
|
||||
limit: 0
|
||||
offset: 0
|
||||
sortBy: UPDATE_TIME
|
||||
}){
|
||||
Page{
|
||||
ItemCount
|
||||
TotalCount
|
||||
}
|
||||
Results{
|
||||
Name
|
||||
NewestImage{
|
||||
Tag
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
var responseStruct RepoWithNewestImageResponse
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(responseStruct.RepoListWithNewestImage.PaginatedReposResult.Results), ShouldEqual, 4)
|
||||
So(responseStruct.RepoListWithNewestImage.PaginatedReposResult.Page.ItemCount, ShouldEqual, 4)
|
||||
So(responseStruct.RepoListWithNewestImage.PaginatedReposResult.Page.TotalCount, ShouldEqual, 4)
|
||||
})
|
||||
|
||||
Convey("Test repoListWithNewestImage multiple", func() {
|
||||
query := `{RepoListWithNewestImage{
|
||||
Results{
|
||||
Name
|
||||
NewestImage{
|
||||
Tag
|
||||
}
|
||||
}
|
||||
}}`
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
var responseStruct RepoWithNewestImageResponse
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(responseStruct.RepoListWithNewestImage.PaginatedReposResult.Results), ShouldEqual, 4)
|
||||
|
||||
images := responseStruct.RepoListWithNewestImage.PaginatedReposResult.Results
|
||||
So(images[0].NewestImage.Tag, ShouldEqual, "0.0.1")
|
||||
|
||||
query = `{
|
||||
RepoListWithNewestImage(requestedPage: {
|
||||
limit: 1
|
||||
offset: 0
|
||||
sortBy: UPDATE_TIME
|
||||
}){
|
||||
Results{
|
||||
Name
|
||||
NewestImage{
|
||||
Tag
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(responseStruct.RepoListWithNewestImage.PaginatedReposResult.Results), ShouldEqual, 1)
|
||||
|
||||
repos := responseStruct.RepoListWithNewestImage.PaginatedReposResult.Results
|
||||
So(repos[0].NewestImage.Tag, ShouldEqual, "0.0.1")
|
||||
|
||||
query = `{
|
||||
RepoListWithNewestImage{
|
||||
Results{
|
||||
Name
|
||||
NewestImage{
|
||||
Tag
|
||||
Vulnerabilities{
|
||||
MaxSeverity
|
||||
Count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
// Verify we don't return any vulnerabilities if CVE scanning is disabled
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(responseStruct.RepoListWithNewestImage.PaginatedReposResult.Results), ShouldEqual, 4)
|
||||
|
||||
images = responseStruct.RepoListWithNewestImage.PaginatedReposResult.Results
|
||||
So(images[0].NewestImage.Tag, ShouldEqual, "0.0.1")
|
||||
So(images[0].NewestImage.Vulnerabilities.Count, ShouldEqual, 0)
|
||||
So(images[0].NewestImage.Vulnerabilities.MaxSeverity, ShouldEqual, "")
|
||||
|
||||
query = `{
|
||||
RepoListWithNewestImage{
|
||||
Results{
|
||||
Name
|
||||
NewestImage{
|
||||
Tag
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = os.Chmod(rootDir, 0o000)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}`
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(responseStruct.RepoListWithNewestImage.Repos), ShouldEqual, 1)
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
repos := responseStruct.RepoListWithNewestImage.Repos
|
||||
So(repos[0].NewestImage.Tag, ShouldEqual, "0.0.1")
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(responseStruct.Errors, ShouldBeNil) // Even if permissions fail data is coming from the DB
|
||||
|
||||
// Verify we don't return any vulnerabilities if CVE scanning is disabled
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query={RepoListWithNewestImage{Name%20NewestImage{Tag%20Vulnerabilities{MaxSeverity%20Count}}}}")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
err = os.Chmod(rootDir, 0o755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(responseStruct.RepoListWithNewestImage.Repos), ShouldEqual, 4)
|
||||
var manifestDigest godigest.Digest
|
||||
var configDigest godigest.Digest
|
||||
manifestDigest, configDigest, _ = GetOciLayoutDigests("../../../../test/data/zot-test")
|
||||
|
||||
images = responseStruct.RepoListWithNewestImage.Repos
|
||||
So(images[0].NewestImage.Tag, ShouldEqual, "0.0.1")
|
||||
So(images[0].NewestImage.Vulnerabilities.Count, ShouldEqual, 0)
|
||||
So(images[0].NewestImage.Vulnerabilities.MaxSeverity, ShouldEqual, "")
|
||||
// Delete config blob and try.
|
||||
err = os.Remove(path.Join(subRootDir, "a/zot-test/blobs/sha256", configDigest.Encoded()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query={RepoListWithNewestImage{Name%20NewestImage{Tag}}}")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
err = os.Chmod(rootDir, 0o000)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = os.Remove(path.Join(subRootDir, "a/zot-test/blobs/sha256",
|
||||
manifestDigest.Encoded()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query={RepoListWithNewestImage{Name%20NewestImage{Tag}}}")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(responseStruct.Errors, ShouldBeNil) // Even if permissions fail data is coming from the DB
|
||||
err = os.Remove(path.Join(rootDir, "zot-test/blobs/sha256", configDigest.Encoded()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = os.Chmod(rootDir, 0o755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
var manifestDigest godigest.Digest
|
||||
var configDigest godigest.Digest
|
||||
manifestDigest, configDigest, _ = GetOciLayoutDigests("../../../../test/data/zot-test")
|
||||
// Delete manifest blob also and try
|
||||
err = os.Remove(path.Join(rootDir, "zot-test/blobs/sha256", manifestDigest.Encoded()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Delete config blob and try.
|
||||
err = os.Remove(path.Join(subRootDir, "a/zot-test/blobs/sha256", configDigest.Encoded()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query={RepoListWithNewestImage{Name%20NewestImage{Tag}}}")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
err = os.Remove(path.Join(subRootDir, "a/zot-test/blobs/sha256",
|
||||
manifestDigest.Encoded()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query={RepoListWithNewestImage{Name%20NewestImage{Tag}}}")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
err = os.Remove(path.Join(rootDir, "zot-test/blobs/sha256", configDigest.Encoded()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query={RepoListWithNewestImage{Name%20NewestImage{Tag}}}")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
// Delete manifest blob also and try
|
||||
err = os.Remove(path.Join(rootDir, "zot-test/blobs/sha256", manifestDigest.Encoded()))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query={RepoListWithNewestImage{Name%20NewestImage{Tag}}}")
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix +
|
||||
"?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Test repoListWithNewestImage with vulnerability scan enabled", t, func() {
|
||||
@@ -534,8 +645,21 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 422)
|
||||
|
||||
query := "?query={RepoListWithNewestImage{Name%20NewestImage{Tag%20Vulnerabilities{MaxSeverity%20Count}}}}"
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + query)
|
||||
query := `{
|
||||
RepoListWithNewestImage{
|
||||
Results{
|
||||
Name
|
||||
NewestImage{
|
||||
Tag
|
||||
Vulnerabilities{
|
||||
MaxSeverity
|
||||
Count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
@@ -543,9 +667,9 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
var responseStruct RepoWithNewestImageResponse
|
||||
err = json.Unmarshal(resp.Body(), &responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(responseStruct.RepoListWithNewestImage.Repos), ShouldEqual, 4)
|
||||
So(len(responseStruct.RepoListWithNewestImage.PaginatedReposResult.Results), ShouldEqual, 4)
|
||||
|
||||
repos := responseStruct.RepoListWithNewestImage.Repos
|
||||
repos := responseStruct.RepoListWithNewestImage.PaginatedReposResult.Results
|
||||
So(repos[0].NewestImage.Tag, ShouldEqual, "0.0.1")
|
||||
|
||||
for _, repo := range repos {
|
||||
@@ -3254,7 +3378,7 @@ func TestGlobalSearchPagination(t *testing.T) {
|
||||
defer stopServer(ctlr)
|
||||
WaitTillServerReady(baseURL)
|
||||
|
||||
for i := 0; i < 1; i++ {
|
||||
for i := 0; i < 3; i++ {
|
||||
config, layers, manifest, err := GetImageComponents(10)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
@@ -3295,7 +3419,133 @@ func TestGlobalSearchPagination(t *testing.T) {
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Repos, ShouldNotBeEmpty)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Layers, ShouldBeEmpty)
|
||||
|
||||
So(len(responseStruct.GlobalSearchResult.GlobalSearch.Repos), ShouldEqual, 1)
|
||||
So(len(responseStruct.GlobalSearchResult.GlobalSearch.Repos), ShouldEqual, 3)
|
||||
})
|
||||
|
||||
Convey("Limit is lower than the repo count", func() {
|
||||
query := `
|
||||
{
|
||||
GlobalSearch(query:"repo", requestedPage:{limit: 2, offset: 0, sortBy:RELEVANCE}){
|
||||
Repos {
|
||||
Name
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
resp, err := resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
responseStruct := &GlobalSearchResultResp{}
|
||||
|
||||
err = json.Unmarshal(resp.Body(), responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Images, ShouldBeEmpty)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Repos, ShouldNotBeEmpty)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Layers, ShouldBeEmpty)
|
||||
|
||||
So(len(responseStruct.GlobalSearchResult.GlobalSearch.Repos), ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("PageInfo returned proper response", func() {
|
||||
query := `
|
||||
{
|
||||
GlobalSearch(query:"repo", requestedPage:{limit: 2, offset: 0, sortBy:RELEVANCE}){
|
||||
Repos {
|
||||
Name
|
||||
}
|
||||
Page{
|
||||
ItemCount
|
||||
TotalCount
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
resp, err := resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
responseStruct := &GlobalSearchResultResp{}
|
||||
|
||||
err = json.Unmarshal(resp.Body(), responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Images, ShouldBeEmpty)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Repos, ShouldNotBeEmpty)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Layers, ShouldBeEmpty)
|
||||
|
||||
So(len(responseStruct.GlobalSearchResult.GlobalSearch.Repos), ShouldEqual, 2)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Page.TotalCount, ShouldEqual, 3)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Page.ItemCount, ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("PageInfo when limit is bigger than the repo count", func() {
|
||||
query := `
|
||||
{
|
||||
GlobalSearch(query:"repo", requestedPage:{limit: 9, offset: 0, sortBy:RELEVANCE}){
|
||||
Repos {
|
||||
Name
|
||||
}
|
||||
Page{
|
||||
ItemCount
|
||||
TotalCount
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
resp, err := resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
responseStruct := &GlobalSearchResultResp{}
|
||||
|
||||
err = json.Unmarshal(resp.Body(), responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Images, ShouldBeEmpty)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Repos, ShouldNotBeEmpty)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Layers, ShouldBeEmpty)
|
||||
|
||||
So(len(responseStruct.GlobalSearchResult.GlobalSearch.Repos), ShouldEqual, 3)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Page.TotalCount, ShouldEqual, 3)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Page.ItemCount, ShouldEqual, 3)
|
||||
})
|
||||
|
||||
Convey("PageInfo when limit and offset have 0 value", func() {
|
||||
query := `
|
||||
{
|
||||
GlobalSearch(query:"repo", requestedPage:{limit: 0, offset: 0, sortBy:RELEVANCE}){
|
||||
Repos {
|
||||
Name
|
||||
}
|
||||
Page{
|
||||
ItemCount
|
||||
TotalCount
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
resp, err := resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query))
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(err, ShouldBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 200)
|
||||
|
||||
responseStruct := &GlobalSearchResultResp{}
|
||||
|
||||
err = json.Unmarshal(resp.Body(), responseStruct)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Images, ShouldBeEmpty)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Repos, ShouldNotBeEmpty)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Layers, ShouldBeEmpty)
|
||||
|
||||
So(len(responseStruct.GlobalSearchResult.GlobalSearch.Repos), ShouldEqual, 3)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Page.TotalCount, ShouldEqual, 3)
|
||||
So(responseStruct.GlobalSearchResult.GlobalSearch.Page.ItemCount, ShouldEqual, 3)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -52,7 +52,8 @@ func TestConvertErrors(t *testing.T) {
|
||||
err = repoDB.SetRepoTag("repo1", "0.1.0", digest11, ispec.MediaTypeImageManifest)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
repoMetas, manifestMetaMap, err := repoDB.SearchRepos(context.Background(), "", repodb.Filter{}, repodb.PageInput{})
|
||||
repoMetas, manifestMetaMap, _, err := repoDB.SearchRepos(context.Background(), "", repodb.Filter{},
|
||||
repodb.PageInput{})
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
ctx := graphql.WithResponseContext(context.Background(),
|
||||
|
||||
@@ -128,10 +128,18 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
PageInfo struct {
|
||||
NextPage func(childComplexity int) int
|
||||
ObjectCount func(childComplexity int) int
|
||||
Pages func(childComplexity int) int
|
||||
PreviousPage func(childComplexity int) int
|
||||
ItemCount func(childComplexity int) int
|
||||
TotalCount func(childComplexity int) int
|
||||
}
|
||||
|
||||
PaginatedImagesResult struct {
|
||||
Page func(childComplexity int) int
|
||||
Results func(childComplexity int) int
|
||||
}
|
||||
|
||||
PaginatedReposResult struct {
|
||||
Page func(childComplexity int) int
|
||||
Results func(childComplexity int) int
|
||||
}
|
||||
|
||||
Query struct {
|
||||
@@ -182,7 +190,7 @@ type QueryResolver interface {
|
||||
ImageListForCve(ctx context.Context, id string) ([]*ImageSummary, error)
|
||||
ImageListWithCVEFixed(ctx context.Context, id string, image string) ([]*ImageSummary, error)
|
||||
ImageListForDigest(ctx context.Context, id string, requestedPage *PageInput) ([]*ImageSummary, error)
|
||||
RepoListWithNewestImage(ctx context.Context, requestedPage *PageInput) ([]*RepoSummary, error)
|
||||
RepoListWithNewestImage(ctx context.Context, requestedPage *PageInput) (*PaginatedReposResult, error)
|
||||
ImageList(ctx context.Context, repo string) ([]*ImageSummary, error)
|
||||
ExpandedRepoInfo(ctx context.Context, repo string) (*RepoInfo, error)
|
||||
GlobalSearch(ctx context.Context, query string, filter *Filter, requestedPage *PageInput) (*GlobalSearchResult, error)
|
||||
@@ -564,33 +572,47 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.PackageInfo.Name(childComplexity), true
|
||||
|
||||
case "PageInfo.NextPage":
|
||||
if e.complexity.PageInfo.NextPage == nil {
|
||||
case "PageInfo.ItemCount":
|
||||
if e.complexity.PageInfo.ItemCount == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.PageInfo.NextPage(childComplexity), true
|
||||
return e.complexity.PageInfo.ItemCount(childComplexity), true
|
||||
|
||||
case "PageInfo.ObjectCount":
|
||||
if e.complexity.PageInfo.ObjectCount == nil {
|
||||
case "PageInfo.TotalCount":
|
||||
if e.complexity.PageInfo.TotalCount == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.PageInfo.ObjectCount(childComplexity), true
|
||||
return e.complexity.PageInfo.TotalCount(childComplexity), true
|
||||
|
||||
case "PageInfo.Pages":
|
||||
if e.complexity.PageInfo.Pages == nil {
|
||||
case "PaginatedImagesResult.Page":
|
||||
if e.complexity.PaginatedImagesResult.Page == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.PageInfo.Pages(childComplexity), true
|
||||
return e.complexity.PaginatedImagesResult.Page(childComplexity), true
|
||||
|
||||
case "PageInfo.PreviousPage":
|
||||
if e.complexity.PageInfo.PreviousPage == nil {
|
||||
case "PaginatedImagesResult.Results":
|
||||
if e.complexity.PaginatedImagesResult.Results == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.PageInfo.PreviousPage(childComplexity), true
|
||||
return e.complexity.PaginatedImagesResult.Results(childComplexity), true
|
||||
|
||||
case "PaginatedReposResult.Page":
|
||||
if e.complexity.PaginatedReposResult.Page == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.PaginatedReposResult.Page(childComplexity), true
|
||||
|
||||
case "PaginatedReposResult.Results":
|
||||
if e.complexity.PaginatedReposResult.Results == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.PaginatedReposResult.Results(childComplexity), true
|
||||
|
||||
case "Query.BaseImageList":
|
||||
if e.complexity.Query.BaseImageList == nil {
|
||||
@@ -1086,10 +1108,8 @@ enum SortCriteria {
|
||||
}
|
||||
|
||||
type PageInfo {
|
||||
ObjectCount: Int!
|
||||
PreviousPage: Int
|
||||
NextPage: Int
|
||||
Pages: Int
|
||||
TotalCount: Int!
|
||||
ItemCount: Int!
|
||||
}
|
||||
|
||||
# Pagination parameters
|
||||
@@ -1099,6 +1119,20 @@ input PageInput {
|
||||
sortBy: SortCriteria
|
||||
}
|
||||
|
||||
# Paginated list of RepoSummary objects
|
||||
# If limit is -1, pagination is disabled
|
||||
type PaginatedReposResult {
|
||||
Page: PageInfo
|
||||
Results: [RepoSummary!]!
|
||||
}
|
||||
|
||||
# Paginated list of ImageSummary objects
|
||||
# If limit is -1, pagination is disabled
|
||||
type PaginatedImagesResult {
|
||||
Page: PageInfo
|
||||
Results: [ImageSummary!]!
|
||||
}
|
||||
|
||||
input Filter {
|
||||
Os: [String]
|
||||
Arch: [String]
|
||||
@@ -1129,7 +1163,7 @@ type Query {
|
||||
"""
|
||||
Returns a list of repos with the newest tag within
|
||||
"""
|
||||
RepoListWithNewestImage(requestedPage: PageInput): [RepoSummary!]! # Newest based on created timestamp
|
||||
RepoListWithNewestImage(requestedPage: PageInput): PaginatedReposResult! # Newest based on created timestamp
|
||||
|
||||
"""
|
||||
Returns all the images from the specified repo
|
||||
@@ -1887,14 +1921,10 @@ func (ec *executionContext) fieldContext_GlobalSearchResult_Page(ctx context.Con
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "ObjectCount":
|
||||
return ec.fieldContext_PageInfo_ObjectCount(ctx, field)
|
||||
case "PreviousPage":
|
||||
return ec.fieldContext_PageInfo_PreviousPage(ctx, field)
|
||||
case "NextPage":
|
||||
return ec.fieldContext_PageInfo_NextPage(ctx, field)
|
||||
case "Pages":
|
||||
return ec.fieldContext_PageInfo_Pages(ctx, field)
|
||||
case "TotalCount":
|
||||
return ec.fieldContext_PageInfo_TotalCount(ctx, field)
|
||||
case "ItemCount":
|
||||
return ec.fieldContext_PageInfo_ItemCount(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name)
|
||||
},
|
||||
@@ -3705,8 +3735,8 @@ func (ec *executionContext) fieldContext_PackageInfo_FixedVersion(ctx context.Co
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _PageInfo_ObjectCount(ctx context.Context, field graphql.CollectedField, obj *PageInfo) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_PageInfo_ObjectCount(ctx, field)
|
||||
func (ec *executionContext) _PageInfo_TotalCount(ctx context.Context, field graphql.CollectedField, obj *PageInfo) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_PageInfo_TotalCount(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
@@ -3719,7 +3749,7 @@ func (ec *executionContext) _PageInfo_ObjectCount(ctx context.Context, field gra
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.ObjectCount, nil
|
||||
return obj.TotalCount, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
@@ -3736,7 +3766,7 @@ func (ec *executionContext) _PageInfo_ObjectCount(ctx context.Context, field gra
|
||||
return ec.marshalNInt2int(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_PageInfo_ObjectCount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
func (ec *executionContext) fieldContext_PageInfo_TotalCount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "PageInfo",
|
||||
Field: field,
|
||||
@@ -3749,8 +3779,8 @@ func (ec *executionContext) fieldContext_PageInfo_ObjectCount(ctx context.Contex
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _PageInfo_PreviousPage(ctx context.Context, field graphql.CollectedField, obj *PageInfo) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_PageInfo_PreviousPage(ctx, field)
|
||||
func (ec *executionContext) _PageInfo_ItemCount(ctx context.Context, field graphql.CollectedField, obj *PageInfo) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_PageInfo_ItemCount(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
@@ -3763,21 +3793,24 @@ func (ec *executionContext) _PageInfo_PreviousPage(ctx context.Context, field gr
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.PreviousPage, nil
|
||||
return obj.ItemCount, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*int)
|
||||
res := resTmp.(int)
|
||||
fc.Result = res
|
||||
return ec.marshalOInt2ᚖint(ctx, field.Selections, res)
|
||||
return ec.marshalNInt2int(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_PageInfo_PreviousPage(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
func (ec *executionContext) fieldContext_PageInfo_ItemCount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "PageInfo",
|
||||
Field: field,
|
||||
@@ -3790,8 +3823,8 @@ func (ec *executionContext) fieldContext_PageInfo_PreviousPage(ctx context.Conte
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _PageInfo_NextPage(ctx context.Context, field graphql.CollectedField, obj *PageInfo) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_PageInfo_NextPage(ctx, field)
|
||||
func (ec *executionContext) _PaginatedImagesResult_Page(ctx context.Context, field graphql.CollectedField, obj *PaginatedImagesResult) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_PaginatedImagesResult_Page(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
@@ -3804,7 +3837,7 @@ func (ec *executionContext) _PageInfo_NextPage(ctx context.Context, field graphq
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.NextPage, nil
|
||||
return obj.Page, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
@@ -3813,26 +3846,32 @@ func (ec *executionContext) _PageInfo_NextPage(ctx context.Context, field graphq
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*int)
|
||||
res := resTmp.(*PageInfo)
|
||||
fc.Result = res
|
||||
return ec.marshalOInt2ᚖint(ctx, field.Selections, res)
|
||||
return ec.marshalOPageInfo2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐPageInfo(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_PageInfo_NextPage(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
func (ec *executionContext) fieldContext_PaginatedImagesResult_Page(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "PageInfo",
|
||||
Object: "PaginatedImagesResult",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type Int does not have child fields")
|
||||
switch field.Name {
|
||||
case "TotalCount":
|
||||
return ec.fieldContext_PageInfo_TotalCount(ctx, field)
|
||||
case "ItemCount":
|
||||
return ec.fieldContext_PageInfo_ItemCount(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name)
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _PageInfo_Pages(ctx context.Context, field graphql.CollectedField, obj *PageInfo) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_PageInfo_Pages(ctx, field)
|
||||
func (ec *executionContext) _PaginatedImagesResult_Results(ctx context.Context, field graphql.CollectedField, obj *PaginatedImagesResult) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_PaginatedImagesResult_Results(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
@@ -3845,7 +3884,95 @@ func (ec *executionContext) _PageInfo_Pages(ctx context.Context, field graphql.C
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Pages, nil
|
||||
return obj.Results, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]*ImageSummary)
|
||||
fc.Result = res
|
||||
return ec.marshalNImageSummary2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐImageSummaryᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_PaginatedImagesResult_Results(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "PaginatedImagesResult",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "RepoName":
|
||||
return ec.fieldContext_ImageSummary_RepoName(ctx, field)
|
||||
case "Tag":
|
||||
return ec.fieldContext_ImageSummary_Tag(ctx, field)
|
||||
case "Digest":
|
||||
return ec.fieldContext_ImageSummary_Digest(ctx, field)
|
||||
case "ConfigDigest":
|
||||
return ec.fieldContext_ImageSummary_ConfigDigest(ctx, field)
|
||||
case "LastUpdated":
|
||||
return ec.fieldContext_ImageSummary_LastUpdated(ctx, field)
|
||||
case "IsSigned":
|
||||
return ec.fieldContext_ImageSummary_IsSigned(ctx, field)
|
||||
case "Size":
|
||||
return ec.fieldContext_ImageSummary_Size(ctx, field)
|
||||
case "Platform":
|
||||
return ec.fieldContext_ImageSummary_Platform(ctx, field)
|
||||
case "Vendor":
|
||||
return ec.fieldContext_ImageSummary_Vendor(ctx, field)
|
||||
case "Score":
|
||||
return ec.fieldContext_ImageSummary_Score(ctx, field)
|
||||
case "DownloadCount":
|
||||
return ec.fieldContext_ImageSummary_DownloadCount(ctx, field)
|
||||
case "Layers":
|
||||
return ec.fieldContext_ImageSummary_Layers(ctx, field)
|
||||
case "Description":
|
||||
return ec.fieldContext_ImageSummary_Description(ctx, field)
|
||||
case "Licenses":
|
||||
return ec.fieldContext_ImageSummary_Licenses(ctx, field)
|
||||
case "Labels":
|
||||
return ec.fieldContext_ImageSummary_Labels(ctx, field)
|
||||
case "Title":
|
||||
return ec.fieldContext_ImageSummary_Title(ctx, field)
|
||||
case "Source":
|
||||
return ec.fieldContext_ImageSummary_Source(ctx, field)
|
||||
case "Documentation":
|
||||
return ec.fieldContext_ImageSummary_Documentation(ctx, field)
|
||||
case "History":
|
||||
return ec.fieldContext_ImageSummary_History(ctx, field)
|
||||
case "Vulnerabilities":
|
||||
return ec.fieldContext_ImageSummary_Vulnerabilities(ctx, field)
|
||||
case "Authors":
|
||||
return ec.fieldContext_ImageSummary_Authors(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type ImageSummary", field.Name)
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _PaginatedReposResult_Page(ctx context.Context, field graphql.CollectedField, obj *PaginatedReposResult) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_PaginatedReposResult_Page(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Page, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
@@ -3854,19 +3981,93 @@ func (ec *executionContext) _PageInfo_Pages(ctx context.Context, field graphql.C
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*int)
|
||||
res := resTmp.(*PageInfo)
|
||||
fc.Result = res
|
||||
return ec.marshalOInt2ᚖint(ctx, field.Selections, res)
|
||||
return ec.marshalOPageInfo2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐPageInfo(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_PageInfo_Pages(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
func (ec *executionContext) fieldContext_PaginatedReposResult_Page(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "PageInfo",
|
||||
Object: "PaginatedReposResult",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type Int does not have child fields")
|
||||
switch field.Name {
|
||||
case "TotalCount":
|
||||
return ec.fieldContext_PageInfo_TotalCount(ctx, field)
|
||||
case "ItemCount":
|
||||
return ec.fieldContext_PageInfo_ItemCount(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name)
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _PaginatedReposResult_Results(ctx context.Context, field graphql.CollectedField, obj *PaginatedReposResult) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_PaginatedReposResult_Results(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Results, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]*RepoSummary)
|
||||
fc.Result = res
|
||||
return ec.marshalNRepoSummary2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐRepoSummaryᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_PaginatedReposResult_Results(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "PaginatedReposResult",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "Name":
|
||||
return ec.fieldContext_RepoSummary_Name(ctx, field)
|
||||
case "LastUpdated":
|
||||
return ec.fieldContext_RepoSummary_LastUpdated(ctx, field)
|
||||
case "Size":
|
||||
return ec.fieldContext_RepoSummary_Size(ctx, field)
|
||||
case "Platforms":
|
||||
return ec.fieldContext_RepoSummary_Platforms(ctx, field)
|
||||
case "Vendors":
|
||||
return ec.fieldContext_RepoSummary_Vendors(ctx, field)
|
||||
case "Score":
|
||||
return ec.fieldContext_RepoSummary_Score(ctx, field)
|
||||
case "NewestImage":
|
||||
return ec.fieldContext_RepoSummary_NewestImage(ctx, field)
|
||||
case "DownloadCount":
|
||||
return ec.fieldContext_RepoSummary_DownloadCount(ctx, field)
|
||||
case "StarCount":
|
||||
return ec.fieldContext_RepoSummary_StarCount(ctx, field)
|
||||
case "IsBookmarked":
|
||||
return ec.fieldContext_RepoSummary_IsBookmarked(ctx, field)
|
||||
case "IsStarred":
|
||||
return ec.fieldContext_RepoSummary_IsStarred(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type RepoSummary", field.Name)
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
@@ -4247,9 +4448,9 @@ func (ec *executionContext) _Query_RepoListWithNewestImage(ctx context.Context,
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]*RepoSummary)
|
||||
res := resTmp.(*PaginatedReposResult)
|
||||
fc.Result = res
|
||||
return ec.marshalNRepoSummary2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐRepoSummaryᚄ(ctx, field.Selections, res)
|
||||
return ec.marshalNPaginatedReposResult2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐPaginatedReposResult(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Query_RepoListWithNewestImage(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
@@ -4260,30 +4461,12 @@ func (ec *executionContext) fieldContext_Query_RepoListWithNewestImage(ctx conte
|
||||
IsResolver: true,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "Name":
|
||||
return ec.fieldContext_RepoSummary_Name(ctx, field)
|
||||
case "LastUpdated":
|
||||
return ec.fieldContext_RepoSummary_LastUpdated(ctx, field)
|
||||
case "Size":
|
||||
return ec.fieldContext_RepoSummary_Size(ctx, field)
|
||||
case "Platforms":
|
||||
return ec.fieldContext_RepoSummary_Platforms(ctx, field)
|
||||
case "Vendors":
|
||||
return ec.fieldContext_RepoSummary_Vendors(ctx, field)
|
||||
case "Score":
|
||||
return ec.fieldContext_RepoSummary_Score(ctx, field)
|
||||
case "NewestImage":
|
||||
return ec.fieldContext_RepoSummary_NewestImage(ctx, field)
|
||||
case "DownloadCount":
|
||||
return ec.fieldContext_RepoSummary_DownloadCount(ctx, field)
|
||||
case "StarCount":
|
||||
return ec.fieldContext_RepoSummary_StarCount(ctx, field)
|
||||
case "IsBookmarked":
|
||||
return ec.fieldContext_RepoSummary_IsBookmarked(ctx, field)
|
||||
case "IsStarred":
|
||||
return ec.fieldContext_RepoSummary_IsStarred(ctx, field)
|
||||
case "Page":
|
||||
return ec.fieldContext_PaginatedReposResult_Page(ctx, field)
|
||||
case "Results":
|
||||
return ec.fieldContext_PaginatedReposResult_Results(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type RepoSummary", field.Name)
|
||||
return nil, fmt.Errorf("no field named %q was found under type PaginatedReposResult", field.Name)
|
||||
},
|
||||
}
|
||||
defer func() {
|
||||
@@ -8185,25 +8368,84 @@ func (ec *executionContext) _PageInfo(ctx context.Context, sel ast.SelectionSet,
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("PageInfo")
|
||||
case "ObjectCount":
|
||||
case "TotalCount":
|
||||
|
||||
out.Values[i] = ec._PageInfo_ObjectCount(ctx, field, obj)
|
||||
out.Values[i] = ec._PageInfo_TotalCount(ctx, field, obj)
|
||||
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "PreviousPage":
|
||||
case "ItemCount":
|
||||
|
||||
out.Values[i] = ec._PageInfo_PreviousPage(ctx, field, obj)
|
||||
out.Values[i] = ec._PageInfo_ItemCount(ctx, field, obj)
|
||||
|
||||
case "NextPage":
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
out.Values[i] = ec._PageInfo_NextPage(ctx, field, obj)
|
||||
var paginatedImagesResultImplementors = []string{"PaginatedImagesResult"}
|
||||
|
||||
case "Pages":
|
||||
func (ec *executionContext) _PaginatedImagesResult(ctx context.Context, sel ast.SelectionSet, obj *PaginatedImagesResult) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, paginatedImagesResultImplementors)
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("PaginatedImagesResult")
|
||||
case "Page":
|
||||
|
||||
out.Values[i] = ec._PageInfo_Pages(ctx, field, obj)
|
||||
out.Values[i] = ec._PaginatedImagesResult_Page(ctx, field, obj)
|
||||
|
||||
case "Results":
|
||||
|
||||
out.Values[i] = ec._PaginatedImagesResult_Results(ctx, field, obj)
|
||||
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var paginatedReposResultImplementors = []string{"PaginatedReposResult"}
|
||||
|
||||
func (ec *executionContext) _PaginatedReposResult(ctx context.Context, sel ast.SelectionSet, obj *PaginatedReposResult) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, paginatedReposResultImplementors)
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("PaginatedReposResult")
|
||||
case "Page":
|
||||
|
||||
out.Values[i] = ec._PaginatedReposResult_Page(ctx, field, obj)
|
||||
|
||||
case "Results":
|
||||
|
||||
out.Values[i] = ec._PaginatedReposResult_Results(ctx, field, obj)
|
||||
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
@@ -9049,6 +9291,50 @@ func (ec *executionContext) marshalNGlobalSearchResult2ᚖzotregistryᚗioᚋzot
|
||||
return ec._GlobalSearchResult(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNImageSummary2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐImageSummaryᚄ(ctx context.Context, sel ast.SelectionSet, v []*ImageSummary) graphql.Marshaler {
|
||||
ret := make(graphql.Array, len(v))
|
||||
var wg sync.WaitGroup
|
||||
isLen1 := len(v) == 1
|
||||
if !isLen1 {
|
||||
wg.Add(len(v))
|
||||
}
|
||||
for i := range v {
|
||||
i := i
|
||||
fc := &graphql.FieldContext{
|
||||
Index: &i,
|
||||
Result: &v[i],
|
||||
}
|
||||
ctx := graphql.WithFieldContext(ctx, fc)
|
||||
f := func(i int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = nil
|
||||
}
|
||||
}()
|
||||
if !isLen1 {
|
||||
defer wg.Done()
|
||||
}
|
||||
ret[i] = ec.marshalNImageSummary2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐImageSummary(ctx, sel, v[i])
|
||||
}
|
||||
if isLen1 {
|
||||
f(i)
|
||||
} else {
|
||||
go f(i)
|
||||
}
|
||||
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
for _, e := range ret {
|
||||
if e == graphql.Null {
|
||||
return graphql.Null
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNImageSummary2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐImageSummary(ctx context.Context, sel ast.SelectionSet, v *ImageSummary) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
@@ -9074,6 +9360,20 @@ func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.Selecti
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNPaginatedReposResult2zotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐPaginatedReposResult(ctx context.Context, sel ast.SelectionSet, v PaginatedReposResult) graphql.Marshaler {
|
||||
return ec._PaginatedReposResult(ctx, sel, &v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNPaginatedReposResult2ᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐPaginatedReposResult(ctx context.Context, sel ast.SelectionSet, v *PaginatedReposResult) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._PaginatedReposResult(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNReferrer2ᚕᚖzotregistryᚗioᚋzotᚋpkgᚋextensionsᚋsearchᚋgql_generatedᚐReferrer(ctx context.Context, sel ast.SelectionSet, v []*Referrer) graphql.Marshaler {
|
||||
ret := make(graphql.Array, len(v))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
@@ -111,10 +111,8 @@ type PackageInfo struct {
|
||||
}
|
||||
|
||||
type PageInfo struct {
|
||||
ObjectCount int `json:"ObjectCount"`
|
||||
PreviousPage *int `json:"PreviousPage"`
|
||||
NextPage *int `json:"NextPage"`
|
||||
Pages *int `json:"Pages"`
|
||||
TotalCount int `json:"TotalCount"`
|
||||
ItemCount int `json:"ItemCount"`
|
||||
}
|
||||
|
||||
type PageInput struct {
|
||||
@@ -123,6 +121,16 @@ type PageInput struct {
|
||||
SortBy *SortCriteria `json:"sortBy"`
|
||||
}
|
||||
|
||||
type PaginatedImagesResult struct {
|
||||
Page *PageInfo `json:"Page"`
|
||||
Results []*ImageSummary `json:"Results"`
|
||||
}
|
||||
|
||||
type PaginatedReposResult struct {
|
||||
Page *PageInfo `json:"Page"`
|
||||
Results []*RepoSummary `json:"Results"`
|
||||
}
|
||||
|
||||
type Referrer struct {
|
||||
MediaType *string `json:"MediaType"`
|
||||
ArtifactType *string `json:"ArtifactType"`
|
||||
|
||||
@@ -197,15 +197,16 @@ func repoListWithNewestImage(
|
||||
log log.Logger, //nolint:unparam // may be used by devs for debugging
|
||||
requestedPage *gql_generated.PageInput,
|
||||
repoDB repodb.RepoDB,
|
||||
) ([]*gql_generated.RepoSummary, error) {
|
||||
) (*gql_generated.PaginatedReposResult, error) {
|
||||
repos := []*gql_generated.RepoSummary{}
|
||||
paginatedRepos := &gql_generated.PaginatedReposResult{}
|
||||
|
||||
if requestedPage == nil {
|
||||
requestedPage = &gql_generated.PageInput{}
|
||||
}
|
||||
|
||||
skip := convert.SkipQGLField{
|
||||
Vulnerabilities: canSkipField(convert.GetPreloads(ctx), "NewestImage.Vulnerabilities"),
|
||||
Vulnerabilities: canSkipField(convert.GetPreloads(ctx), "Results.NewestImage.Vulnerabilities"),
|
||||
}
|
||||
|
||||
pageInput := repodb.PageInput{
|
||||
@@ -216,9 +217,9 @@ func repoListWithNewestImage(
|
||||
),
|
||||
}
|
||||
|
||||
reposMeta, manifestMetaMap, err := repoDB.SearchRepos(ctx, "", repodb.Filter{}, pageInput)
|
||||
reposMeta, manifestMetaMap, pageInfo, err := repoDB.SearchRepos(ctx, "", repodb.Filter{}, pageInput)
|
||||
if err != nil {
|
||||
return []*gql_generated.RepoSummary{}, err
|
||||
return &gql_generated.PaginatedReposResult{}, err
|
||||
}
|
||||
|
||||
for _, repoMeta := range reposMeta {
|
||||
@@ -226,15 +227,22 @@ func repoListWithNewestImage(
|
||||
repos = append(repos, repoSummary)
|
||||
}
|
||||
|
||||
return repos, nil
|
||||
paginatedRepos.Page = &gql_generated.PageInfo{
|
||||
TotalCount: pageInfo.TotalCount,
|
||||
ItemCount: pageInfo.ItemCount,
|
||||
}
|
||||
paginatedRepos.Results = repos
|
||||
|
||||
return paginatedRepos, nil
|
||||
}
|
||||
|
||||
func globalSearch(ctx context.Context, query string, repoDB repodb.RepoDB, filter *gql_generated.Filter,
|
||||
requestedPage *gql_generated.PageInput, cveInfo cveinfo.CveInfo, log log.Logger, //nolint:unparam
|
||||
) ([]*gql_generated.RepoSummary, []*gql_generated.ImageSummary, []*gql_generated.LayerSummary, error,
|
||||
) (*gql_generated.PaginatedReposResult, []*gql_generated.ImageSummary, []*gql_generated.LayerSummary, error,
|
||||
) {
|
||||
preloads := convert.GetPreloads(ctx)
|
||||
repos := []*gql_generated.RepoSummary{}
|
||||
paginatedRepos := gql_generated.PaginatedReposResult{}
|
||||
images := []*gql_generated.ImageSummary{}
|
||||
layers := []*gql_generated.LayerSummary{}
|
||||
|
||||
@@ -264,9 +272,9 @@ func globalSearch(ctx context.Context, query string, repoDB repodb.RepoDB, filte
|
||||
),
|
||||
}
|
||||
|
||||
reposMeta, manifestMetaMap, err := repoDB.SearchRepos(ctx, query, localFilter, pageInput)
|
||||
reposMeta, manifestMetaMap, pageInfo, err := repoDB.SearchRepos(ctx, query, localFilter, pageInput)
|
||||
if err != nil {
|
||||
return []*gql_generated.RepoSummary{}, []*gql_generated.ImageSummary{}, []*gql_generated.LayerSummary{}, err
|
||||
return &gql_generated.PaginatedReposResult{}, []*gql_generated.ImageSummary{}, []*gql_generated.LayerSummary{}, err
|
||||
}
|
||||
|
||||
for _, repoMeta := range reposMeta {
|
||||
@@ -274,6 +282,13 @@ func globalSearch(ctx context.Context, query string, repoDB repodb.RepoDB, filte
|
||||
|
||||
repos = append(repos, repoSummary)
|
||||
}
|
||||
|
||||
paginatedRepos.Page = &gql_generated.PageInfo{
|
||||
TotalCount: pageInfo.TotalCount,
|
||||
ItemCount: pageInfo.ItemCount,
|
||||
}
|
||||
|
||||
paginatedRepos.Results = repos
|
||||
} else { // search for images
|
||||
skip := convert.SkipQGLField{
|
||||
Vulnerabilities: canSkipField(preloads, "Images.Vulnerabilities"),
|
||||
@@ -287,9 +302,9 @@ func globalSearch(ctx context.Context, query string, repoDB repodb.RepoDB, filte
|
||||
),
|
||||
}
|
||||
|
||||
reposMeta, manifestMetaMap, err := repoDB.SearchTags(ctx, query, localFilter, pageInput)
|
||||
reposMeta, manifestMetaMap, pageInfo, err := repoDB.SearchTags(ctx, query, localFilter, pageInput)
|
||||
if err != nil {
|
||||
return []*gql_generated.RepoSummary{}, []*gql_generated.ImageSummary{}, []*gql_generated.LayerSummary{}, err
|
||||
return &gql_generated.PaginatedReposResult{}, []*gql_generated.ImageSummary{}, []*gql_generated.LayerSummary{}, err
|
||||
}
|
||||
|
||||
for _, repoMeta := range reposMeta {
|
||||
@@ -297,9 +312,14 @@ func globalSearch(ctx context.Context, query string, repoDB repodb.RepoDB, filte
|
||||
|
||||
images = append(images, imageSummaries...)
|
||||
}
|
||||
|
||||
paginatedRepos.Page = &gql_generated.PageInfo{
|
||||
TotalCount: pageInfo.TotalCount,
|
||||
ItemCount: pageInfo.ItemCount,
|
||||
}
|
||||
}
|
||||
|
||||
return repos, images, layers, nil
|
||||
return &paginatedRepos, images, layers, nil
|
||||
}
|
||||
|
||||
func canSkipField(preloads map[string]bool, s string) bool {
|
||||
|
||||
@@ -31,8 +31,8 @@ func TestGlobalSearch(t *testing.T) {
|
||||
Convey("RepoDB SearchRepos error", func() {
|
||||
mockRepoDB := mocks.RepoDBMock{
|
||||
SearchReposFn: func(ctx context.Context, searchText string, filter repodb.Filter, requestedPage repodb.PageInput,
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, error) {
|
||||
return make([]repodb.RepoMetadata, 0), make(map[string]repodb.ManifestMetadata), ErrTestError
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, repodb.PageInfo, error) {
|
||||
return make([]repodb.RepoMetadata, 0), make(map[string]repodb.ManifestMetadata), repodb.PageInfo{}, ErrTestError
|
||||
},
|
||||
}
|
||||
responseContext := graphql.WithResponseContext(context.Background(), graphql.DefaultErrorPresenter,
|
||||
@@ -43,13 +43,13 @@ func TestGlobalSearch(t *testing.T) {
|
||||
So(err, ShouldNotBeNil)
|
||||
So(images, ShouldBeEmpty)
|
||||
So(layers, ShouldBeEmpty)
|
||||
So(repos, ShouldBeEmpty)
|
||||
So(repos.Results, ShouldBeEmpty)
|
||||
})
|
||||
|
||||
Convey("RepoDB SearchRepo is successful", func() {
|
||||
mockRepoDB := mocks.RepoDBMock{
|
||||
SearchReposFn: func(ctx context.Context, searchText string, filter repodb.Filter, requestedPage repodb.PageInput,
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, error) {
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, repodb.PageInfo, error) {
|
||||
repos := []repodb.RepoMetadata{
|
||||
{
|
||||
Name: "repo1",
|
||||
@@ -101,7 +101,7 @@ func TestGlobalSearch(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
return repos, manifestMetas, nil
|
||||
return repos, manifestMetas, repodb.PageInfo{}, nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -123,14 +123,14 @@ func TestGlobalSearch(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
So(images, ShouldBeEmpty)
|
||||
So(layers, ShouldBeEmpty)
|
||||
So(repos, ShouldNotBeEmpty)
|
||||
So(len(repos[0].Vendors), ShouldEqual, 2)
|
||||
So(repos.Results, ShouldNotBeEmpty)
|
||||
So(len(repos.Results[0].Vendors), ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("RepoDB SearchRepo Bad manifest referenced", func() {
|
||||
mockRepoDB := mocks.RepoDBMock{
|
||||
SearchReposFn: func(ctx context.Context, searchText string, filter repodb.Filter, requestedPage repodb.PageInput,
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, error) {
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, repodb.PageInfo, error) {
|
||||
repos := []repodb.RepoMetadata{
|
||||
{
|
||||
Name: "repo1",
|
||||
@@ -154,7 +154,7 @@ func TestGlobalSearch(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
return repos, manifestMetas, nil
|
||||
return repos, manifestMetas, repodb.PageInfo{}, nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -188,13 +188,13 @@ func TestGlobalSearch(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
So(images, ShouldBeEmpty)
|
||||
So(layers, ShouldBeEmpty)
|
||||
So(repos, ShouldBeEmpty)
|
||||
So(repos.Results, ShouldBeEmpty)
|
||||
})
|
||||
|
||||
Convey("RepoDB SearchRepo good manifest referenced and bad config blob", func() {
|
||||
mockRepoDB := mocks.RepoDBMock{
|
||||
SearchReposFn: func(ctx context.Context, searchText string, filter repodb.Filter, requestedPage repodb.PageInput,
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, error) {
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, repodb.PageInfo, error) {
|
||||
repos := []repodb.RepoMetadata{
|
||||
{
|
||||
Name: "repo1",
|
||||
@@ -218,7 +218,7 @@ func TestGlobalSearch(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
return repos, manifestMetas, nil
|
||||
return repos, manifestMetas, repodb.PageInfo{}, nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ func TestGlobalSearch(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
So(images, ShouldBeEmpty)
|
||||
So(layers, ShouldBeEmpty)
|
||||
So(repos, ShouldNotBeEmpty)
|
||||
So(repos.Results, ShouldNotBeEmpty)
|
||||
|
||||
query = "repo1:1.0.1"
|
||||
responseContext = graphql.WithResponseContext(context.Background(), graphql.DefaultErrorPresenter,
|
||||
@@ -251,14 +251,14 @@ func TestGlobalSearch(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
So(images, ShouldBeEmpty)
|
||||
So(layers, ShouldBeEmpty)
|
||||
So(repos, ShouldBeEmpty)
|
||||
So(repos.Results, ShouldBeEmpty)
|
||||
})
|
||||
|
||||
Convey("RepoDB SearchTags gives error", func() {
|
||||
mockRepoDB := mocks.RepoDBMock{
|
||||
SearchTagsFn: func(ctx context.Context, searchText string, filter repodb.Filter, requestedPage repodb.PageInput,
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, error) {
|
||||
return make([]repodb.RepoMetadata, 0), make(map[string]repodb.ManifestMetadata), ErrTestError
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, repodb.PageInfo, error) {
|
||||
return make([]repodb.RepoMetadata, 0), make(map[string]repodb.ManifestMetadata), repodb.PageInfo{}, ErrTestError
|
||||
},
|
||||
}
|
||||
const query = "repo1:1.0.1"
|
||||
@@ -271,13 +271,13 @@ func TestGlobalSearch(t *testing.T) {
|
||||
So(err, ShouldNotBeNil)
|
||||
So(images, ShouldBeEmpty)
|
||||
So(layers, ShouldBeEmpty)
|
||||
So(repos, ShouldBeEmpty)
|
||||
So(repos.Results, ShouldBeEmpty)
|
||||
})
|
||||
|
||||
Convey("RepoDB SearchTags is successful", func() {
|
||||
mockRepoDB := mocks.RepoDBMock{
|
||||
SearchTagsFn: func(ctx context.Context, searchText string, filter repodb.Filter, requestedPage repodb.PageInput,
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, error) {
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, repodb.PageInfo, error) {
|
||||
repos := []repodb.RepoMetadata{
|
||||
{
|
||||
Name: "repo1",
|
||||
@@ -323,7 +323,7 @@ func TestGlobalSearch(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
return repos, manifestMetas, nil
|
||||
return repos, manifestMetas, repodb.PageInfo{}, nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ func TestGlobalSearch(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
So(images, ShouldNotBeEmpty)
|
||||
So(layers, ShouldBeEmpty)
|
||||
So(repos, ShouldBeEmpty)
|
||||
So(repos.Results, ShouldBeEmpty)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -356,8 +356,8 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
Convey("RepoDB SearchRepos error", func() {
|
||||
mockRepoDB := mocks.RepoDBMock{
|
||||
SearchReposFn: func(ctx context.Context, searchText string, filter repodb.Filter, requestedPage repodb.PageInput,
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, error) {
|
||||
return make([]repodb.RepoMetadata, 0), make(map[string]repodb.ManifestMetadata), ErrTestError
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, repodb.PageInfo, error) {
|
||||
return make([]repodb.RepoMetadata, 0), make(map[string]repodb.ManifestMetadata), repodb.PageInfo{}, ErrTestError
|
||||
},
|
||||
}
|
||||
responseContext := graphql.WithResponseContext(context.Background(), graphql.DefaultErrorPresenter,
|
||||
@@ -374,13 +374,13 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
}
|
||||
repos, err := repoListWithNewestImage(responseContext, mockCve, log.NewLogger("debug", ""), &pageInput, mockRepoDB)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(repos, ShouldBeEmpty)
|
||||
So(repos.Results, ShouldBeEmpty)
|
||||
})
|
||||
|
||||
Convey("RepoDB SearchRepo Bad manifest referenced", func() {
|
||||
mockRepoDB := mocks.RepoDBMock{
|
||||
SearchReposFn: func(ctx context.Context, searchText string, filter repodb.Filter, requestedPage repodb.PageInput,
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, error) {
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, repodb.PageInfo, error) {
|
||||
repos := []repodb.RepoMetadata{
|
||||
{
|
||||
Name: "repo1",
|
||||
@@ -422,7 +422,7 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
return repos, manifestMetas, nil
|
||||
return repos, manifestMetas, repodb.PageInfo{}, nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
}
|
||||
repos, err := repoListWithNewestImage(responseContext, mockCve, log.NewLogger("debug", ""), &pageInput, mockRepoDB)
|
||||
So(err, ShouldBeNil)
|
||||
So(repos, ShouldNotBeEmpty)
|
||||
So(repos.Results, ShouldNotBeEmpty)
|
||||
})
|
||||
|
||||
Convey("Working SearchRepo function", func() {
|
||||
@@ -448,7 +448,7 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
createTime2 := createTime.Add(time.Second)
|
||||
mockRepoDB := mocks.RepoDBMock{
|
||||
SearchReposFn: func(ctx context.Context, searchText string, filter repodb.Filter, requestedPage repodb.PageInput,
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, error) {
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, repodb.PageInfo, error) {
|
||||
pageFinder, err := repodb.NewBaseRepoPageFinder(requestedPage.Limit, requestedPage.Offset, requestedPage.SortBy)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
@@ -483,7 +483,7 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
createTime = createTime.Add(time.Second)
|
||||
}
|
||||
|
||||
repos = pageFinder.Page()
|
||||
repos, _ = pageFinder.Page()
|
||||
|
||||
configBlob1, err := json.Marshal(ispec.Image{
|
||||
Config: ispec.ImageConfig{
|
||||
@@ -515,7 +515,7 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
return repos, manifestMetas, nil
|
||||
return repos, manifestMetas, repodb.PageInfo{}, nil
|
||||
},
|
||||
}
|
||||
Convey("RepoDB missing requestedPage", func() {
|
||||
@@ -524,7 +524,7 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
mockCve := mocks.CveInfoMock{}
|
||||
repos, err := repoListWithNewestImage(responseContext, mockCve, log.NewLogger("debug", ""), nil, mockRepoDB)
|
||||
So(err, ShouldBeNil)
|
||||
So(repos, ShouldNotBeEmpty)
|
||||
So(repos.Results, ShouldNotBeEmpty)
|
||||
})
|
||||
|
||||
Convey("RepoDB SearchRepo is successful", func() {
|
||||
@@ -545,9 +545,9 @@ func TestRepoListWithNewestImage(t *testing.T) {
|
||||
log.NewLogger("debug", ""), &pageInput, mockRepoDB)
|
||||
So(err, ShouldBeNil)
|
||||
So(repos, ShouldNotBeEmpty)
|
||||
So(len(repos), ShouldEqual, 2)
|
||||
So(*repos[0].Name, ShouldEqual, "repo2")
|
||||
So(*repos[0].LastUpdated, ShouldEqual, createTime2)
|
||||
So(len(repos.Results), ShouldEqual, 2)
|
||||
So(*repos.Results[0].Name, ShouldEqual, "repo2")
|
||||
So(*repos.Results[0].LastUpdated, ShouldEqual, createTime2)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -960,7 +960,7 @@ func TestImageListForDigest(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
repos = pageFinder.Page()
|
||||
repos, _ = pageFinder.Page()
|
||||
|
||||
return repos, manifestMetaDatas, nil
|
||||
},
|
||||
@@ -1264,8 +1264,8 @@ func TestQueryResolverErrors(t *testing.T) {
|
||||
mocks.RepoDBMock{
|
||||
SearchReposFn: func(ctx context.Context, searchText string, filter repodb.Filter,
|
||||
requestedPage repodb.PageInput,
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, error) {
|
||||
return nil, nil, ErrTestError
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, repodb.PageInfo, error) {
|
||||
return nil, nil, repodb.PageInfo{}, ErrTestError
|
||||
},
|
||||
},
|
||||
mocks.CveInfoMock{},
|
||||
@@ -1347,8 +1347,8 @@ func TestQueryResolverErrors(t *testing.T) {
|
||||
mocks.RepoDBMock{
|
||||
SearchReposFn: func(ctx context.Context, searchText string,
|
||||
filter repodb.Filter, requestedPage repodb.PageInput,
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, error) {
|
||||
return nil, nil, ErrTestError
|
||||
) ([]repodb.RepoMetadata, map[string]repodb.ManifestMetadata, repodb.PageInfo, error) {
|
||||
return nil, nil, repodb.PageInfo{}, ErrTestError
|
||||
},
|
||||
},
|
||||
mocks.CveInfoMock{},
|
||||
|
||||
@@ -167,10 +167,8 @@ enum SortCriteria {
|
||||
}
|
||||
|
||||
type PageInfo {
|
||||
ObjectCount: Int!
|
||||
PreviousPage: Int
|
||||
NextPage: Int
|
||||
Pages: Int
|
||||
TotalCount: Int!
|
||||
ItemCount: Int!
|
||||
}
|
||||
|
||||
# Pagination parameters
|
||||
@@ -180,6 +178,20 @@ input PageInput {
|
||||
sortBy: SortCriteria
|
||||
}
|
||||
|
||||
# Paginated list of RepoSummary objects
|
||||
# If limit is -1, pagination is disabled
|
||||
type PaginatedReposResult {
|
||||
Page: PageInfo
|
||||
Results: [RepoSummary!]!
|
||||
}
|
||||
|
||||
# Paginated list of ImageSummary objects
|
||||
# If limit is -1, pagination is disabled
|
||||
type PaginatedImagesResult {
|
||||
Page: PageInfo
|
||||
Results: [ImageSummary!]!
|
||||
}
|
||||
|
||||
input Filter {
|
||||
Os: [String]
|
||||
Arch: [String]
|
||||
@@ -210,7 +222,7 @@ type Query {
|
||||
"""
|
||||
Returns a list of repos with the newest tag within
|
||||
"""
|
||||
RepoListWithNewestImage(requestedPage: PageInput): [RepoSummary!]! # Newest based on created timestamp
|
||||
RepoListWithNewestImage(requestedPage: PageInput): PaginatedReposResult! # Newest based on created timestamp
|
||||
|
||||
"""
|
||||
Returns all the images from the specified repo
|
||||
|
||||
@@ -172,17 +172,17 @@ func (r *queryResolver) ImageListForDigest(ctx context.Context, id string, reque
|
||||
}
|
||||
|
||||
// RepoListWithNewestImage is the resolver for the RepoListWithNewestImage field.
|
||||
func (r *queryResolver) RepoListWithNewestImage(ctx context.Context, requestedPage *gql_generated.PageInput) ([]*gql_generated.RepoSummary, error) {
|
||||
func (r *queryResolver) RepoListWithNewestImage(ctx context.Context, requestedPage *gql_generated.PageInput) (*gql_generated.PaginatedReposResult, error) {
|
||||
r.log.Info().Msg("extension api: finding image list")
|
||||
|
||||
reposSummary, err := repoListWithNewestImage(ctx, r.cveInfo, r.log, requestedPage, r.repoDB)
|
||||
paginatedReposResult, err := repoListWithNewestImage(ctx, r.cveInfo, r.log, requestedPage, r.repoDB)
|
||||
if err != nil {
|
||||
r.log.Error().Err(err).Msg("unable to retrieve repo list")
|
||||
|
||||
return reposSummary, err
|
||||
return paginatedReposResult, err
|
||||
}
|
||||
|
||||
return reposSummary, nil
|
||||
return paginatedReposResult, nil
|
||||
}
|
||||
|
||||
// ImageList is the resolver for the ImageList field.
|
||||
@@ -238,11 +238,12 @@ func (r *queryResolver) GlobalSearch(ctx context.Context, query string, filter *
|
||||
query = cleanQuery(query)
|
||||
filter = cleanFilter(filter)
|
||||
|
||||
repos, images, layers, err := globalSearch(ctx, query, r.repoDB, filter, requestedPage, r.cveInfo, r.log)
|
||||
paginatedReposResult, images, layers, err := globalSearch(ctx, query, r.repoDB, filter, requestedPage, r.cveInfo, r.log)
|
||||
|
||||
return &gql_generated.GlobalSearchResult{
|
||||
Page: paginatedReposResult.Page,
|
||||
Images: images,
|
||||
Repos: repos,
|
||||
Repos: paginatedReposResult.Results,
|
||||
Layers: layers,
|
||||
}, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user