Skip to content

Commit

Permalink
Allow to mute Object/Incident via specific events
Browse files Browse the repository at this point in the history
  • Loading branch information
yhabteab committed Jun 4, 2024
1 parent 7cdb7f5 commit 3c76ed8
Show file tree
Hide file tree
Showing 14 changed files with 307 additions and 115 deletions.
12 changes: 12 additions & 0 deletions internal/event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ type Event struct {
Username string `json:"username"`
Message string `json:"message"`

Mute types.Bool `json:"mute"`
MuteReason string `json:"mute_reason"`

ID int64 `json:"-"`
}

Expand Down Expand Up @@ -64,6 +67,9 @@ func (e *Event) Validate() error {
if e.Severity != SeverityNone && e.Type != TypeState {
return fmt.Errorf("invalid event: if 'severity' is set, 'type' must be set to %q", TypeState)
}
if e.Mute.Valid && e.Mute.Bool && e.MuteReason == "" {
return fmt.Errorf("invalid event: 'mute_reason' must not be empty if 'mute' is set")
}

switch e.Type {
case "":
Expand All @@ -84,6 +90,12 @@ func (e *Event) Validate() error {
}
}

// SetMute alters the event mute and mute reason.
func (e *Event) SetMute(muted bool, reason string) {
e.Mute = types.Bool{Valid: true, Bool: muted}
e.MuteReason = reason
}

func (e *Event) String() string {
return fmt.Sprintf("[time=%s type=%q severity=%s]", e.Time, e.Type, e.Severity.String())
}
Expand Down
62 changes: 32 additions & 30 deletions internal/icinga2/api_responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,16 @@ type CheckResult struct {
//
// NOTE:
// - An empty Service field indicates a host downtime.
// - If a downtime was added by a ScheduledDowntime object, ConfigOwner is set to the name of that object and can
// only be cancelled by its owner. Otherwise, it is empty and indicates user-created downtimes (via API or/and UI).
//
// https://icinga.com/docs/icinga-2/latest/doc/09-object-types/#objecttype-downtime
type Downtime struct {
Host string `json:"host_name"`
Service string `json:"service_name"`
Author string `json:"author"`
Comment string `json:"comment"`
Host string `json:"host_name"`
Service string `json:"service_name"`
Author string `json:"author"`
Comment string `json:"comment"`
ConfigOwner string `json:"config_owner"`

// RemoveTime is used to indicate whether a downtime was ended automatically or cancelled prematurely by a user.
// It is set to zero time for the former case, otherwise to the timestamp at which time has been cancelled.
Expand Down Expand Up @@ -133,6 +136,7 @@ type HostServiceRuntimeAttributes struct {
LastStateChange UnixFloat `json:"last_state_change"`
DowntimeDepth int `json:"downtime_depth"`
Acknowledgement int `json:"acknowledgement"`
IsFlapping bool `json:"flapping"`
AcknowledgementLastChange UnixFloat `json:"acknowledgement_last_change"`
}

Expand Down Expand Up @@ -179,40 +183,32 @@ type StateChange struct {
CheckResult CheckResult `json:"check_result"`
DowntimeDepth int `json:"downtime_depth"`
Acknowledgement bool `json:"acknowledgement"`

// There is no such json key in the Icinga 2 API streams for state change events, so exclude it.
// This is going to be set/unset manually within this icinga2 package.
IsFlapping bool `json:"-"`
}

// AcknowledgementSet represents the Icinga 2 API Event Stream AcknowledgementSet response for acknowledgements set on hosts/services.
// Acknowledgement represents the Icinga 2 API Event Stream AcknowledgementSet or AcknowledgementCleared
// response for acknowledgements set/cleared on/from hosts/services.
//
// NOTE:
// - An empty Service field indicates a host acknowledgement.
// - State might be StateHost{Up,Down} for hosts or StateService{Ok,Warning,Critical,Unknown} for services.
// - StateType might be StateTypeSoft or StateTypeHard.
// - EventType is either set to typeAcknowledgementSet or typeAcknowledgementCleared
//
// https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#event-stream-type-acknowledgementset
type AcknowledgementSet struct {
// https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#event-stream-type-acknowledgementcleared
type Acknowledgement struct {
Timestamp UnixFloat `json:"timestamp"`
Host string `json:"host"`
Service string `json:"service"`
State int `json:"state"`
StateType int `json:"state_type"`
Author string `json:"author"`
Comment string `json:"comment"`
}

// AcknowledgementCleared represents the Icinga 2 API Event Stream AcknowledgementCleared response for acknowledgements cleared on hosts/services.
//
// NOTE:
// - An empty Service field indicates a host acknowledgement.
// - State might be StateHost{Up,Down} for hosts or StateService{Ok,Warning,Critical,Unknown} for services.
// - StateType might be StateTypeSoft or StateTypeHard.
//
// https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#event-stream-type-acknowledgementcleared
type AcknowledgementCleared struct {
Timestamp UnixFloat `json:"timestamp"`
Host string `json:"host"`
Service string `json:"service"`
State int `json:"state"`
StateType int `json:"state_type"`
EventType string `json:"type"`
}

// CommentAdded represents the Icinga 2 API Event Stream CommentAdded response for added host/service comments.
Expand Down Expand Up @@ -267,13 +263,21 @@ type DowntimeTriggered struct {
//
// NOTE:
// - An empty Service field indicates a host being in flapping state.
// - State includes the current state of the Checkable at the point in time at which it enters or exits the flapping state.
// - CurrentFlapping indicates the current flapping value of a Checkable in percent.
// - ThresholdLow is the low/min flapping threshold value set by the user (CurrentFlapping < ThresholdLow = flapping end).
// - ThresholdHigh is the high/max flapping threshold value set by the user (CurrentFlapping > ThresholdHigh = flapping start).
//
// https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#event-stream-type-flapping
type Flapping struct {
Timestamp UnixFloat `json:"timestamp"`
Host string `json:"host"`
Service string `json:"service"`
IsFlapping bool `json:"is_flapping"`
Timestamp UnixFloat `json:"timestamp"`
Host string `json:"host"`
Service string `json:"service"`
IsFlapping bool `json:"is_flapping"`
State int `json:"state"`
CurrentFlapping int `json:"current_flapping"`
ThresholdLow int `json:"threshold_low"`
ThresholdHigh int `json:"threshold_high"`
}

// CheckableCreatedDeleted represents the Icinga 2 API stream Checkable created/deleted response.
Expand Down Expand Up @@ -339,10 +343,8 @@ func UnmarshalEventStreamResponse(bytes []byte) (any, error) {
switch responseType {
case typeStateChange:
resp = new(StateChange)
case typeAcknowledgementSet:
resp = new(AcknowledgementSet)
case typeAcknowledgementCleared:
resp = new(AcknowledgementCleared)
case typeAcknowledgementSet, typeAcknowledgementCleared:
resp = new(Acknowledgement)
case typeCommentAdded:
resp = new(CommentAdded)
case typeCommentRemoved:
Expand Down
25 changes: 15 additions & 10 deletions internal/icinga2/api_responses_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,13 @@ func TestObjectQueriesResult_UnmarshalJSON(t *testing.T) {
Name: "docker-master!load!c27b27c2-e0ab-45ff-8b9b-e95f29851eb0",
Type: "Downtime",
Attrs: Downtime{
Host: "docker-master",
Service: "load",
Author: "icingaadmin",
Comment: "Scheduled downtime for backup",
RemoveTime: UnixFloat(time.UnixMilli(0)),
IsFixed: true,
Host: "docker-master",
Service: "load",
Author: "icingaadmin",
Comment: "Scheduled downtime for backup",
ConfigOwner: "docker-master!load!backup-downtime",
RemoveTime: UnixFloat(time.UnixMilli(0)),
IsFixed: true,
},
},
},
Expand Down Expand Up @@ -373,47 +374,51 @@ func TestApiResponseUnmarshal(t *testing.T) {
{
name: "acknowledgementset-host",
jsonData: `{"acknowledgement_type":1,"author":"icingaadmin","comment":"working on it","expiry":0,"host":"dummy-805","notify":true,"persistent":false,"state":1,"state_type":1,"timestamp":1697201074.579106,"type":"AcknowledgementSet"}`,
expected: &AcknowledgementSet{
expected: &Acknowledgement{
Timestamp: UnixFloat(time.UnixMicro(1697201074579106)),
Host: "dummy-805",
State: StateHostDown,
StateType: StateTypeHard,
Author: "icingaadmin",
Comment: "working on it",
EventType: typeAcknowledgementSet,
},
},
{
name: "acknowledgementset-service",
jsonData: `{"acknowledgement_type":1,"author":"icingaadmin","comment":"will be fixed soon","expiry":0,"host":"docker-master","notify":true,"persistent":false,"service":"ssh","state":2,"state_type":1,"timestamp":1697201107.64792,"type":"AcknowledgementSet"}`,
expected: &AcknowledgementSet{
expected: &Acknowledgement{
Timestamp: UnixFloat(time.UnixMicro(1697201107647920)),
Host: "docker-master",
Service: "ssh",
State: StateServiceCritical,
StateType: StateTypeHard,
Author: "icingaadmin",
Comment: "will be fixed soon",
EventType: typeAcknowledgementSet,
},
},
{
name: "acknowledgementcleared-host",
jsonData: `{"acknowledgement_type":0,"host":"dummy-805","state":1,"state_type":1,"timestamp":1697201082.440148,"type":"AcknowledgementCleared"}`,
expected: &AcknowledgementCleared{
expected: &Acknowledgement{
Timestamp: UnixFloat(time.UnixMicro(1697201082440148)),
Host: "dummy-805",
State: StateHostDown,
StateType: StateTypeHard,
EventType: typeAcknowledgementCleared,
},
},
{
name: "acknowledgementcleared-service",
jsonData: `{"acknowledgement_type":0,"host":"docker-master","service":"ssh","state":2,"state_type":1,"timestamp":1697201110.220349,"type":"AcknowledgementCleared"}`,
expected: &AcknowledgementCleared{
expected: &Acknowledgement{
Timestamp: UnixFloat(time.UnixMicro(1697201110220349)),
Host: "docker-master",
Service: "ssh",
State: StateServiceCritical,
StateType: StateTypeHard,
EventType: typeAcknowledgementCleared,
},
},
{
Expand Down
Loading

0 comments on commit 3c76ed8

Please sign in to comment.