Merge pull request #7379 from ywk253100/190414_label_filter

Fix buf in native docker registry adapter
This commit is contained in:
Wenkai Yin 2019-04-14 15:46:17 +08:00 committed by GitHub
commit f0fa90d10f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 104 additions and 90 deletions

View File

@ -105,8 +105,6 @@ func NewDefaultImageRegistry(registry *model.Registry) (*DefaultImageRegistry, e
} }
func (d *DefaultImageRegistry) getClient(repository string) (*registry_pkg.Repository, error) { func (d *DefaultImageRegistry) getClient(repository string) (*registry_pkg.Repository, error) {
d.RLock()
defer d.RUnlock()
client, exist := d.clients[repository] client, exist := d.clients[repository]
if exist { if exist {
return client, nil return client, nil
@ -250,6 +248,5 @@ func (d *DefaultImageRegistry) ListTag(repository string) ([]string, error) {
if err != nil { if err != nil {
return []string{}, err return []string{}, err
} }
return client.ListTag() return client.ListTag()
} }

View File

@ -1,3 +1,17 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package native package native
import ( import (

View File

@ -1,9 +1,25 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package native package native
import ( import (
"errors" "errors"
"net/http"
"strings" "strings"
common_http "github.com/goharbor/harbor/src/common/http"
adp "github.com/goharbor/harbor/src/replication/adapter" adp "github.com/goharbor/harbor/src/replication/adapter"
"github.com/goharbor/harbor/src/replication/model" "github.com/goharbor/harbor/src/replication/model"
"github.com/goharbor/harbor/src/replication/util" "github.com/goharbor/harbor/src/replication/util"
@ -11,119 +27,106 @@ import (
var _ adp.ImageRegistry = native{} var _ adp.ImageRegistry = native{}
// TODO: support other filters
// MUST have filters and name filter
// NOT support namespaces
func (n native) FetchImages(namespaces []string, filters []*model.Filter) ([]*model.Resource, error) { func (n native) FetchImages(namespaces []string, filters []*model.Filter) ([]*model.Resource, error) {
if len(namespaces) > 0 { if len(namespaces) > 0 {
return nil, errors.New("native registry adapter not support namespace") return nil, errors.New("native registry adapter not support namespace")
} }
if len(filters) < 1 { nameFilterPattern := ""
return nil, errors.New("no any repository filter") tagFilterPattern := ""
} for _, filter := range filters {
var resources = []*model.Resource{}
var nameFilter, tagFilter *model.Filter
for i, filter := range filters {
switch filter.Type { switch filter.Type {
case model.FilterTypeName: case model.FilterTypeName:
nameFilter = filters[i] nameFilterPattern = filter.Value.(string)
case model.FilterTypeTag: case model.FilterTypeTag:
tagFilter = filters[i] tagFilterPattern = filter.Value.(string)
} }
} }
repositories, err := n.filterRepositories(nameFilterPattern)
repositories, err := n.filterRepoistory(nameFilter)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var tagFilterTerm string resources := []*model.Resource{}
var haveWildcardChars bool for _, repository := range repositories {
tags, err := n.filterTags(repository, tagFilterPattern)
if tagFilter != nil { if err != nil {
tagFilterTerm = tagFilter.Value.(string) return nil, err
}
if strings.ContainsAny(tagFilterTerm, "?*") {
haveWildcardChars = true
}
if haveWildcardChars || tagFilterTerm == "" {
// need call list tag api
for _, repository := range repositories {
var tags []string
resp, err := n.DefaultImageRegistry.ListTag(repository)
if err != nil {
return nil, err
}
if haveWildcardChars {
for _, tag := range resp {
if m, _ := util.Match(tagFilterTerm, tag); m {
tags = append(tags, tag)
}
}
} else {
tags = resp
}
resources = append(resources, &model.Resource{
Type: model.ResourceTypeRepository,
Registry: n.registry,
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{
Name: repository,
},
Vtags: tags,
},
})
} }
} else if tagFilterTerm != "" { if len(tags) == 0 {
for _, repository := range repositories { continue
resources = append(resources, &model.Resource{
Type: model.ResourceTypeRepository,
Registry: n.registry,
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{
Name: repository,
},
Vtags: []string{tagFilterTerm},
},
})
} }
resources = append(resources, &model.Resource{
Type: model.ResourceTypeRepository,
Registry: n.registry,
Metadata: &model.ResourceMetadata{
Repository: &model.Repository{
Name: repository,
},
Vtags: tags,
},
})
} }
return resources, nil return resources, nil
} }
func (n native) filterRepoistory(nameFilter *model.Filter) (repositories []string, err error) { func (n native) filterRepositories(pattern string) ([]string, error) {
if nameFilter == nil { // if the pattern contains no "*" and "?", it is a specific repository name
return nil, errors.New("native registry adapter must have repository filter") // just to make sure the repository exists
if len(pattern) > 0 && !strings.ContainsAny(pattern, "*?") {
_, err := n.ListTag(pattern)
// the repository exists
if err == nil {
return []string{pattern}, nil
}
// the repository doesn't exist
if e, ok := err.(*common_http.Error); ok && e.Code == http.StatusNotFound {
return nil, nil
}
// other error
return nil, err
} }
var nameFilterTerm = nameFilter.Value.(string) // search repositories from catalog api
repositories, err := n.Catalog()
// search repoistories from catalog api if err != nil {
if strings.ContainsAny(nameFilterTerm, "*?") { return nil, err
repos, err := n.DefaultImageRegistry.Catalog() }
// if the pattern is null, just return the result of catalog API
if len(pattern) == 0 {
return repositories, nil
}
result := []string{}
for _, repository := range repositories {
match, err := util.Match(pattern, repository)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if match {
for _, repo := range repos { result = append(result, repository)
m, err := util.Match(nameFilterTerm, repo)
if err != nil {
return nil, err
}
if m {
repositories = append(repositories, repo)
}
} }
} else if nameFilterTerm != "" { }
// only single repository return result, nil
repositories = []string{nameFilterTerm} }
func (n native) filterTags(repository, pattern string) ([]string, error) {
tags, err := n.ListTag(repository)
if err != nil {
return nil, err
}
if len(pattern) == 0 {
return tags, nil
} }
return result := []string{}
for _, tag := range tags {
match, err := util.Match(pattern, tag)
if err != nil {
return nil, err
}
if match {
result = append(result, tag)
}
}
return result, nil
} }