// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package api
import (
"bytes"
"strconv"
)
// Event can be used to query the Event endpoints
type Event struct {
c * Client
}
// UserEvent represents an event that was fired by the user
type UserEvent struct {
ID string
Name string
Payload [ ] byte
NodeFilter string
ServiceFilter string
TagFilter string
Version int
LTime uint64
}
// Event returns a handle to the event endpoints
func ( c * Client ) Event ( ) * Event {
return & Event { c }
}
// Fire is used to fire a new user event. Only the Name, Payload and Filters
// are respected. This returns the ID or an associated error. Cross DC requests
// are supported.
func ( e * Event ) Fire ( params * UserEvent , q * WriteOptions ) ( string , * WriteMeta , error ) {
r := e . c . newRequest ( "PUT" , "/v1/event/fire/" + params . Name )
r . setWriteOptions ( q )
if params . NodeFilter != "" {
r . params . Set ( "node" , params . NodeFilter )
}
if params . ServiceFilter != "" {
r . params . Set ( "service" , params . ServiceFilter )
}
if params . TagFilter != "" {
r . params . Set ( "tag" , params . TagFilter )
}
if params . Payload != nil {
r . body = bytes . NewReader ( params . Payload )
}
r . header . Set ( "Content-Type" , "application/octet-stream" )
rtt , resp , err := e . c . doRequest ( r )
if err != nil {
return "" , nil , err
}
defer closeResponseBody ( resp )
if err := requireOK ( resp ) ; err != nil {
return "" , nil , err
}
wm := & WriteMeta { RequestTime : rtt }
var out UserEvent
if err := decodeBody ( resp , & out ) ; err != nil {
return "" , nil , err
}
return out . ID , wm , nil
}
// List is used to get the most recent events an agent has received.
// This list can be optionally filtered by the name. This endpoint supports
// quasi-blocking queries. The index is not monotonic, nor does it provide provide
// LastContact or KnownLeader.
func ( e * Event ) List ( name string , q * QueryOptions ) ( [ ] * UserEvent , * QueryMeta , error ) {
r := e . c . newRequest ( "GET" , "/v1/event/list" )
r . setQueryOptions ( q )
if name != "" {
r . params . Set ( "name" , name )
}
rtt , resp , err := e . c . doRequest ( r )
if err != nil {
return nil , nil , err
}
defer closeResponseBody ( resp )
if err := requireOK ( resp ) ; err != nil {
return nil , nil , err
}
qm := & QueryMeta { }
parseQueryMeta ( resp , qm )
qm . RequestTime = rtt
var entries [ ] * UserEvent
if err := decodeBody ( resp , & entries ) ; err != nil {
return nil , nil , err
}
return entries , qm , nil
}
// IDToIndex is a bit of a hack. This simulates the index generation to
// convert an event ID into a WaitIndex.
func ( e * Event ) IDToIndex ( uuid string ) uint64 {
lower := uuid [ 0 : 8 ] + uuid [ 9 : 13 ] + uuid [ 14 : 18 ]
upper := uuid [ 19 : 23 ] + uuid [ 24 : 36 ]
lowVal , err := strconv . ParseUint ( lower , 16 , 64 )
if err != nil {
panic ( "Failed to convert " + lower )
}
highVal , err := strconv . ParseUint ( upper , 16 , 64 )
if err != nil {
panic ( "Failed to convert " + upper )
}
return lowVal ^ highVal
}