mirror of
https://github.com/goharbor/harbor.git
synced 2025-02-22 23:01:33 +01:00
Add valid method to adapter to valid resource
Signed-off-by: cd1989 <chende@caicloud.io>
This commit is contained in:
parent
1231c533db
commit
cc4f08cc04
@ -39,6 +39,9 @@ type Adapter interface {
|
|||||||
// PrepareForPush does the prepare work that needed for pushing/uploading the resource
|
// PrepareForPush does the prepare work that needed for pushing/uploading the resource
|
||||||
// eg: create the namespace or repository
|
// eg: create the namespace or repository
|
||||||
PrepareForPush(*model.Resource) error
|
PrepareForPush(*model.Resource) error
|
||||||
|
// ValidResource checks whether a resource is valid for the registry. For example, DockerHub don't support
|
||||||
|
// multiple parts repo name like 'a/b/c'.
|
||||||
|
ValidResource(*model.Resource) bool
|
||||||
// Get the namespace specified by the name, the returning value should
|
// Get the namespace specified by the name, the returning value should
|
||||||
// contain the metadata about the namespace if it has
|
// contain the metadata about the namespace if it has
|
||||||
// TODO remove this method?
|
// TODO remove this method?
|
||||||
|
@ -51,7 +51,8 @@ var _ adp.Adapter = (*adapter)(nil)
|
|||||||
// Info returns information of the registry
|
// Info returns information of the registry
|
||||||
func (a *adapter) Info() (*model.RegistryInfo, error) {
|
func (a *adapter) Info() (*model.RegistryInfo, error) {
|
||||||
return &model.RegistryInfo{
|
return &model.RegistryInfo{
|
||||||
Type: model.RegistryTypeDockerHub,
|
Type: model.RegistryTypeDockerHub,
|
||||||
|
SupportNamespace: true,
|
||||||
SupportedResourceTypes: []model.ResourceType{
|
SupportedResourceTypes: []model.ResourceType{
|
||||||
model.ResourceTypeRepository,
|
model.ResourceTypeRepository,
|
||||||
},
|
},
|
||||||
@ -67,13 +68,54 @@ func (a *adapter) Info() (*model.RegistryInfo, error) {
|
|||||||
},
|
},
|
||||||
SupportedTriggers: []model.TriggerType{
|
SupportedTriggers: []model.TriggerType{
|
||||||
model.TriggerTypeManual,
|
model.TriggerTypeManual,
|
||||||
|
model.TriggerTypeScheduled,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HealthCheck checks health status of the registry
|
// ValidResource checks whether a resource is valid, in DockerHub, multi-parts repo name like 'a/b/c' is not supported.
|
||||||
func (a *adapter) HealthCheck() (model.HealthStatus, error) {
|
func (a *adapter) ValidResource(resource *model.Resource) bool {
|
||||||
return model.Healthy, nil
|
if resource == nil || resource.Metadata == nil || resource.Metadata.Repository == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(strings.Split(resource.Metadata.Repository.Name, "/")) != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertResourceMetadata converts the namespace and repository part of the resource metadata
|
||||||
|
// to the one that the adapter can handle
|
||||||
|
func (a *adapter) ConvertResourceMetadata(meta *model.ResourceMetadata, namespace *model.Namespace) (*model.ResourceMetadata, error) {
|
||||||
|
return meta, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrepareForPush does the prepare work that needed for pushing/uploading the resource
|
||||||
|
// eg: create the namespace or repository
|
||||||
|
func (a *adapter) PrepareForPush(resource *model.Resource) error {
|
||||||
|
if resource == nil {
|
||||||
|
return errors.New("the resource cannot be null")
|
||||||
|
}
|
||||||
|
if resource.Metadata == nil {
|
||||||
|
return errors.New("the metadata of resource cannot be null")
|
||||||
|
}
|
||||||
|
if resource.Metadata.Namespace == nil {
|
||||||
|
return errors.New("the namespace of resource cannot be null")
|
||||||
|
}
|
||||||
|
if len(resource.Metadata.Namespace.Name) == 0 {
|
||||||
|
return errors.New("the name of the namespace cannot be null")
|
||||||
|
}
|
||||||
|
|
||||||
|
err := a.CreateNamespace(&model.Namespace{
|
||||||
|
Name: resource.Metadata.Namespace.Name,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create namespace '%s' in DockerHub error: %v", resource.Metadata.Namespace.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListNamespaces lists namespaces from DockerHub with the provided query conditions.
|
// ListNamespaces lists namespaces from DockerHub with the provided query conditions.
|
||||||
@ -273,9 +315,13 @@ func (a *adapter) FetchImages(namespaces []string, filters []*model.Filter) ([]*
|
|||||||
Type: model.ResourceTypeRepository,
|
Type: model.ResourceTypeRepository,
|
||||||
Registry: a.registry,
|
Registry: a.registry,
|
||||||
Metadata: &model.ResourceMetadata{
|
Metadata: &model.ResourceMetadata{
|
||||||
Namespace: repo.Namespace,
|
Namespace: &model.Namespace{
|
||||||
Name: fmt.Sprintf("%s/%s", repo.Namespace, repo.Name),
|
Name: repo.Namespace,
|
||||||
Vtags: tags,
|
},
|
||||||
|
Repository: &model.Repository{
|
||||||
|
Name: repo.Name,
|
||||||
|
},
|
||||||
|
Vtags: tags,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -48,21 +48,3 @@ func TestListNamespaces(t *testing.T) {
|
|||||||
fmt.Println(ns.Name)
|
fmt.Println(ns.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateNamespace(t *testing.T) {
|
|
||||||
if testUser == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
assert := assert.New(t)
|
|
||||||
adapter := getAdapter(t)
|
|
||||||
|
|
||||||
err := adapter.CreateNamespace(&model.Namespace{
|
|
||||||
Name: "harborns",
|
|
||||||
Metadata: map[string]interface{}{
|
|
||||||
metadataKeyFullName: "harbor namespace",
|
|
||||||
metadataKeyCompany: "harbor",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
assert.Nil(err)
|
|
||||||
}
|
|
||||||
|
@ -118,6 +118,11 @@ func (adapter Adapter) ConvertResourceMetadata(resourceMetadata *model.ResourceM
|
|||||||
return metadata, nil
|
return metadata, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidResource ...
|
||||||
|
func (adapter Adapter) ValidResource(*model.Resource) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// PrepareForPush prepare for push to Huawei SWR
|
// PrepareForPush prepare for push to Huawei SWR
|
||||||
func (adapter Adapter) PrepareForPush(resource *model.Resource) error {
|
func (adapter Adapter) PrepareForPush(resource *model.Resource) error {
|
||||||
|
|
||||||
|
@ -276,6 +276,11 @@ func (d *DefaultImageRegistry) PushBlob(repository, digest string, size int64, b
|
|||||||
return client.PushBlob(digest, size, blob)
|
return client.PushBlob(digest, size, blob)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidResource ...
|
||||||
|
func (d *DefaultImageRegistry) ValidResource(*model.Resource) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func isDigest(str string) bool {
|
func isDigest(str string) bool {
|
||||||
return strings.Contains(str, ":")
|
return strings.Contains(str, ":")
|
||||||
}
|
}
|
||||||
|
@ -69,4 +69,6 @@ type Resource struct {
|
|||||||
Deleted bool `json:"deleted"`
|
Deleted bool `json:"deleted"`
|
||||||
// indicate whether the resource can be overridden
|
// indicate whether the resource can be overridden
|
||||||
Override bool `json:"override"`
|
Override bool `json:"override"`
|
||||||
|
// Invalid indicates the resource is invalid for the registry
|
||||||
|
Invalid bool `json:"invalid"`
|
||||||
}
|
}
|
||||||
|
@ -149,6 +149,9 @@ func (f *fakedAdapter) PrepareForPush(*model.Resource) error {
|
|||||||
func (f *fakedAdapter) HealthCheck() (model.HealthStatus, error) {
|
func (f *fakedAdapter) HealthCheck() (model.HealthStatus, error) {
|
||||||
return model.Healthy, nil
|
return model.Healthy, nil
|
||||||
}
|
}
|
||||||
|
func (f *fakedAdapter) ValidResource(*model.Resource) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
func (f *fakedAdapter) GetNamespace(ns string) (*model.Namespace, error) {
|
func (f *fakedAdapter) GetNamespace(ns string) (*model.Namespace, error) {
|
||||||
var namespace *model.Namespace
|
var namespace *model.Namespace
|
||||||
if ns == "library" {
|
if ns == "library" {
|
||||||
|
@ -61,6 +61,13 @@ func (c *copyFlow) Run(interface{}) (int, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i := range dstResources {
|
||||||
|
if !dstAdapter.ValidResource(dstResources[i]) {
|
||||||
|
dstResources[i].Invalid = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err = prepareForPush(dstAdapter, dstResources); err != nil {
|
if err = prepareForPush(dstAdapter, dstResources); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -71,7 +78,14 @@ func (c *copyFlow) Run(interface{}) (int, error) {
|
|||||||
if err = createTasks(c.executionMgr, c.executionID, items); err != nil {
|
if err = createTasks(c.executionMgr, c.executionID, items); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return schedule(c.scheduler, c.executionMgr, items)
|
|
||||||
|
var filtered []*scheduler.ScheduleItem
|
||||||
|
for _, item := range items {
|
||||||
|
if !item.DstResource.Invalid {
|
||||||
|
filtered = append(filtered, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return schedule(c.scheduler, c.executionMgr, filtered)
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark the execution as success in database
|
// mark the execution as success in database
|
||||||
|
@ -64,6 +64,13 @@ func (d *deletionFlow) Run(interface{}) (int, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i := range dstResources {
|
||||||
|
if !dstAdapter.ValidResource(dstResources[i]) {
|
||||||
|
dstResources[i].Invalid = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
items, err := preprocess(d.scheduler, srcResources, dstResources)
|
items, err := preprocess(d.scheduler, srcResources, dstResources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@ -71,5 +78,13 @@ func (d *deletionFlow) Run(interface{}) (int, error) {
|
|||||||
if err = createTasks(d.executionMgr, d.executionID, items); err != nil {
|
if err = createTasks(d.executionMgr, d.executionID, items); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return schedule(d.scheduler, d.executionMgr, items)
|
|
||||||
|
var filtered []*scheduler.ScheduleItem
|
||||||
|
for _, item := range items {
|
||||||
|
if !item.DstResource.Invalid {
|
||||||
|
filtered = append(filtered, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return schedule(d.scheduler, d.executionMgr, filtered)
|
||||||
}
|
}
|
||||||
|
@ -241,6 +241,7 @@ func createTasks(mgr execution.Manager, executionID int64, items []*scheduler.Sc
|
|||||||
if item.DstResource.Deleted {
|
if item.DstResource.Deleted {
|
||||||
operation = "deletion"
|
operation = "deletion"
|
||||||
}
|
}
|
||||||
|
|
||||||
task := &models.Task{
|
task := &models.Task{
|
||||||
ExecutionID: executionID,
|
ExecutionID: executionID,
|
||||||
Status: models.TaskStatusInitialized,
|
Status: models.TaskStatusInitialized,
|
||||||
@ -249,6 +250,12 @@ func createTasks(mgr execution.Manager, executionID int64, items []*scheduler.Sc
|
|||||||
DstResource: getResourceName(item.DstResource),
|
DstResource: getResourceName(item.DstResource),
|
||||||
Operation: operation,
|
Operation: operation,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if item.DstResource.Invalid {
|
||||||
|
task.Status = models.TaskStatusFailed
|
||||||
|
task.EndTime = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
id, err := mgr.CreateTask(task)
|
id, err := mgr.CreateTask(task)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// if failed to create the task for one of the items,
|
// if failed to create the task for one of the items,
|
||||||
|
@ -62,6 +62,9 @@ func (f *fakedAdapter) PrepareForPush(*model.Resource) error {
|
|||||||
func (f *fakedAdapter) HealthCheck() (model.HealthStatus, error) {
|
func (f *fakedAdapter) HealthCheck() (model.HealthStatus, error) {
|
||||||
return model.Healthy, nil
|
return model.Healthy, nil
|
||||||
}
|
}
|
||||||
|
func (f *fakedAdapter) ValidResource(*model.Resource) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
func (f *fakedAdapter) GetNamespace(ns string) (*model.Namespace, error) {
|
func (f *fakedAdapter) GetNamespace(ns string) (*model.Namespace, error) {
|
||||||
var namespace *model.Namespace
|
var namespace *model.Namespace
|
||||||
if ns == "library" {
|
if ns == "library" {
|
||||||
|
@ -17,31 +17,31 @@ type MockJobClient struct {
|
|||||||
// GetJobLog ...
|
// GetJobLog ...
|
||||||
func (mjc *MockJobClient) GetJobLog(uuid string) ([]byte, error) {
|
func (mjc *MockJobClient) GetJobLog(uuid string) ([]byte, error) {
|
||||||
if uuid == "500" {
|
if uuid == "500" {
|
||||||
return nil, &http.Error{500, "Server side error"}
|
return nil, &http.Error{500, "server side error"}
|
||||||
}
|
}
|
||||||
if mjc.validUUID(uuid) {
|
if mjc.validUUID(uuid) {
|
||||||
return []byte("some log"), nil
|
return []byte("some log"), nil
|
||||||
}
|
}
|
||||||
return nil, &http.Error{404, "Not Found"}
|
return nil, &http.Error{404, "not Found"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubmitJob ...
|
// SubmitJob ...
|
||||||
func (mjc *MockJobClient) SubmitJob(data *models.JobData) (string, error) {
|
func (mjc *MockJobClient) SubmitJob(data *models.JobData) (string, error) {
|
||||||
if data.Name == job.ImageScanAllJob || data.Name == job.ImageReplicate || data.Name == job.ImageGC || data.Name == job.ImageScanJob {
|
if data.Name == job.ImageScanAllJob || data.Name == job.Replication || data.Name == job.ImageGC || data.Name == job.ImageScanJob {
|
||||||
uuid := fmt.Sprintf("u-%d", rand.Int())
|
uuid := fmt.Sprintf("u-%d", rand.Int())
|
||||||
mjc.JobUUID = append(mjc.JobUUID, uuid)
|
mjc.JobUUID = append(mjc.JobUUID, uuid)
|
||||||
return uuid, nil
|
return uuid, nil
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("Unsupported job %s", data.Name)
|
return "", fmt.Errorf("unsupported job %s", data.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostAction ...
|
// PostAction ...
|
||||||
func (mjc *MockJobClient) PostAction(uuid, action string) error {
|
func (mjc *MockJobClient) PostAction(uuid, action string) error {
|
||||||
if "500" == uuid {
|
if "500" == uuid {
|
||||||
return &http.Error{500, "Server side error"}
|
return &http.Error{500, "server side error"}
|
||||||
}
|
}
|
||||||
if !mjc.validUUID(uuid) {
|
if !mjc.validUUID(uuid) {
|
||||||
return &http.Error{404, "Not Found"}
|
return &http.Error{404, "not Found"}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user