mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-19 15:17:43 +01:00
Iterate all paginations when listing projects and repositories (#7660)
Iterate all paginations when listing projects and repositories Signed-off-by: Wenkai Yin <yinw@vmware.com>
This commit is contained in:
parent
09c5f9cfc8
commit
d74624d306
@ -17,9 +17,13 @@ package http
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/common/http/modifier"
|
"github.com/goharbor/harbor/src/common/http/modifier"
|
||||||
)
|
)
|
||||||
@ -168,3 +172,63 @@ func (c *Client) do(req *http.Request) ([]byte, error) {
|
|||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAndIteratePagination iterates the pagination header and returns all resources
|
||||||
|
// The parameter "v" must be a pointer to a slice
|
||||||
|
func (c *Client) GetAndIteratePagination(endpoint string, v interface{}) error {
|
||||||
|
url, err := url.Parse(endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rv := reflect.ValueOf(v)
|
||||||
|
if rv.Kind() != reflect.Ptr {
|
||||||
|
return errors.New("v should be a pointer to a slice")
|
||||||
|
}
|
||||||
|
elemType := rv.Elem().Type()
|
||||||
|
if elemType.Kind() != reflect.Slice {
|
||||||
|
return errors.New("v should be a pointer to a slice")
|
||||||
|
}
|
||||||
|
|
||||||
|
resources := reflect.Indirect(reflect.New(elemType))
|
||||||
|
for len(endpoint) > 0 {
|
||||||
|
req, err := http.NewRequest(http.MethodGet, endpoint, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resp, err := c.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if resp.StatusCode < 200 || resp.StatusCode > 299 {
|
||||||
|
return &Error{
|
||||||
|
Code: resp.StatusCode,
|
||||||
|
Message: string(data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res := reflect.New(elemType)
|
||||||
|
if err = json.Unmarshal(data, res.Interface()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resources = reflect.AppendSlice(resources, reflect.Indirect(res))
|
||||||
|
|
||||||
|
endpoint = ""
|
||||||
|
link := resp.Header.Get("Link")
|
||||||
|
for _, str := range strings.Split(link, ",") {
|
||||||
|
if strings.HasSuffix(str, `rel="next"`) &&
|
||||||
|
strings.Index(str, "<") >= 0 &&
|
||||||
|
strings.Index(str, ">") >= 0 {
|
||||||
|
endpoint = url.Scheme + "://" + url.Host + str[strings.Index(str, "<")+1:strings.Index(str, ">")]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rv.Elem().Set(resources)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -211,8 +211,8 @@ type project struct {
|
|||||||
|
|
||||||
func (a *adapter) getProjects(name string) ([]*project, error) {
|
func (a *adapter) getProjects(name string) ([]*project, error) {
|
||||||
projects := []*project{}
|
projects := []*project{}
|
||||||
url := fmt.Sprintf("%s/api/projects?name=%s&page=1&page_size=1000", a.coreServiceURL, name)
|
url := fmt.Sprintf("%s/api/projects?name=%s&page=1&page_size=500", a.coreServiceURL, name)
|
||||||
if err := a.client.Get(url, &projects); err != nil {
|
if err := a.client.GetAndIteratePagination(url, &projects); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return projects, nil
|
return projects, nil
|
||||||
@ -243,3 +243,12 @@ func (a *adapter) getProject(name string) (*project, error) {
|
|||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *adapter) getRepositories(projectID int64) ([]*repository, error) {
|
||||||
|
repositories := []*repository{}
|
||||||
|
url := fmt.Sprintf("%s/api/repositories?project_id=%d&page=1&page_size=500", a.coreServiceURL, projectID)
|
||||||
|
if err := a.client.GetAndIteratePagination(url, &repositories); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return repositories, nil
|
||||||
|
}
|
||||||
|
@ -64,9 +64,8 @@ func (a *adapter) FetchImages(filters []*model.Filter) ([]*model.Resource, error
|
|||||||
}
|
}
|
||||||
resources := []*model.Resource{}
|
resources := []*model.Resource{}
|
||||||
for _, project := range projects {
|
for _, project := range projects {
|
||||||
repositories := []*repository{}
|
repositories, err := a.getRepositories(project.ID)
|
||||||
url := fmt.Sprintf("%s/api/repositories?project_id=%d", a.coreServiceURL, project.ID)
|
if err != nil {
|
||||||
if err = a.client.Get(url, &repositories); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
repositories, err = filterRepositories(repositories, filters)
|
repositories, err = filterRepositories(repositories, filters)
|
||||||
|
Loading…
Reference in New Issue
Block a user