Skip to content

Commit 0c6241f

Browse files
committed
Allow to mute Object/Incident via specific events
1 parent d415e08 commit 0c6241f

14 files changed

+304
-115
lines changed

internal/event/event.go

+12
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ type Event struct {
3434
Username string `json:"username"`
3535
Message string `json:"message"`
3636

37+
Mute types.Bool `json:"mute"`
38+
MuteReason string `json:"mute_reason"`
39+
3740
ID int64 `json:"-"`
3841
}
3942

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

6874
switch e.Type {
6975
case "":
@@ -84,6 +90,12 @@ func (e *Event) Validate() error {
8490
}
8591
}
8692

93+
// SetMute alters the event mute and mute reason.
94+
func (e *Event) SetMute(muted bool, reason string) {
95+
e.Mute = types.Bool{Valid: true, Bool: muted}
96+
e.MuteReason = reason
97+
}
98+
8799
func (e *Event) String() string {
88100
return fmt.Sprintf("[time=%s type=%q severity=%s]", e.Time, e.Type, e.Severity.String())
89101
}

internal/icinga2/api_responses.go

+29-30
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,16 @@ type CheckResult struct {
8585
//
8686
// NOTE:
8787
// - An empty Service field indicates a host downtime.
88+
// - If a downtime was added by a ScheduledDowntime object, ConfigOwner is set to the name of that object and can
89+
// only be cancelled by its owner. Otherwise, it is empty and indicates user-created downtimes (via API or/and UI).
8890
//
8991
// https://icinga.com/docs/icinga-2/latest/doc/09-object-types/#objecttype-downtime
9092
type Downtime struct {
91-
Host string `json:"host_name"`
92-
Service string `json:"service_name"`
93-
Author string `json:"author"`
94-
Comment string `json:"comment"`
93+
Host string `json:"host_name"`
94+
Service string `json:"service_name"`
95+
Author string `json:"author"`
96+
Comment string `json:"comment"`
97+
ConfigOwner string `json:"config_owner"`
9598

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

@@ -179,40 +183,29 @@ type StateChange struct {
179183
CheckResult CheckResult `json:"check_result"`
180184
DowntimeDepth int `json:"downtime_depth"`
181185
Acknowledgement bool `json:"acknowledgement"`
186+
IsFlapping bool `json:"-"`
182187
}
183188

184-
// AcknowledgementSet represents the Icinga 2 API Event Stream AcknowledgementSet response for acknowledgements set on hosts/services.
189+
// Acknowledgement represents the Icinga 2 API Event Stream AcknowledgementSet or AcknowledgementCleared
190+
// response for acknowledgements set/cleared on/from hosts/services.
185191
//
186192
// NOTE:
187193
// - An empty Service field indicates a host acknowledgement.
188194
// - State might be StateHost{Up,Down} for hosts or StateService{Ok,Warning,Critical,Unknown} for services.
189195
// - StateType might be StateTypeSoft or StateTypeHard.
196+
// - EventType is either set to typeAcknowledgementSet or typeAcknowledgementCleared
190197
//
191198
// https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#event-stream-type-acknowledgementset
192-
type AcknowledgementSet struct {
199+
// https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#event-stream-type-acknowledgementcleared
200+
type Acknowledgement struct {
193201
Timestamp UnixFloat `json:"timestamp"`
194202
Host string `json:"host"`
195203
Service string `json:"service"`
196204
State int `json:"state"`
197205
StateType int `json:"state_type"`
198206
Author string `json:"author"`
199207
Comment string `json:"comment"`
200-
}
201-
202-
// AcknowledgementCleared represents the Icinga 2 API Event Stream AcknowledgementCleared response for acknowledgements cleared on hosts/services.
203-
//
204-
// NOTE:
205-
// - An empty Service field indicates a host acknowledgement.
206-
// - State might be StateHost{Up,Down} for hosts or StateService{Ok,Warning,Critical,Unknown} for services.
207-
// - StateType might be StateTypeSoft or StateTypeHard.
208-
//
209-
// https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#event-stream-type-acknowledgementcleared
210-
type AcknowledgementCleared struct {
211-
Timestamp UnixFloat `json:"timestamp"`
212-
Host string `json:"host"`
213-
Service string `json:"service"`
214-
State int `json:"state"`
215-
StateType int `json:"state_type"`
208+
EventType string `json:"type"`
216209
}
217210

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

279280
// CheckableCreatedDeleted represents the Icinga 2 API stream Checkable created/deleted response.
@@ -328,10 +329,8 @@ func UnmarshalEventStreamResponse(bytes []byte) (any, error) {
328329
switch responseType {
329330
case typeStateChange:
330331
resp = new(StateChange)
331-
case typeAcknowledgementSet:
332-
resp = new(AcknowledgementSet)
333-
case typeAcknowledgementCleared:
334-
resp = new(AcknowledgementCleared)
332+
case typeAcknowledgementSet, typeAcknowledgementCleared:
333+
resp = new(Acknowledgement)
335334
case typeCommentAdded:
336335
resp = new(CommentAdded)
337336
case typeCommentRemoved:

internal/icinga2/api_responses_test.go

+15-10
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,13 @@ func TestObjectQueriesResult_UnmarshalJSON(t *testing.T) {
180180
Name: "docker-master!load!c27b27c2-e0ab-45ff-8b9b-e95f29851eb0",
181181
Type: "Downtime",
182182
Attrs: Downtime{
183-
Host: "docker-master",
184-
Service: "load",
185-
Author: "icingaadmin",
186-
Comment: "Scheduled downtime for backup",
187-
RemoveTime: UnixFloat(time.UnixMilli(0)),
188-
IsFixed: true,
183+
Host: "docker-master",
184+
Service: "load",
185+
Author: "icingaadmin",
186+
Comment: "Scheduled downtime for backup",
187+
ConfigOwner: "docker-master!load!backup-downtime",
188+
RemoveTime: UnixFloat(time.UnixMilli(0)),
189+
IsFixed: true,
189190
},
190191
},
191192
},
@@ -348,47 +349,51 @@ func TestApiResponseUnmarshal(t *testing.T) {
348349
{
349350
name: "acknowledgementset-host",
350351
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"}`,
351-
expected: &AcknowledgementSet{
352+
expected: &Acknowledgement{
352353
Timestamp: UnixFloat(time.UnixMicro(1697201074579106)),
353354
Host: "dummy-805",
354355
State: StateHostDown,
355356
StateType: StateTypeHard,
356357
Author: "icingaadmin",
357358
Comment: "working on it",
359+
EventType: typeAcknowledgementSet,
358360
},
359361
},
360362
{
361363
name: "acknowledgementset-service",
362364
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"}`,
363-
expected: &AcknowledgementSet{
365+
expected: &Acknowledgement{
364366
Timestamp: UnixFloat(time.UnixMicro(1697201107647920)),
365367
Host: "docker-master",
366368
Service: "ssh",
367369
State: StateServiceCritical,
368370
StateType: StateTypeHard,
369371
Author: "icingaadmin",
370372
Comment: "will be fixed soon",
373+
EventType: typeAcknowledgementSet,
371374
},
372375
},
373376
{
374377
name: "acknowledgementcleared-host",
375378
jsonData: `{"acknowledgement_type":0,"host":"dummy-805","state":1,"state_type":1,"timestamp":1697201082.440148,"type":"AcknowledgementCleared"}`,
376-
expected: &AcknowledgementCleared{
379+
expected: &Acknowledgement{
377380
Timestamp: UnixFloat(time.UnixMicro(1697201082440148)),
378381
Host: "dummy-805",
379382
State: StateHostDown,
380383
StateType: StateTypeHard,
384+
EventType: typeAcknowledgementCleared,
381385
},
382386
},
383387
{
384388
name: "acknowledgementcleared-service",
385389
jsonData: `{"acknowledgement_type":0,"host":"docker-master","service":"ssh","state":2,"state_type":1,"timestamp":1697201110.220349,"type":"AcknowledgementCleared"}`,
386-
expected: &AcknowledgementCleared{
390+
expected: &Acknowledgement{
387391
Timestamp: UnixFloat(time.UnixMicro(1697201110220349)),
388392
Host: "docker-master",
389393
Service: "ssh",
390394
State: StateServiceCritical,
391395
StateType: StateTypeHard,
396+
EventType: typeAcknowledgementCleared,
392397
},
393398
},
394399
{

0 commit comments

Comments
 (0)