harbor/src/pkg/notifier/event/event.go

101 lines
2.4 KiB
Go

package event
import (
"context"
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/log"
policy_model "github.com/goharbor/harbor/src/pkg/notification/policy/model"
"github.com/goharbor/harbor/src/pkg/notifier"
"github.com/goharbor/harbor/src/pkg/notifier/model"
)
// Event to publish
type Event struct {
Topic string
Data interface{}
}
// TopicEvent - Events that contains topic information
type TopicEvent interface {
Topic() string
}
// New ...
func New() *Event {
return &Event{}
}
// WithTopicEvent - builder method
func (e *Event) WithTopicEvent(topicEvent TopicEvent) *Event {
e.Topic = topicEvent.Topic()
e.Data = topicEvent
return e
}
// Metadata is the event raw data to be processed
type Metadata interface {
Resolve(event *Event) error
}
// HookMetaData defines hook notification related event data
type HookMetaData struct {
ProjectID int64
PolicyID int64
EventType string
Target *policy_model.EventTarget
Payload *model.Payload
}
// Resolve hook metadata into hook event
func (h *HookMetaData) Resolve(evt *Event) error {
data := &model.HookEvent{
ProjectID: h.ProjectID,
PolicyID: h.PolicyID,
EventType: h.EventType,
Target: h.Target,
Payload: h.Payload,
}
evt.Topic = h.Target.Type
evt.Data = data
return nil
}
// Build an event by metadata
func (e *Event) Build(ctx context.Context, metadata ...Metadata) error {
for _, md := range metadata {
if err := md.Resolve(e); err != nil {
log.Debugf("failed to resolve event metadata: %v", md)
return errors.Wrap(err, "failed to resolve event metadata")
}
}
return nil
}
// Publish an event
func (e *Event) Publish(ctx context.Context) error {
if err := notifier.Publish(ctx, e.Topic, e.Data); err != nil {
log.Debugf("failed to publish topic %s with event: %v", e.Topic, e.Data)
return errors.Wrap(err, "failed to publish event")
}
return nil
}
// BuildAndPublish builds the event according to the metadata and publish the event
// The process is done in a separated goroutine
func BuildAndPublish(ctx context.Context, metadata ...Metadata) {
go func() {
event := &Event{}
if err := event.Build(ctx, metadata...); err != nil {
log.Errorf("failed to build the event from metadata: %v", err)
return
}
if err := event.Publish(ctx); err != nil {
log.Errorf("failed to publish the event %s: %v", event.Topic, err)
return
}
log.Debugf("event %s published", event.Topic)
}()
}