FIX AliACR Provider.

1. Pagination.
2. Resource filter.

Signed-off-by: 慕薇疯魔 <kfanjian@gmail.com>
This commit is contained in:
慕薇疯魔 2019-12-29 12:07:18 +08:00
parent 69740fc396
commit ad01d68396
2 changed files with 103 additions and 23 deletions

View File

@ -7,7 +7,9 @@ import (
"net/http" "net/http"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/cr" "github.com/aliyun/alibaba-cloud-sdk-go/services/cr"
"github.com/goharbor/harbor/src/common/utils" "github.com/goharbor/harbor/src/common/utils"
"github.com/goharbor/harbor/src/common/utils/log" "github.com/goharbor/harbor/src/common/utils/log"
@ -147,6 +149,43 @@ func getAdapterInfo() *model.AdapterPattern {
return info return info
} }
func (a *adapter) listNamespaces(c *cr.Client) (namespaces []string, err error) {
// list namespaces
var nsReq = cr.CreateGetNamespaceListRequest()
var nsResp = cr.CreateGetNamespaceListResponse()
nsReq.SetDomain(a.domain)
nsResp, err = c.GetNamespaceList(nsReq)
if err != nil {
return
}
var resp = &aliACRNamespaceResp{}
err = json.Unmarshal(nsResp.GetHttpContentBytes(), resp)
if err != nil {
return
}
for _, ns := range resp.Data.Namespaces {
namespaces = append(namespaces, ns.Namespace)
}
log.Debugf("FetchImages.listNamespaces: %#v\n", namespaces)
return
}
func (a *adapter) listCandidateNamespaces(c *cr.Client, namespacePattern string) (namespaces []string, err error) {
if len(namespacePattern) > 0 {
if nms, ok := util.IsSpecificPathComponent(namespacePattern); ok {
namespaces = append(namespaces, nms...)
}
if len(namespaces) > 0 {
log.Debugf("parsed the namespaces %v from pattern %s", namespaces, namespacePattern)
return namespaces, nil
}
}
return a.listNamespaces(c)
}
// FetchImages AliACR not support /v2/_catalog of Registry, we'll list all resources via Aliyun's API // FetchImages AliACR not support /v2/_catalog of Registry, we'll list all resources via Aliyun's API
func (a *adapter) FetchImages(filters []*model.Filter) (resources []*model.Resource, err error) { func (a *adapter) FetchImages(filters []*model.Filter) (resources []*model.Resource, err error) {
log.Debugf("FetchImages.filters: %#v\n", filters) log.Debugf("FetchImages.filters: %#v\n", filters)
@ -168,20 +207,39 @@ func (a *adapter) FetchImages(filters []*model.Filter) (resources []*model.Resou
tagsPattern = filter.Value.(string) tagsPattern = filter.Value.(string)
} }
} }
var namespacePattern = strings.Split(repoPattern, "/")[0]
log.Debugf("\nrepoPattern=%s tagsPattern=%s\n\n", repoPattern, tagsPattern)
// get namespaces
var namespaces []string
namespaces, err = a.listCandidateNamespaces(client, namespacePattern)
if err != nil {
return
}
log.Debugf("got namespaces: %v \n", namespaces)
// list repos // list repos
var repositories []aliRepo var repositories []aliRepo
for { for _, namespace := range namespaces {
var repoListResp *aliRepoResp var repos []aliRepo
repoListResp, err = a.listRepo(a.region, client) repos, err = a.listReposByNamespace(a.region, namespace, client)
if err != nil { if err != nil {
return return
} }
if repoPattern != "" {
for _, repo := range repoListResp.Data.Repos { log.Debugf("\nnamespace: %s \t repositories: %#v\n\n", namespace, repos)
if _, ok := util.IsSpecificPathComponent(namespacePattern); ok {
log.Debugf("specific namespace: %s", repoPattern)
repositories = append(repositories, repos...)
} else {
for _, repo := range repos {
var ok bool var ok bool
ok, err = util.Match(repoPattern, filepath.Join(repo.RepoNamespace, repo.RepoName)) var repoName = filepath.Join(repo.RepoNamespace, repo.RepoName)
ok, err = util.Match(repoPattern, repoName)
log.Debugf("\n Repository: %s\t repoPattern: %s\t Match: %v\n", repoName, repoPattern, ok)
if err != nil { if err != nil {
return return
} }
@ -189,12 +247,6 @@ func (a *adapter) FetchImages(filters []*model.Filter) (resources []*model.Resou
repositories = append(repositories, repo) repositories = append(repositories, repo)
} }
} }
} else {
repositories = append(repositories, repoListResp.Data.Repos...)
}
if repoListResp.Data.Total-(repoListResp.Data.Page*repoListResp.Data.PageSize) <= 0 {
break
} }
} }
log.Debugf("FetchImages.repositories: %#v\n", repositories) log.Debugf("FetchImages.repositories: %#v\n", repositories)
@ -261,17 +313,30 @@ func (a *adapter) FetchImages(filters []*model.Filter) (resources []*model.Resou
return return
} }
func (a *adapter) listRepo(region string, c *cr.Client) (resp *aliRepoResp, err error) { func (a *adapter) listReposByNamespace(region string, namespace string, c *cr.Client) (repos []aliRepo, err error) {
var reposReq = cr.CreateGetRepoListRequest() var reposReq = cr.CreateGetRepoListByNamespaceRequest()
var reposResp = cr.CreateGetRepoListResponse() var reposResp = cr.CreateGetRepoListByNamespaceResponse()
reposReq.SetDomain(a.domain) reposReq.SetDomain(a.domain)
reposResp, err = c.GetRepoList(reposReq) reposReq.RepoNamespace = namespace
if err != nil { var page = 1
return for {
} reposReq.Page = requests.NewInteger(page)
resp = &aliRepoResp{} reposResp, err = c.GetRepoListByNamespace(reposReq)
json.Unmarshal(reposResp.GetHttpContentBytes(), resp) if err != nil {
return
}
var resp = &aliReposResp{}
err = json.Unmarshal(reposResp.GetHttpContentBytes(), resp)
if err != nil {
return
}
repos = append(repos, resp.Data.Repos...)
if resp.Data.Total-(resp.Data.Page*resp.Data.PageSize) <= 0 {
break
}
page++
}
return return
} }
@ -282,8 +347,9 @@ func (a *adapter) getTags(repo aliRepo, c *cr.Client) (tags []string, err error)
tagsReq.SetDomain(a.domain) tagsReq.SetDomain(a.domain)
tagsReq.RepoNamespace = repo.RepoNamespace tagsReq.RepoNamespace = repo.RepoNamespace
tagsReq.RepoName = repo.RepoName tagsReq.RepoName = repo.RepoName
var page = 1
for { for {
fmt.Printf("[GetRepoTags.req] %#v\n", tagsReq) tagsReq.Page = requests.NewInteger(page)
tagsResp, err = c.GetRepoTags(tagsReq) tagsResp, err = c.GetRepoTags(tagsReq)
if err != nil { if err != nil {
return return
@ -298,6 +364,7 @@ func (a *adapter) getTags(repo aliRepo, c *cr.Client) (tags []string, err error)
if resp.Data.Total-(resp.Data.Page*resp.Data.PageSize) <= 0 { if resp.Data.Total-(resp.Data.Page*resp.Data.PageSize) <= 0 {
break break
} }
page++
} }
return return

View File

@ -27,7 +27,20 @@ func (t timeUnix) String() string {
return t.ToTime().String() return t.ToTime().String()
} }
type aliRepoResp struct { type aliACRNamespaceResp struct {
Data struct {
Namespaces []aliACRNamespace `json:"namespaces"`
} `json:"data"`
RequestID string `json:"requestId"`
}
type aliACRNamespace struct {
Namespace string `json:"namespace"`
AuthorizeType string `json:"authorizeType"`
NamespaceStatus string `json:"namespaceStatus"`
}
type aliReposResp struct {
Data struct { Data struct {
Page int `json:"page"` Page int `json:"page"`
Total int `json:"total"` Total int `json:"total"`