mirror of https://github.com/goharbor/harbor.git
222 lines
5.8 KiB
Go
222 lines
5.8 KiB
Go
// 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 replication
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
|
|
"github.com/goharbor/harbor/src/controller/event"
|
|
repevent "github.com/goharbor/harbor/src/controller/event/handler/replication/event"
|
|
"github.com/goharbor/harbor/src/controller/project"
|
|
"github.com/goharbor/harbor/src/lib/log"
|
|
"github.com/goharbor/harbor/src/lib/orm"
|
|
"github.com/goharbor/harbor/src/pkg/label"
|
|
labmodel "github.com/goharbor/harbor/src/pkg/label/model"
|
|
"github.com/goharbor/harbor/src/pkg/reg/model"
|
|
)
|
|
|
|
// Handler ...
|
|
type Handler struct {
|
|
}
|
|
|
|
// Name ...
|
|
func (r *Handler) Name() string {
|
|
return "Replication"
|
|
}
|
|
|
|
// Handle ...
|
|
func (r *Handler) Handle(ctx context.Context, value interface{}) error {
|
|
pushArtEvent, ok := value.(*event.PushArtifactEvent)
|
|
if ok {
|
|
return r.handlePushArtifact(ctx, pushArtEvent)
|
|
}
|
|
deleteArtEvent, ok := value.(*event.DeleteArtifactEvent)
|
|
if ok {
|
|
return r.handleDeleteArtifact(ctx, deleteArtEvent)
|
|
}
|
|
createTagEvent, ok := value.(*event.CreateTagEvent)
|
|
if ok {
|
|
return r.handleCreateTag(ctx, createTagEvent)
|
|
}
|
|
deleteTagEvent, ok := value.(*event.DeleteTagEvent)
|
|
if ok {
|
|
return r.handleDeleteTag(ctx, deleteTagEvent)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// IsStateful ...
|
|
func (r *Handler) IsStateful() bool {
|
|
return false
|
|
}
|
|
|
|
// abstractLabelNames returns labels name.
|
|
func abstractLabelNames(labels []*labmodel.Label) []string {
|
|
res := make([]string, 0, len(labels))
|
|
for _, lab := range labels {
|
|
res = append(res, lab.Name)
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
func (r *Handler) handlePushArtifact(ctx context.Context, event *event.PushArtifactEvent) error {
|
|
art := event.Artifact
|
|
public := false
|
|
prj, err := project.Ctl.Get(orm.Context(), art.ProjectID, project.Metadata(true))
|
|
if err != nil {
|
|
log.Errorf("failed to get project: %d, error: %v", art.ProjectID, err)
|
|
return err
|
|
}
|
|
public = prj.IsPublic()
|
|
// list attached labels
|
|
labels, err := label.Mgr.ListByArtifact(ctx, art.ID)
|
|
if err != nil {
|
|
log.Errorf("failed to list artifact %d labels, error: %v", art.ID, err)
|
|
return err
|
|
}
|
|
|
|
e := &repevent.Event{
|
|
Type: repevent.EventTypeArtifactPush,
|
|
Resource: &model.Resource{
|
|
Type: model.ResourceTypeArtifact,
|
|
Metadata: &model.ResourceMetadata{
|
|
Repository: &model.Repository{
|
|
Name: event.Repository,
|
|
Metadata: map[string]interface{}{
|
|
"public": strconv.FormatBool(public),
|
|
},
|
|
},
|
|
Artifacts: []*model.Artifact{
|
|
{
|
|
Type: art.Type,
|
|
Digest: art.Digest,
|
|
Tags: event.Tags,
|
|
Labels: abstractLabelNames(labels),
|
|
}},
|
|
},
|
|
},
|
|
Operator: event.Operator,
|
|
}
|
|
return repevent.Handle(ctx, e)
|
|
}
|
|
|
|
func (r *Handler) handleDeleteArtifact(ctx context.Context, event *event.DeleteArtifactEvent) error {
|
|
art := event.Artifact
|
|
// list attached labels
|
|
labels, err := label.Mgr.ListByArtifact(ctx, art.ID)
|
|
if err != nil {
|
|
log.Errorf("failed to list artifact %d labels, error: %v", art.ID, err)
|
|
return err
|
|
}
|
|
|
|
e := &repevent.Event{
|
|
Type: repevent.EventTypeArtifactDelete,
|
|
Resource: &model.Resource{
|
|
Type: model.ResourceTypeArtifact,
|
|
Metadata: &model.ResourceMetadata{
|
|
Repository: &model.Repository{
|
|
Name: event.Repository,
|
|
},
|
|
Artifacts: []*model.Artifact{
|
|
{
|
|
Type: art.Type,
|
|
Digest: art.Digest,
|
|
Tags: event.Tags,
|
|
Labels: abstractLabelNames(labels),
|
|
}},
|
|
},
|
|
Deleted: true,
|
|
},
|
|
Operator: event.Operator,
|
|
}
|
|
return repevent.Handle(ctx, e)
|
|
}
|
|
|
|
func (r *Handler) handleCreateTag(ctx context.Context, event *event.CreateTagEvent) error {
|
|
art := event.AttachedArtifact
|
|
public := false
|
|
prj, err := project.Ctl.Get(orm.Context(), art.ProjectID, project.Metadata(true))
|
|
if err != nil {
|
|
log.Errorf("failed to get project: %d, error: %v", art.ProjectID, err)
|
|
return err
|
|
}
|
|
public = prj.IsPublic()
|
|
// list attached labels
|
|
labels, err := label.Mgr.ListByArtifact(ctx, art.ID)
|
|
if err != nil {
|
|
log.Errorf("failed to list artifact %d labels, error: %v", art.ID, err)
|
|
return err
|
|
}
|
|
|
|
e := &repevent.Event{
|
|
Type: repevent.EventTypeArtifactPush,
|
|
Resource: &model.Resource{
|
|
Type: model.ResourceTypeArtifact,
|
|
Metadata: &model.ResourceMetadata{
|
|
Repository: &model.Repository{
|
|
Name: event.Repository,
|
|
Metadata: map[string]interface{}{
|
|
"public": strconv.FormatBool(public),
|
|
},
|
|
},
|
|
Artifacts: []*model.Artifact{
|
|
{
|
|
Type: art.Type,
|
|
Digest: art.Digest,
|
|
Tags: []string{event.Tag},
|
|
Labels: abstractLabelNames(labels),
|
|
}},
|
|
},
|
|
},
|
|
Operator: event.Operator,
|
|
}
|
|
return repevent.Handle(ctx, e)
|
|
}
|
|
|
|
func (r *Handler) handleDeleteTag(ctx context.Context, event *event.DeleteTagEvent) error {
|
|
art := event.AttachedArtifact
|
|
// list attached labels
|
|
labels, err := label.Mgr.ListByArtifact(ctx, art.ID)
|
|
if err != nil {
|
|
log.Errorf("failed to list artifact %d labels, error: %v", art.ID, err)
|
|
return err
|
|
}
|
|
|
|
e := &repevent.Event{
|
|
Type: repevent.EventTypeTagDelete,
|
|
Resource: &model.Resource{
|
|
Type: model.ResourceTypeArtifact,
|
|
Metadata: &model.ResourceMetadata{
|
|
Repository: &model.Repository{
|
|
Name: event.Repository,
|
|
},
|
|
Artifacts: []*model.Artifact{
|
|
{
|
|
Type: art.Type,
|
|
Digest: art.Digest,
|
|
Tags: []string{event.Tag},
|
|
Labels: abstractLabelNames(labels),
|
|
}},
|
|
},
|
|
Deleted: true,
|
|
IsDeleteTag: true,
|
|
},
|
|
Operator: event.Operator,
|
|
}
|
|
return repevent.Handle(ctx, e)
|
|
}
|