diff --git a/src/replication/consts.go b/src/replication/consts.go index 76926f224..150937585 100644 --- a/src/replication/consts.go +++ b/src/replication/consts.go @@ -7,4 +7,7 @@ const ( FilterItemKindRepository = "repository" //FilterItemKindTag : Kind of filter item is 'tag' FilterItemKindTag = "tag" + + //AdaptorKindHarbor : Kind of adaptor of Harbor + AdaptorKindHarbor = "Harbor" ) diff --git a/src/replication/models/registry_models.go b/src/replication/models/registry_models.go new file mode 100644 index 000000000..69be2268c --- /dev/null +++ b/src/replication/models/registry_models.go @@ -0,0 +1,34 @@ +package models + +//Namespace is the resource group/scope like project in Harbor and organization in docker hub. +type Namespace struct { + //Name of the namespace + Name string + + //Extensions to provide flexibility + Metadata map[string]interface{} +} + +//Repository is to keep the info of image repository. +type Repository struct { + //Name of the repository + Name string + + //Project reference of this repository belongs to + Namespace Namespace + + //Extensions to provide flexibility + Metadata map[string]interface{} +} + +//Tag keeps the info of image with specified version +type Tag struct { + //Name of the tag + Name string + + //The repository reference of this tag belongs to + Repository Repository + + //Extensions to provide flexibility + Metadata map[string]interface{} +} diff --git a/src/replication/registry/adaptor.go b/src/replication/registry/adaptor.go new file mode 100644 index 000000000..29b3cf138 --- /dev/null +++ b/src/replication/registry/adaptor.go @@ -0,0 +1,34 @@ +package registry + +import ( + "github.com/vmware/harbor/src/replication/models" +) + +//Adaptor defines the unified operations for all the supported registries such as Harbor or DockerHub. +//It's used to adapt the different interfaces provied by the different registry providers. +//Use external registry with restful api providing as example, these intrefaces may depends on the +//related restful apis like: +// /api/vx/repositories/{namespace}/{repositoryName}/tags/{name} +// /api/v0/accounts/{namespace} +type Adaptor interface { + //Return the unique kind identifier of the adaptor + Kind() string + + //Get all the namespaces + GetNamespaces() []models.Namespace + + //Get the namespace with the specified name + GetNamespace(name string) models.Namespace + + //Get all the repositories under the specified namespace + GetRepositories(namespace string) []models.Repository + + //Get the repository with the specified name under the specified namespace + GetRepository(name string, namespace string) models.Repository + + //Get all the tags of the specified repository under the namespace + GetTags(repositoryName string, namespace string) []models.Tag + + //Get the tag with the specified name of the repository under the namespace + GetTag(name string, repositoryName string, namespace string) models.Tag +} diff --git a/src/replication/registry/harbor_adaptor.go b/src/replication/registry/harbor_adaptor.go new file mode 100644 index 000000000..6c7ffe09d --- /dev/null +++ b/src/replication/registry/harbor_adaptor.go @@ -0,0 +1,44 @@ +package registry + +import ( + "github.com/vmware/harbor/src/replication" + "github.com/vmware/harbor/src/replication/models" +) + +//HarborAdaptor is defined to adapt the Harbor registry +type HarborAdaptor struct{} + +//Kind returns the unique kind identifier of the adaptor +func (ha *HarborAdaptor) Kind() string { + return replication.AdaptorKindHarbor +} + +//GetNamespaces is ued to get all the namespaces +func (ha *HarborAdaptor) GetNamespaces() []models.Namespace { + return nil +} + +//GetNamespace is used to get the namespace with the specified name +func (ha *HarborAdaptor) GetNamespace(name string) models.Namespace { + return models.Namespace{} +} + +//GetRepositories is used to get all the repositories under the specified namespace +func (ha *HarborAdaptor) GetRepositories(namespace string) []models.Repository { + return nil +} + +//GetRepository is used to get the repository with the specified name under the specified namespace +func (ha *HarborAdaptor) GetRepository(name string, namespace string) models.Repository { + return models.Repository{} +} + +//GetTags is used to get all the tags of the specified repository under the namespace +func (ha *HarborAdaptor) GetTags(repositoryName string, namespace string) []models.Tag { + return nil +} + +//GetTag is used to get the tag with the specified name of the repository under the namespace +func (ha *HarborAdaptor) GetTag(name string, repositoryName string, namespace string) models.Tag { + return models.Tag{} +} diff --git a/src/replication/source/sourcer.go b/src/replication/source/sourcer.go new file mode 100644 index 000000000..4bbfc2c44 --- /dev/null +++ b/src/replication/source/sourcer.go @@ -0,0 +1,44 @@ +package source + +import ( + "github.com/vmware/harbor/src/replication" + "github.com/vmware/harbor/src/replication/registry" +) + +//Sourcer is used to manage and/or handle all the artifacts and information related with source registry. +//All the things with replication source should be covered in this object. +type Sourcer struct { + //Keep the adaptors we support now + adaptors map[string]registry.Adaptor +} + +//ReplicationSourcer is default sourcer for replication service. +var ReplicationSourcer = NewSourcer() + +//NewSourcer is the constructor of Sourcer +func NewSourcer() *Sourcer { + return &Sourcer{ + adaptors: make(map[string]registry.Adaptor), + } +} + +//Init will do some initialization work like registrying all the adaptors we support +func (sc *Sourcer) Init() { + //Register Harbor adaptor + sc.adaptors[replication.AdaptorKindHarbor] = ®istry.HarborAdaptor{} +} + +//GetAdaptor returns the required adaptor with the specified kind. +//If no adaptor with the specified kind existing, nil will be returned. +func (sc *Sourcer) GetAdaptor(kind string) registry.Adaptor { + if len(kind) == 0 { + return nil + } + + return sc.adaptors[kind] +} + +//Init the adaptors +func Init() { + ReplicationSourcer.Init() +} diff --git a/src/replication/source/sourcer_test.go b/src/replication/source/sourcer_test.go new file mode 100644 index 000000000..1cf9b0a90 --- /dev/null +++ b/src/replication/source/sourcer_test.go @@ -0,0 +1,24 @@ +package source + +import ( + "testing" + + "github.com/vmware/harbor/src/replication" +) + +func TestReplicationSourcer(t *testing.T) { + testingSourcer := NewSourcer() + if testingSourcer == nil { + t.Fatal("Failed to create sourcer") + } + + testingSourcer.Init() + + if testingSourcer.GetAdaptor("") != nil { + t.Fatal("Empty kind should not be supported") + } + + if testingSourcer.GetAdaptor(replication.AdaptorKindHarbor) == nil { + t.Fatalf("%s adaptor should be existing", replication.AdaptorKindHarbor) + } +}