mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-10 20:50:29 +01:00
1. Implement native docker registry adapter.
2. register the native adapter. Signed-off-by: 慕薇疯魔 <kfanjian@gmail.com>
This commit is contained in:
parent
f0f92791c7
commit
a555b09df0
@ -30,6 +30,8 @@ import (
|
||||
_ "github.com/goharbor/harbor/src/replication/ng/adapter/harbor"
|
||||
// register the DockerHub adapter
|
||||
_ "github.com/goharbor/harbor/src/replication/ng/adapter/dockerhub"
|
||||
// register the Native adapter
|
||||
_ "github.com/goharbor/harbor/src/replication/ng/adapter/native"
|
||||
)
|
||||
|
||||
// Replication implements the job interface
|
||||
|
@ -279,3 +279,23 @@ func (d *DefaultImageRegistry) PushBlob(repository, digest string, size int64, b
|
||||
func isDigest(str string) bool {
|
||||
return strings.Contains(str, ":")
|
||||
}
|
||||
|
||||
// ListTag ...
|
||||
func (d *DefaultImageRegistry) ListTag(repository string) ([]string, error) {
|
||||
client, err := d.getClient(repository)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
return client.ListTag()
|
||||
}
|
||||
|
||||
// Catalog ...
|
||||
func (d *DefaultImageRegistry) Catalog() ([]string, error) {
|
||||
client, err := registry_pkg.NewRegistry(d.registry.URL, d.client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client.Catalog()
|
||||
}
|
||||
|
89
src/replication/ng/adapter/native/adapter.go
Normal file
89
src/replication/ng/adapter/native/adapter.go
Normal file
@ -0,0 +1,89 @@
|
||||
package native
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/goharbor/harbor/src/common/utils/log"
|
||||
adp "github.com/goharbor/harbor/src/replication/ng/adapter"
|
||||
"github.com/goharbor/harbor/src/replication/ng/model"
|
||||
)
|
||||
|
||||
const registryTypeNative model.RegistryType = "native"
|
||||
|
||||
func init() {
|
||||
if err := adp.RegisterFactory(registryTypeNative, func(registry *model.Registry) (adp.Adapter, error) {
|
||||
return &native{
|
||||
registry: registry,
|
||||
DefaultImageRegistry: adp.NewDefaultImageRegistry(registry),
|
||||
}, nil
|
||||
}); err != nil {
|
||||
log.Errorf("failed to register factory for %s: %v", registryTypeNative, err)
|
||||
return
|
||||
}
|
||||
log.Infof("the factory for adapter %s registered", registryTypeNative)
|
||||
}
|
||||
|
||||
type native struct {
|
||||
*adp.DefaultImageRegistry
|
||||
registry *model.Registry
|
||||
}
|
||||
|
||||
var _ adp.Adapter = native{}
|
||||
|
||||
func (native) Info() (info *model.RegistryInfo, err error) {
|
||||
return &model.RegistryInfo{
|
||||
Type: registryTypeNative,
|
||||
SupportedResourceTypes: []model.ResourceType{
|
||||
model.ResourceTypeRepository,
|
||||
},
|
||||
SupportedResourceFilters: []*model.FilterStyle{
|
||||
{
|
||||
Type: model.FilterTypeName,
|
||||
Style: model.FilterStyleTypeText,
|
||||
},
|
||||
{
|
||||
Type: model.FilterTypeTag,
|
||||
Style: model.FilterStyleTypeText,
|
||||
},
|
||||
},
|
||||
SupportedTriggers: []model.TriggerType{
|
||||
model.TriggerTypeManual,
|
||||
model.TriggerTypeScheduled,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ConvertResourceMetadata convert src to dst resource
|
||||
func (native) ConvertResourceMetadata(metadata *model.ResourceMetadata, namespace *model.Namespace) (*model.ResourceMetadata, error) {
|
||||
if metadata == nil {
|
||||
return nil, errors.New("the metadata cannot be null")
|
||||
}
|
||||
|
||||
var result = &model.ResourceMetadata{
|
||||
Namespace: metadata.Namespace,
|
||||
Repository: metadata.Repository,
|
||||
Vtags: metadata.Vtags,
|
||||
}
|
||||
|
||||
// if dest namespace is set, rename metadata namespace
|
||||
if namespace != nil {
|
||||
result.Namespace = namespace
|
||||
}
|
||||
|
||||
result.Repository = &model.Repository{Name: result.GetResourceName()}
|
||||
result.Namespace = nil
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// PrepareForPush nothing need to do.
|
||||
func (native) PrepareForPush(*model.Resource) error { return nil }
|
||||
|
||||
// GetNamespace naitve registry no namespace.
|
||||
func (native) GetNamespace(name string) (*model.Namespace, error) {
|
||||
return &model.Namespace{Name: name}, nil
|
||||
}
|
||||
|
||||
// ListNamespaces native registry no namespaces, so list empty array.
|
||||
func (native) ListNamespaces(*model.NamespaceQuery) ([]*model.Namespace, error) {
|
||||
return []*model.Namespace{}, nil
|
||||
}
|
129
src/replication/ng/adapter/native/image_registry.go
Normal file
129
src/replication/ng/adapter/native/image_registry.go
Normal file
@ -0,0 +1,129 @@
|
||||
package native
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
adp "github.com/goharbor/harbor/src/replication/ng/adapter"
|
||||
"github.com/goharbor/harbor/src/replication/ng/model"
|
||||
"github.com/goharbor/harbor/src/replication/ng/util"
|
||||
)
|
||||
|
||||
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) {
|
||||
if len(namespaces) > 0 {
|
||||
return nil, errors.New("native registry adapter not support namespace")
|
||||
}
|
||||
|
||||
if len(filters) < 1 {
|
||||
return nil, errors.New("no any repository filter")
|
||||
}
|
||||
|
||||
var resources = []*model.Resource{}
|
||||
var nameFilter, tagFilter *model.Filter
|
||||
for i, filter := range filters {
|
||||
switch filter.Type {
|
||||
case model.FilterTypeName:
|
||||
nameFilter = filters[i]
|
||||
case model.FilterTypeTag:
|
||||
tagFilter = filters[i]
|
||||
}
|
||||
}
|
||||
|
||||
repositories, err := n.filterRepoistory(nameFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tagFilterTerm string
|
||||
var haveWildcardChars bool
|
||||
|
||||
if tagFilter != nil {
|
||||
tagFilterTerm = tagFilter.Value.(string)
|
||||
}
|
||||
|
||||
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 != "" {
|
||||
for _, repository := range repositories {
|
||||
resources = append(resources, &model.Resource{
|
||||
Type: model.ResourceTypeRepository,
|
||||
Registry: n.registry,
|
||||
Metadata: &model.ResourceMetadata{
|
||||
Repository: &model.Repository{
|
||||
Name: repository,
|
||||
},
|
||||
Vtags: []string{tagFilterTerm},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func (n native) filterRepoistory(nameFilter *model.Filter) (repositories []string, err error) {
|
||||
if nameFilter == nil {
|
||||
return nil, errors.New("native registry adapter must have repository filter")
|
||||
}
|
||||
var nameFilterTerm = nameFilter.Value.(string)
|
||||
|
||||
// search repoistories from catalog api
|
||||
if strings.ContainsAny(nameFilterTerm, "*?") {
|
||||
repos, err := n.DefaultImageRegistry.Catalog()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, repo := range repos {
|
||||
m, err := util.Match(nameFilterTerm, repo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if m {
|
||||
repositories = append(repositories, repo)
|
||||
}
|
||||
}
|
||||
} else if nameFilterTerm != "" {
|
||||
// only single repository
|
||||
repositories = []string{nameFilterTerm}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -33,6 +33,8 @@ import (
|
||||
_ "github.com/goharbor/harbor/src/replication/ng/adapter/dockerhub"
|
||||
// register the DockerHub adapter
|
||||
_ "github.com/goharbor/harbor/src/replication/ng/adapter/harbor"
|
||||
// register the Native adapter
|
||||
_ "github.com/goharbor/harbor/src/replication/ng/adapter/native"
|
||||
)
|
||||
|
||||
var (
|
||||
|
Loading…
Reference in New Issue
Block a user