diff --git a/src/core/api/registry.go b/src/core/api/registry.go index 3885e11a0..8973eb3bd 100644 --- a/src/core/api/registry.go +++ b/src/core/api/registry.go @@ -407,7 +407,7 @@ func (t *RegistryAPI) GetInfo() { t.SendInternalServerError(fmt.Errorf("failed to get the adapter factory for registry type %s: %v", registry.Type, err)) return } - adp, err := factory(registry) + adp, err := factory.Create(registry) if err != nil { t.SendInternalServerError(fmt.Errorf("failed to create the adapter for registry %d: %v", registry.ID, err)) return diff --git a/src/core/api/replication_adapter.go b/src/core/api/replication_adapter.go index bf5df68d2..14fe96201 100644 --- a/src/core/api/replication_adapter.go +++ b/src/core/api/replication_adapter.go @@ -44,3 +44,8 @@ func (r *ReplicationAdapterAPI) List() { types = append(types, adapter.ListRegisteredAdapterTypes()...) r.WriteJSONData(types) } + +// ListAdapterInfos the replication adapter infos +func (r *ReplicationAdapterAPI) ListAdapterInfos() { + r.WriteJSONData(adapter.ListAdapterInfos()) +} diff --git a/src/core/api/replication_adapter_test.go b/src/core/api/replication_adapter_test.go index 2719ece74..786bcd19f 100644 --- a/src/core/api/replication_adapter_test.go +++ b/src/core/api/replication_adapter_test.go @@ -23,12 +23,19 @@ import ( "github.com/stretchr/testify/require" ) -func fakedFactory(*model.Registry) (adapter.Adapter, error) { +type fakedFactory struct { +} + +func (fakedFactory) Create(*model.Registry) (adapter.Adapter, error) { return nil, nil } +func (fakedFactory) AdapterPattern() *model.AdapterPattern { + return nil +} + func TestReplicationAdapterAPIList(t *testing.T) { - err := adapter.RegisterFactory("test", fakedFactory) + err := adapter.RegisterFactory("test", new(fakedFactory)) require.Nil(t, err) cases := []*codeCheckingCase{ // 401 diff --git a/src/core/router.go b/src/core/router.go index 6f38680b9..2d2645189 100755 --- a/src/core/router.go +++ b/src/core/router.go @@ -102,6 +102,7 @@ func initRouters() { beego.Router("/api/logs", &api.LogAPI{}) beego.Router("/api/replication/adapters", &api.ReplicationAdapterAPI{}, "get:List") + beego.Router("/api/replication/adapterinfos", &api.ReplicationAdapterAPI{}, "get:ListAdapterInfos") beego.Router("/api/replication/executions", &api.ReplicationOperationAPI{}, "get:ListExecutions;post:CreateExecution") beego.Router("/api/replication/executions/:id([0-9]+)", &api.ReplicationOperationAPI{}, "get:GetExecution;put:StopExecution") beego.Router("/api/replication/executions/:id([0-9]+)/tasks", &api.ReplicationOperationAPI{}, "get:ListTasks") diff --git a/src/replication/adapter/adapter.go b/src/replication/adapter/adapter.go index 81c49f0a9..1e7f7865c 100644 --- a/src/replication/adapter/adapter.go +++ b/src/replication/adapter/adapter.go @@ -31,9 +31,13 @@ const ( ) var registry = map[model.RegistryType]Factory{} +var adapterInfoMap = map[model.RegistryType]*model.AdapterPattern{} // Factory creates a specific Adapter according to the params -type Factory func(*model.Registry) (Adapter, error) +type Factory interface { + Create(*model.Registry) (Adapter, error) + AdapterPattern() *model.AdapterPattern +} // Adapter interface defines the capabilities of registry type Adapter interface { @@ -134,6 +138,10 @@ func RegisterFactory(t model.RegistryType, factory Factory) error { return fmt.Errorf("adapter factory for %s already exists", t) } registry[t] = factory + adapterInfo := factory.AdapterPattern() + if adapterInfo != nil { + adapterInfoMap[t] = adapterInfo + } return nil } @@ -160,3 +168,8 @@ func ListRegisteredAdapterTypes() []model.RegistryType { } return types } + +// ListAdapterInfos list the adapter infos +func ListAdapterInfos() map[model.RegistryType]*model.AdapterPattern { + return adapterInfoMap +} diff --git a/src/replication/adapter/adapter_test.go b/src/replication/adapter/adapter_test.go index 51295ebc5..cfb999b61 100644 --- a/src/replication/adapter/adapter_test.go +++ b/src/replication/adapter/adapter_test.go @@ -22,24 +22,31 @@ import ( "github.com/stretchr/testify/require" ) -func fakedFactory(*model.Registry) (Adapter, error) { +type fakedFactory struct { +} + +func (fakedFactory) Create(*model.Registry) (Adapter, error) { return nil, nil } +func (fakedFactory) AdapterPattern() *model.AdapterPattern { + return nil +} + func TestRegisterFactory(t *testing.T) { // empty type assert.NotNil(t, RegisterFactory("", nil)) // empty factory assert.NotNil(t, RegisterFactory("harbor", nil)) // pass - assert.Nil(t, RegisterFactory("harbor", fakedFactory)) + assert.Nil(t, RegisterFactory("harbor", new(fakedFactory))) // already exists - assert.NotNil(t, RegisterFactory("harbor", fakedFactory)) + assert.NotNil(t, RegisterFactory("harbor", new(fakedFactory))) } func TestGetFactory(t *testing.T) { registry = map[model.RegistryType]Factory{} - require.Nil(t, RegisterFactory("harbor", fakedFactory)) + require.Nil(t, RegisterFactory("harbor", new(fakedFactory))) // doesn't exist _, err := GetFactory("gcr") assert.NotNil(t, err) @@ -55,7 +62,7 @@ func TestListRegisteredAdapterTypes(t *testing.T) { assert.Equal(t, 0, len(types)) // register one factory - require.Nil(t, RegisterFactory("harbor", fakedFactory)) + require.Nil(t, RegisterFactory("harbor", new(fakedFactory))) types = ListRegisteredAdapterTypes() require.Equal(t, 1, len(types)) diff --git a/src/replication/adapter/aliacr/adapter.go b/src/replication/adapter/aliacr/adapter.go index 386f2b3c1..e50750b6f 100644 --- a/src/replication/adapter/aliacr/adapter.go +++ b/src/replication/adapter/aliacr/adapter.go @@ -19,9 +19,7 @@ import ( ) func init() { - if err := adp.RegisterFactory(model.RegistryTypeAliAcr, func(registry *model.Registry) (adp.Adapter, error) { - return newAdapter(registry) - }); err != nil { + if err := adp.RegisterFactory(model.RegistryTypeAliAcr, new(factory)); err != nil { log.Errorf("failed to register factory for %s: %v", model.RegistryTypeAliAcr, err) return } @@ -70,6 +68,19 @@ func newAdapter(registry *model.Registry) (*adapter, error) { }, nil } +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return newAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return getAdapterInfo() +} + // adapter for to aliyun docker registry type adapter struct { *native.Adapter @@ -105,6 +116,37 @@ func (a *adapter) Info() (info *model.RegistryInfo, err error) { return } +func getAdapterInfo() *model.AdapterPattern { + info := &model.AdapterPattern{ + EndpointPattern: &model.EndpointPattern{ + EndpointType: model.EndpointPatternTypeList, + Endpoints: []*model.Endpoint{ + {Key: "cn-hangzhou", Value: "https://registry.cn-hangzhou.aliyuncs.com"}, + {Key: "cn-shanghai", Value: "https://registry.cn-shanghai.aliyuncs.com"}, + {Key: "cn-qingdao", Value: "https://registry.cn-qingdao.aliyuncs.com"}, + {Key: "cn-beijing", Value: "https://registry.cn-beijing.aliyuncs.com"}, + {Key: "cn-zhangjiakou", Value: "https://registry.cn-zhangjiakou.aliyuncs.com"}, + {Key: "cn-huhehaote", Value: "https://registry.cn-huhehaote.aliyuncs.com"}, + {Key: "cn-shenzhen", Value: "https://registry.cn-shenzhen.aliyuncs.com"}, + {Key: "cn-chengdu", Value: "https://registry.cn-chengdu.aliyuncs.com"}, + {Key: "cn-hongkong", Value: "https://registry.cn-hongkong.aliyuncs.com"}, + {Key: "ap-southeast-1", Value: "https://registry.ap-southeast-1.aliyuncs.com"}, + {Key: "ap-southeast-2", Value: "https://registry.ap-southeast-2.aliyuncs.com"}, + {Key: "ap-southeast-3", Value: "https://registry.ap-southeast-3.aliyuncs.com"}, + {Key: "ap-southeast-5", Value: "https://registry.ap-southeast-5.aliyuncs.com"}, + {Key: "ap-northeast-1", Value: "https://registry.ap-northeast-1.aliyuncs.com"}, + {Key: "ap-south-1", Value: "https://registry.ap-south-1.aliyuncs.com"}, + {Key: "eu-central-1", Value: "https://registry.eu-central-1.aliyuncs.com"}, + {Key: "eu-west-1", Value: "https://registry.eu-west-1.aliyuncs.com"}, + {Key: "us-west-1", Value: "https://registry.us-west-1.aliyuncs.com"}, + {Key: "us-east-1", Value: "https://registry.us-east-1.aliyuncs.com"}, + {Key: "me-east-1", Value: "https://registry.me-east-1.aliyuncs.com"}, + }, + }, + } + return info +} + // 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) { log.Debugf("FetchImages.filters: %#v\n", filters) diff --git a/src/replication/adapter/aliacr/adapter_test.go b/src/replication/adapter/aliacr/adapter_test.go index 94fd41eb3..9f8212ead 100644 --- a/src/replication/adapter/aliacr/adapter_test.go +++ b/src/replication/adapter/aliacr/adapter_test.go @@ -26,7 +26,7 @@ func TestAdapter_NewAdapter(t *testing.T) { assert.NotNil(t, factory) // test case for URL is registry. - adapter, err := factory(&model.Registry{ + adapter, err := newAdapter(&model.Registry{ Type: model.RegistryTypeAliAcr, Credential: &model.Credential{ AccessKey: "MockAccessKey", @@ -38,7 +38,7 @@ func TestAdapter_NewAdapter(t *testing.T) { assert.NotNil(t, adapter) // test case for URL is cr service. - adapter, err = factory(&model.Registry{ + adapter, err = newAdapter(&model.Registry{ Type: model.RegistryTypeAliAcr, Credential: &model.Credential{ AccessKey: "MockAccessKey", diff --git a/src/replication/adapter/awsecr/adapter.go b/src/replication/adapter/awsecr/adapter.go index 69ee60b49..e2ed93d02 100644 --- a/src/replication/adapter/awsecr/adapter.go +++ b/src/replication/adapter/awsecr/adapter.go @@ -40,9 +40,7 @@ var ( ) func init() { - if err := adp.RegisterFactory(model.RegistryTypeAwsEcr, func(registry *model.Registry) (adp.Adapter, error) { - return newAdapter(registry) - }); err != nil { + if err := adp.RegisterFactory(model.RegistryTypeAwsEcr, new(factory)); err != nil { log.Errorf("failed to register factory for %s: %v", model.RegistryTypeAwsEcr, err) return } @@ -74,6 +72,19 @@ func parseRegion(url string) (string, error) { return rs[1], nil } +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return newAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return getAdapterInfo() +} + type adapter struct { *native.Adapter registry *model.Registry @@ -104,6 +115,85 @@ func (*adapter) Info() (info *model.RegistryInfo, err error) { }, nil } +func getAdapterInfo() *model.AdapterPattern { + info := &model.AdapterPattern{ + EndpointPattern: &model.EndpointPattern{ + EndpointType: model.EndpointPatternTypeList, + Endpoints: []*model.Endpoint{ + { + Key: "ap-northeast-1", + Value: "https://api.ecr.ap-northeast-1.amazonaws.com", + }, + { + Key: "us-east-1", + Value: "https://api.ecr.us-east-1.amazonaws.com", + }, + { + Key: "us-east-2", + Value: "https://api.ecr.us-east-2.amazonaws.com", + }, + { + Key: "us-west-1", + Value: "https://api.ecr.us-west-1.amazonaws.com", + }, + { + Key: "us-west-2", + Value: "https://api.ecr.us-west-2.amazonaws.com", + }, + { + Key: "ap-east-1", + Value: "https://api.ecr.ap-east-1.amazonaws.com", + }, + { + Key: "ap-south-1", + Value: "https://api.ecr.ap-south-1.amazonaws.com", + }, + { + Key: "ap-northeast-2", + Value: "https://api.ecr.ap-northeast-2.amazonaws.com", + }, + { + Key: "ap-southeast-1", + Value: "https://api.ecr.ap-southeast-1.amazonaws.com", + }, + { + Key: "ap-southeast-2", + Value: "https://api.ecr.ap-southeast-2.amazonaws.com", + }, + { + Key: "ca-central-1", + Value: "https://api.ecr.ca-central-1.amazonaws.com", + }, + { + Key: "eu-central-1", + Value: "https://api.ecr.eu-central-1.amazonaws.com", + }, + { + Key: "eu-west-1", + Value: "https://api.ecr.eu-west-1.amazonaws.com", + }, + { + Key: "eu-west-2", + Value: "https://api.ecr.eu-west-2.amazonaws.com", + }, + { + Key: "eu-west-3", + Value: "https://api.ecr.eu-west-3.amazonaws.com", + }, + { + Key: "eu-north-1", + Value: "https://api.ecr.eu-north-1.amazonaws.com", + }, + { + Key: "sa-east-1", + Value: "https://api.ecr.sa-east-1.amazonaws.com", + }, + }, + }, + } + return info +} + // HealthCheck checks health status of a registry func (a *adapter) HealthCheck() (model.HealthStatus, error) { if a.registry.Credential == nil || diff --git a/src/replication/adapter/awsecr/adapter_test.go b/src/replication/adapter/awsecr/adapter_test.go index 206e35673..0f186b5f5 100644 --- a/src/replication/adapter/awsecr/adapter_test.go +++ b/src/replication/adapter/awsecr/adapter_test.go @@ -27,7 +27,7 @@ func TestAdapter_NewAdapter(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, factory) - adapter, err := factory(&model.Registry{ + adapter, err := newAdapter(&model.Registry{ Type: model.RegistryTypeAwsEcr, Credential: &model.Credential{ AccessKey: "xxx", @@ -38,7 +38,7 @@ func TestAdapter_NewAdapter(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, adapter) - adapter, err = factory(&model.Registry{ + adapter, err = newAdapter(&model.Registry{ Type: model.RegistryTypeAwsEcr, Credential: &model.Credential{ AccessKey: "xxx", @@ -49,7 +49,7 @@ func TestAdapter_NewAdapter(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, adapter) - adapter, err = factory(&model.Registry{ + adapter, err = newAdapter(&model.Registry{ Type: model.RegistryTypeAwsEcr, Credential: &model.Credential{ AccessKey: "xxx", diff --git a/src/replication/adapter/azurecr/adapter.go b/src/replication/adapter/azurecr/adapter.go index 5dc89d56b..b11d71708 100644 --- a/src/replication/adapter/azurecr/adapter.go +++ b/src/replication/adapter/azurecr/adapter.go @@ -8,14 +8,14 @@ import ( ) func init() { - if err := adp.RegisterFactory(model.RegistryTypeAzureAcr, factory); err != nil { + if err := adp.RegisterFactory(model.RegistryTypeAzureAcr, new(factory)); err != nil { log.Errorf("Register adapter factory for %s error: %v", model.RegistryTypeAzureAcr, err) return } log.Infof("Factory for adapter %s registered", model.RegistryTypeAzureAcr) } -func factory(registry *model.Registry) (adp.Adapter, error) { +func newAdapter(registry *model.Registry) (adp.Adapter, error) { dockerRegistryAdapter, err := native.NewAdapter(registry) if err != nil { return nil, err @@ -25,6 +25,19 @@ func factory(registry *model.Registry) (adp.Adapter, error) { }, nil } +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return newAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return nil +} + type adapter struct { *native.Adapter } diff --git a/src/replication/adapter/dockerhub/adapter.go b/src/replication/adapter/dockerhub/adapter.go index 3cfb692eb..490d42c5a 100644 --- a/src/replication/adapter/dockerhub/adapter.go +++ b/src/replication/adapter/dockerhub/adapter.go @@ -18,14 +18,14 @@ import ( ) func init() { - if err := adp.RegisterFactory(model.RegistryTypeDockerHub, factory); err != nil { + if err := adp.RegisterFactory(model.RegistryTypeDockerHub, new(factory)); err != nil { log.Errorf("Register adapter factory for %s error: %v", model.RegistryTypeDockerHub, err) return } log.Infof("Factory for adapter %s registered", model.RegistryTypeDockerHub) } -func factory(registry *model.Registry) (adp.Adapter, error) { +func newAdapter(registry *model.Registry) (adp.Adapter, error) { client, err := NewClient(registry) if err != nil { return nil, err @@ -47,6 +47,19 @@ func factory(registry *model.Registry) (adp.Adapter, error) { }, nil } +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return newAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return getAdapterInfo() +} + type adapter struct { *native.Adapter registry *model.Registry @@ -80,6 +93,21 @@ func (a *adapter) Info() (*model.RegistryInfo, error) { }, nil } +func getAdapterInfo() *model.AdapterPattern { + info := &model.AdapterPattern{ + EndpointPattern: &model.EndpointPattern{ + EndpointType: model.EndpointPatternTypeFix, + Endpoints: []*model.Endpoint{ + { + Key: "hub.docker.com", + Value: "https://hub.docker.com", + }, + }, + }, + } + return info +} + // PrepareForPush does the prepare work that needed for pushing/uploading the resource // eg: create the namespace or repository func (a *adapter) PrepareForPush(resources []*model.Resource) error { diff --git a/src/replication/adapter/dockerhub/adapter_test.go b/src/replication/adapter/dockerhub/adapter_test.go index 9cf9ed650..dda533d54 100644 --- a/src/replication/adapter/dockerhub/adapter_test.go +++ b/src/replication/adapter/dockerhub/adapter_test.go @@ -21,7 +21,7 @@ func getAdapter(t *testing.T) adp.Adapter { assert.Nil(err) assert.NotNil(factory) - adapter, err := factory(&model.Registry{ + adapter, err := newAdapter(&model.Registry{ Type: model.RegistryTypeDockerHub, URL: baseURL, Credential: &model.Credential{ diff --git a/src/replication/adapter/gitlab/adapter.go b/src/replication/adapter/gitlab/adapter.go index b63a7080d..50c674ade 100644 --- a/src/replication/adapter/gitlab/adapter.go +++ b/src/replication/adapter/gitlab/adapter.go @@ -12,15 +12,26 @@ import ( ) func init() { - if err := adp.RegisterFactory(model.RegistryTypeGitLab, func(registry *model.Registry) (adp.Adapter, error) { - return newAdapter(registry) - }); err != nil { + if err := adp.RegisterFactory(model.RegistryTypeGitLab, new(factory)); err != nil { log.Errorf("failed to register factory for %s: %v", model.RegistryTypeGitLab, err) return } log.Infof("the factory for adapter %s registered", model.RegistryTypeGitLab) } +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return newAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return nil +} + type adapter struct { *native.Adapter registry *model.Registry @@ -31,7 +42,6 @@ type adapter struct { } func newAdapter(registry *model.Registry) (*adapter, error) { - var credential auth.Credential if registry.Credential != nil && len(registry.Credential.AccessSecret) != 0 { credential = auth.NewBasicAuthCredential( diff --git a/src/replication/adapter/googlegcr/adapter.go b/src/replication/adapter/googlegcr/adapter.go index 4dd47d834..a5174962d 100644 --- a/src/replication/adapter/googlegcr/adapter.go +++ b/src/replication/adapter/googlegcr/adapter.go @@ -22,9 +22,7 @@ import ( ) func init() { - if err := adp.RegisterFactory(model.RegistryTypeGoogleGcr, func(registry *model.Registry) (adp.Adapter, error) { - return newAdapter(registry) - }); err != nil { + if err := adp.RegisterFactory(model.RegistryTypeGoogleGcr, new(factory)); err != nil { log.Errorf("failed to register factory for %s: %v", model.RegistryTypeGoogleGcr, err) return } @@ -43,6 +41,19 @@ func newAdapter(registry *model.Registry) (*adapter, error) { }, nil } +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return newAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return getAdapterInfo() +} + type adapter struct { *native.Adapter registry *model.Registry @@ -73,6 +84,39 @@ func (adapter) Info() (info *model.RegistryInfo, err error) { }, nil } +func getAdapterInfo() *model.AdapterPattern { + info := &model.AdapterPattern{ + EndpointPattern: &model.EndpointPattern{ + EndpointType: model.EndpointPatternTypeList, + Endpoints: []*model.Endpoint{ + { + Key: "gcr.io", + Value: "https://gcr.io", + }, + { + Key: "us.gcr.io", + Value: "https://us.gcr.io", + }, + { + Key: "eu.gcr.io", + Value: "https://eu.gcr.io", + }, + { + Key: "asia.gcr.io", + Value: "https://asia.gcr.io", + }, + }, + }, + CredentialPattern: &model.CredentialPattern{ + AccessKeyType: model.AccessKeyTypeFix, + AccessKeyData: "_json_key", + AccessSecretType: model.AccessSecretTypeFile, + AccessSecretData: "No Change", + }, + } + return info +} + // HealthCheck checks health status of a registry func (a adapter) HealthCheck() (model.HealthStatus, error) { var err error diff --git a/src/replication/adapter/googlegcr/adapter_test.go b/src/replication/adapter/googlegcr/adapter_test.go index a2acefabd..08e0ef2c8 100644 --- a/src/replication/adapter/googlegcr/adapter_test.go +++ b/src/replication/adapter/googlegcr/adapter_test.go @@ -88,10 +88,10 @@ func getMockAdapter(t *testing.T, hasCred, health bool) (*adapter, *httptest.Ser factory, err := adp.GetFactory(model.RegistryTypeGoogleGcr) assert.Nil(t, err) assert.NotNil(t, factory) - a, err := factory(registry) + a, err := newAdapter(registry) assert.Nil(t, err) - return a.(*adapter), server + return a, server } func TestAdapter_Info(t *testing.T) { diff --git a/src/replication/adapter/harbor/adapter.go b/src/replication/adapter/harbor/adapter.go index 4c8a26597..41c823c5c 100644 --- a/src/replication/adapter/harbor/adapter.go +++ b/src/replication/adapter/harbor/adapter.go @@ -33,15 +33,26 @@ import ( ) func init() { - if err := adp.RegisterFactory(model.RegistryTypeHarbor, func(registry *model.Registry) (adp.Adapter, error) { - return newAdapter(registry) - }); err != nil { + if err := adp.RegisterFactory(model.RegistryTypeHarbor, new(factory)); err != nil { log.Errorf("failed to register factory for %s: %v", model.RegistryTypeHarbor, err) return } log.Infof("the factory for adapter %s registered", model.RegistryTypeHarbor) } +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return newAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return nil +} + type adapter struct { *native.Adapter registry *model.Registry diff --git a/src/replication/adapter/helmhub/adapter.go b/src/replication/adapter/helmhub/adapter.go index 45fb7a0a3..e0d027d81 100644 --- a/src/replication/adapter/helmhub/adapter.go +++ b/src/replication/adapter/helmhub/adapter.go @@ -22,15 +22,26 @@ import ( ) func init() { - if err := adp.RegisterFactory(model.RegistryTypeHelmHub, func(registry *model.Registry) (adp.Adapter, error) { - return newAdapter(registry) - }); err != nil { + if err := adp.RegisterFactory(model.RegistryTypeHelmHub, new(factory)); err != nil { log.Errorf("failed to register factory for %s: %v", model.RegistryTypeHelmHub, err) return } log.Infof("the factory for adapter %s registered", model.RegistryTypeHelmHub) } +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return newAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return nil +} + type adapter struct { registry *model.Registry client *Client diff --git a/src/replication/adapter/huawei/huawei_adapter.go b/src/replication/adapter/huawei/huawei_adapter.go index fc655e6ea..7d647176b 100644 --- a/src/replication/adapter/huawei/huawei_adapter.go +++ b/src/replication/adapter/huawei/huawei_adapter.go @@ -19,7 +19,7 @@ import ( ) func init() { - err := adp.RegisterFactory(model.RegistryTypeHuawei, AdapterFactory) + err := adp.RegisterFactory(model.RegistryTypeHuawei, new(factory)) if err != nil { log.Errorf("failed to register factory for Huawei: %v", err) return @@ -27,6 +27,19 @@ func init() { log.Infof("the factory of Huawei adapter was registered") } +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return newAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return nil +} + // Adapter is for images replications between harbor and Huawei image repository(SWR) type adapter struct { *native.Adapter @@ -210,8 +223,7 @@ func (a *adapter) HealthCheck() (model.HealthStatus, error) { return model.Healthy, nil } -// AdapterFactory is the factory for huawei adapter -func AdapterFactory(registry *model.Registry) (adp.Adapter, error) { +func newAdapter(registry *model.Registry) (adp.Adapter, error) { dockerRegistryAdapter, err := native.NewAdapter(registry) if err != nil { return nil, err diff --git a/src/replication/adapter/huawei/huawei_adapter_test.go b/src/replication/adapter/huawei/huawei_adapter_test.go index 9c25c8a30..7cfd835b2 100644 --- a/src/replication/adapter/huawei/huawei_adapter_test.go +++ b/src/replication/adapter/huawei/huawei_adapter_test.go @@ -24,7 +24,7 @@ func init() { Status: "", } - hwAdapter, err = AdapterFactory(hwRegistry) + hwAdapter, err = newAdapter(hwRegistry) if err != nil { os.Exit(1) } diff --git a/src/replication/adapter/huawei/image_registry_test.go b/src/replication/adapter/huawei/image_registry_test.go index 94e38908a..b61a50722 100644 --- a/src/replication/adapter/huawei/image_registry_test.go +++ b/src/replication/adapter/huawei/image_registry_test.go @@ -21,7 +21,7 @@ func init() { Insecure: false, Status: "", } - adp, err := AdapterFactory(hwRegistry) + adp, err := newAdapter(hwRegistry) if err != nil { os.Exit(1) } diff --git a/src/replication/adapter/jfrog/adapter.go b/src/replication/adapter/jfrog/adapter.go index f77d81360..ab17712f0 100644 --- a/src/replication/adapter/jfrog/adapter.go +++ b/src/replication/adapter/jfrog/adapter.go @@ -22,7 +22,7 @@ import ( ) func init() { - err := adp.RegisterFactory(model.RegistryTypeJfrogArtifactory, AdapterFactory) + err := adp.RegisterFactory(model.RegistryTypeJfrogArtifactory, new(factory)) if err != nil { log.Errorf("failed to register factory for jfrog artifactory: %v", err) return @@ -30,6 +30,19 @@ func init() { log.Infof("the factory of jfrog artifactory adapter was registered") } +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return newAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return nil +} + // Adapter is for images replications between harbor and jfrog artifactory image repository type adapter struct { *native.Adapter @@ -64,8 +77,7 @@ func (a *adapter) Info() (info *model.RegistryInfo, err error) { return } -// AdapterFactory is the factory for jfrog artifactory adapter -func AdapterFactory(registry *model.Registry) (adp.Adapter, error) { +func newAdapter(registry *model.Registry) (adp.Adapter, error) { dockerRegistryAdapter, err := native.NewAdapter(registry) if err != nil { return nil, err diff --git a/src/replication/adapter/jfrog/adapter_test.go b/src/replication/adapter/jfrog/adapter_test.go index 1f62a62f4..8d49a9317 100644 --- a/src/replication/adapter/jfrog/adapter_test.go +++ b/src/replication/adapter/jfrog/adapter_test.go @@ -91,7 +91,7 @@ func getMockAdapter(t *testing.T, hasCred, health bool) (*adapter, *httptest.Ser factory, err := adp.GetFactory(model.RegistryTypeJfrogArtifactory) assert.Nil(t, err) assert.NotNil(t, factory) - a, err := factory(registry) + a, err := newAdapter(registry) assert.Nil(t, err) return a.(*adapter), server diff --git a/src/replication/adapter/native/adapter.go b/src/replication/adapter/native/adapter.go index 887448ed7..64c8e9cb7 100644 --- a/src/replication/adapter/native/adapter.go +++ b/src/replication/adapter/native/adapter.go @@ -35,9 +35,7 @@ import ( ) func init() { - if err := adp.RegisterFactory(model.RegistryTypeDockerRegistry, func(registry *model.Registry) (adp.Adapter, error) { - return NewAdapter(registry) - }); err != nil { + if err := adp.RegisterFactory(model.RegistryTypeDockerRegistry, new(factory)); err != nil { log.Errorf("failed to register factory for %s: %v", model.RegistryTypeDockerRegistry, err) return } @@ -46,6 +44,19 @@ func init() { var _ adp.Adapter = &Adapter{} +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return NewAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return nil +} + // Adapter implements an adapter for Docker registry. It can be used to all registries // that implement the registry V2 API type Adapter struct { diff --git a/src/replication/adapter/quayio/adapter.go b/src/replication/adapter/quayio/adapter.go index 01dc5c5d8..cf775ca73 100644 --- a/src/replication/adapter/quayio/adapter.go +++ b/src/replication/adapter/quayio/adapter.go @@ -26,9 +26,7 @@ type adapter struct { } func init() { - err := adp.RegisterFactory(model.RegistryTypeQuayio, func(registry *model.Registry) (adp.Adapter, error) { - return newAdapter(registry) - }) + err := adp.RegisterFactory(model.RegistryTypeQuayio, new(factory)) if err != nil { log.Errorf("failed to register factory for Quay.io: %v", err) return @@ -68,6 +66,19 @@ func newAdapter(registry *model.Registry) (*adapter, error) { }, nil } +type factory struct { +} + +// Create ... +func (f *factory) Create(r *model.Registry) (adp.Adapter, error) { + return newAdapter(r) +} + +// AdapterPattern ... +func (f *factory) AdapterPattern() *model.AdapterPattern { + return nil +} + // Info returns information of the registry func (a *adapter) Info() (*model.RegistryInfo, error) { return &model.RegistryInfo{ diff --git a/src/replication/adapter/quayio/adapter_test.go b/src/replication/adapter/quayio/adapter_test.go index a77218c0b..5bbe70b15 100644 --- a/src/replication/adapter/quayio/adapter_test.go +++ b/src/replication/adapter/quayio/adapter_test.go @@ -10,7 +10,7 @@ import ( func getMockAdapter(t *testing.T) adp.Adapter { factory, _ := adp.GetFactory(model.RegistryTypeQuayio) - adapter, err := factory(&model.Registry{ + adapter, err := factory.Create(&model.Registry{ Type: model.RegistryTypeQuayio, URL: "https://quay.io", }) diff --git a/src/replication/model/registry.go b/src/replication/model/registry.go index cdcc0a1f4..1a0ef85e0 100644 --- a/src/replication/model/registry.go +++ b/src/replication/model/registry.go @@ -116,6 +116,58 @@ type FilterStyle struct { Values []string `json:"values,omitempty"` } +// EndpointPattern ... +type EndpointPattern struct { + EndpointType EndpointType `json:"endpoint_type"` + Endpoints []*Endpoint `json:"endpoints"` +} + +// EndpointType .. +type EndpointType string + +const ( + // EndpointPatternTypeStandard ... + EndpointPatternTypeStandard EndpointType = "EndpointPatternTypeStandard" + // EndpointPatternTypeFix ... + EndpointPatternTypeFix EndpointType = "EndpointPatternTypeFix" + // EndpointPatternTypeList ... + EndpointPatternTypeList EndpointType = "EndpointPatternTypeList" +) + +// Endpoint ... +type Endpoint struct { + Key string `json:"key"` + Value string `json:"value"` +} + +// CredentialPattern ... +type CredentialPattern struct { + AccessKeyType AccessKeyType `json:"access_key_type"` + AccessKeyData string `json:"access_key_data"` + AccessSecretType AccessSecretType `json:"access_secret_type"` + AccessSecretData string `json:"access_secret_data"` +} + +// AccessKeyType .. +type AccessKeyType string + +const ( + // AccessKeyTypeStandard ... + AccessKeyTypeStandard AccessKeyType = "AccessKeyTypeStandard" + // AccessKeyTypeFix ... + AccessKeyTypeFix AccessKeyType = "AccessKeyTypeFix" +) + +// AccessSecretType ... +type AccessSecretType string + +const ( + // AccessSecretTypeStandard ... + AccessSecretTypeStandard AccessSecretType = "AccessSecretTypePass" + // AccessSecretTypeFile ... + AccessSecretTypeFile AccessSecretType = "AccessSecretTypeFile" +) + // RegistryInfo provides base info and capability declarations of the registry type RegistryInfo struct { Type RegistryType `json:"type"` @@ -124,3 +176,32 @@ type RegistryInfo struct { SupportedResourceFilters []*FilterStyle `json:"supported_resource_filters"` SupportedTriggers []TriggerType `json:"supported_triggers"` } + +// AdapterPattern provides base info and capability declarations of the registry +type AdapterPattern struct { + EndpointPattern *EndpointPattern `json:"endpoint_pattern"` + CredentialPattern *CredentialPattern `json:"credential_pattern"` +} + +// NewDefaultAdapterPattern ... +func NewDefaultAdapterPattern() *AdapterPattern { + return &AdapterPattern{ + EndpointPattern: NewDefaultEndpointPattern(), + CredentialPattern: NewDefaultCredentialPattern(), + } +} + +// NewDefaultEndpointPattern ... +func NewDefaultEndpointPattern() *EndpointPattern { + return &EndpointPattern{ + EndpointType: EndpointPatternTypeStandard, + } +} + +// NewDefaultCredentialPattern ... +func NewDefaultCredentialPattern() *CredentialPattern { + return &CredentialPattern{ + AccessKeyType: AccessKeyTypeStandard, + AccessSecretType: AccessSecretTypeStandard, + } +} diff --git a/src/replication/operation/controller_test.go b/src/replication/operation/controller_test.go index 9da380c6a..7c39bbfef 100644 --- a/src/replication/operation/controller_test.go +++ b/src/replication/operation/controller_test.go @@ -113,10 +113,17 @@ func (f *fakedScheduler) Stop(id string) error { return nil } -func fakedAdapterFactory(*model.Registry) (adapter.Adapter, error) { +type fakedFactory struct { +} + +func (fakedFactory) Create(*model.Registry) (adapter.Adapter, error) { return &fakedAdapter{}, nil } +func (fakedFactory) AdapterPattern() *model.AdapterPattern { + return nil +} + type fakedAdapter struct{} func (f *fakedAdapter) Info() (*model.RegistryInfo, error) { @@ -212,7 +219,7 @@ func TestMain(m *testing.M) { } func TestStartReplication(t *testing.T) { - err := adapter.RegisterFactory(model.RegistryTypeHarbor, fakedAdapterFactory) + err := adapter.RegisterFactory(model.RegistryTypeHarbor, new(fakedFactory)) require.Nil(t, err) config.Config = &config.Configuration{} diff --git a/src/replication/operation/flow/stage.go b/src/replication/operation/flow/stage.go index 0e49f4820..f9e064d83 100644 --- a/src/replication/operation/flow/stage.go +++ b/src/replication/operation/flow/stage.go @@ -38,7 +38,7 @@ func initialize(policy *model.Policy) (adp.Adapter, adp.Adapter, error) { if err != nil { return nil, nil, fmt.Errorf("failed to get adapter factory for registry type %s: %v", policy.SrcRegistry.Type, err) } - srcAdapter, err = srcFactory(policy.SrcRegistry) + srcAdapter, err = srcFactory.Create(policy.SrcRegistry) if err != nil { return nil, nil, fmt.Errorf("failed to create adapter for source registry %s: %v", policy.SrcRegistry.URL, err) } @@ -48,7 +48,7 @@ func initialize(policy *model.Policy) (adp.Adapter, adp.Adapter, error) { if err != nil { return nil, nil, fmt.Errorf("failed to get adapter factory for registry type %s: %v", policy.DestRegistry.Type, err) } - dstAdapter, err = dstFactory(policy.DestRegistry) + dstAdapter, err = dstFactory.Create(policy.DestRegistry) if err != nil { return nil, nil, fmt.Errorf("failed to create adapter for destination registry %s: %v", policy.DestRegistry.URL, err) } diff --git a/src/replication/operation/flow/stage_test.go b/src/replication/operation/flow/stage_test.go index b26857488..be03b220b 100644 --- a/src/replication/operation/flow/stage_test.go +++ b/src/replication/operation/flow/stage_test.go @@ -29,10 +29,17 @@ import ( "github.com/stretchr/testify/require" ) -func fakedAdapterFactory(*model.Registry) (adapter.Adapter, error) { +type fakedFactory struct { +} + +func (fakedFactory) Create(*model.Registry) (adapter.Adapter, error) { return &fakedAdapter{}, nil } +func (fakedFactory) AdapterPattern() *model.AdapterPattern { + return nil +} + type fakedAdapter struct{} func (f *fakedAdapter) Info() (*model.RegistryInfo, error) { @@ -194,7 +201,7 @@ func TestMain(m *testing.M) { config.Config = &config.Configuration{ CoreURL: url, } - if err := adapter.RegisterFactory(model.RegistryTypeHarbor, fakedAdapterFactory); err != nil { + if err := adapter.RegisterFactory(model.RegistryTypeHarbor, new(fakedFactory)); err != nil { os.Exit(1) } os.Exit(m.Run()) diff --git a/src/replication/registry/manager.go b/src/replication/registry/manager.go index d29f69244..34628f2e8 100644 --- a/src/replication/registry/manager.go +++ b/src/replication/registry/manager.go @@ -195,7 +195,7 @@ func CheckHealthStatus(r *model.Registry) (model.HealthStatus, error) { return model.Unknown, fmt.Errorf("get adaper for type '%s' error: %v", r.Type, err) } - rAdapter, err := factory(r) + rAdapter, err := factory.Create(r) if err != nil { return model.Unknown, fmt.Errorf("generate '%s' type adapter form factory error: %v", r.Type, err) } diff --git a/src/replication/transfer/chart/transfer.go b/src/replication/transfer/chart/transfer.go index 3a7604374..08facf6c7 100644 --- a/src/replication/transfer/chart/transfer.go +++ b/src/replication/transfer/chart/transfer.go @@ -106,7 +106,7 @@ func createRegistry(reg *model.Registry) (adapter.ChartRegistry, error) { if err != nil { return nil, err } - ad, err := factory(reg) + ad, err := factory.Create(reg) if err != nil { return nil, err } diff --git a/src/replication/transfer/image/transfer.go b/src/replication/transfer/image/transfer.go index 898eebb8f..8a31b0ed0 100644 --- a/src/replication/transfer/image/transfer.go +++ b/src/replication/transfer/image/transfer.go @@ -113,7 +113,7 @@ func createRegistry(reg *model.Registry) (adapter.ImageRegistry, error) { if err != nil { return nil, err } - ad, err := factory(reg) + ad, err := factory.Create(reg) if err != nil { return nil, err }