open-nomad/nomad/structs/event.go
Drew Bailey d62d8a8587
Event sink manager improvements (#9206)
* Improve managed sink run loop and reloading

resetCh no longer needed

length of buffer equal to count of items, not count of events in each item

update equality fn name, pr feedback

clean up sink manager sink creation

* update test to reflect changes

* bad editor find and replace

* pr feedback
2020-11-02 09:21:32 -05:00

170 lines
3.6 KiB
Go

package structs
import (
"fmt"
"net/url"
"reflect"
"strings"
multierror "github.com/hashicorp/go-multierror"
)
// EventStreamRequest is used to stream events from a servers EventBroker
type EventStreamRequest struct {
Topics map[Topic][]string
Index int
QueryOptions
}
type EventStreamWrapper struct {
Error *RpcError
Event *EventJson
}
type Topic string
const (
TopicDeployment Topic = "Deployment"
TopicEval Topic = "Eval"
TopicAlloc Topic = "Alloc"
TopicJob Topic = "Job"
TopicNode Topic = "Node"
TopicAll Topic = "*"
)
// Event represents a change in Nomads state.
type Event struct {
// Topic represeents the primary object for the event
Topic Topic
// Type is a short string representing the reason for the event
Type string
// Key is the primary identifier of the Event, The involved objects ID
Key string
// Namespace is the namespace of the object, If the object is not namespace
// aware (Node) it is left blank
Namespace string
// FilterKeys are a set of additional related keys that are used to include
// events during filtering.
FilterKeys []string
// Index is the raft index that corresponds to the event
Index uint64
// Payload is the Event itself see state/events.go for a list of events
Payload interface{}
}
// Events is a wrapper that contains a set of events for a given index.
type Events struct {
Index uint64
Events []Event
}
// EventJson is a wrapper for a JSON object
type EventJson struct {
Data []byte
}
func (j *EventJson) Copy() *EventJson {
n := new(EventJson)
*n = *j
n.Data = make([]byte, len(j.Data))
copy(n.Data, j.Data)
return n
}
type EventSinkProgressRequest struct {
Sinks []*EventSink
WriteRequest
}
type EventSinkUpsertRequest struct {
Sink *EventSink
WriteRequest
}
type EventSinkSpecificRequest struct {
ID string
QueryOptions
}
type EventSinkResponse struct {
Sink *EventSink
QueryMeta
}
type EventSinkDeleteRequest struct {
IDs []string
WriteRequest
}
type EventSinkListRequest struct {
QueryOptions
}
type EventSinkListResponse struct {
Sinks []*EventSink
QueryMeta
}
type SinkType string
const (
SinkWebhook SinkType = "webhook"
)
type EventSink struct {
ID string
Type SinkType
Topics map[Topic][]string
Address string
// LatestIndex is the latest reported index that was successfully sent.
// MangedSinks periodically check in to update the LatestIndex so that a
// minimal amount of events are resent when reestablishing an event sink
LatestIndex uint64
CreateIndex uint64
ModifyIndex uint64
}
func (e *EventSink) Validate() error {
var mErr multierror.Error
if e.ID == "" {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Missing sink ID"))
} else if strings.Contains(e.ID, " ") {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Sink ID contains a space"))
} else if strings.Contains(e.ID, "\000") {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Sink ID contains a null character"))
}
switch e.Type {
case SinkWebhook:
if e.Address == "" {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Webhook sink requires a valid Address"))
} else if _, err := url.Parse(e.Address); err != nil {
mErr.Errors = append(mErr.Errors, fmt.Errorf("Webhook sink Address must be a valid url: %w", err))
}
default:
mErr.Errors = append(mErr.Errors, fmt.Errorf("Sink type invalid"))
}
return mErr.ErrorOrNil()
}
// EqualSubscriptionValues specifies if this event has equivalent subscription
// values to the one that we are comparing it to
func (e *EventSink) EqualSubscriptionValues(old *EventSink) bool {
return e.Address == old.Address &&
e.Type == old.Type &&
reflect.DeepEqual(e.Topics, old.Topics)
}