Skip to content

Commit e1641d0

Browse files
committed
deadmansswitches: fix bug where alertAcked was signalled on wrong branch
1 parent faf1f7b commit e1641d0

File tree

3 files changed

+122
-6
lines changed

3 files changed

+122
-6
lines changed

cmd/alertmanager/deadmansswitches.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ func deadMansSwitchEntry() *cobra.Command {
6363
ctx,
6464
args[0],
6565
ttl,
66-
app)
66+
app,
67+
time.Now())
6768
exitIfError(err)
6869
},
6970
})
@@ -116,9 +117,8 @@ func deadmansswitchCheckin(
116117
subject string,
117118
ttl time.Time,
118119
app *amstate.App,
120+
now time.Time,
119121
) (bool, error) {
120-
now := time.Now()
121-
122122
alertAcked := false
123123

124124
checkin := amdomain.NewDeadMansSwitchCheckin(
@@ -135,8 +135,6 @@ func deadmansswitchCheckin(
135135
subject,
136136
ttl,
137137
ehevent.MetaSystemUser(now)))
138-
139-
alertAcked = true
140138
}
141139

142140
events = append(events, checkin)
@@ -145,6 +143,8 @@ func deadmansswitchCheckin(
145143
events = append(events, amdomain.NewAlertAcknowledged(
146144
alert.Id,
147145
ehevent.MetaSystemUser(now)))
146+
147+
alertAcked = true
148148
}
149149

150150
return app.AppendAfter(ctx, app.State.Version(), events...)
+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"github.com/function61/eventhorizon/pkg/ehclient"
6+
"github.com/function61/eventhorizon/pkg/ehevent"
7+
"github.com/function61/eventhorizon/pkg/ehreader"
8+
"github.com/function61/eventhorizon/pkg/ehreader/ehreadertest"
9+
"github.com/function61/gokit/assert"
10+
"github.com/function61/lambda-alertmanager/pkg/amdomain"
11+
"github.com/function61/lambda-alertmanager/pkg/amstate"
12+
"strings"
13+
"testing"
14+
"time"
15+
)
16+
17+
func TestDeadmansswitchCheckin(t *testing.T) {
18+
ctx := context.Background()
19+
20+
testStreamName := "/t-42/alertmanager"
21+
22+
eventLog := ehreadertest.NewEventLog()
23+
// not significant (we just need an event in the log for initial read to work)
24+
// TODO: add CreateStream() on the testing log?
25+
eventLog.AppendE(
26+
testStreamName,
27+
amdomain.NewUnnoticedAlertsNotified(
28+
[]string{"dummyid"},
29+
ehevent.MetaSystemUser(t0)))
30+
31+
app, err := amstate.LoadUntilRealtime(
32+
ctx,
33+
ehreader.NewTenantCtxWithSnapshots(
34+
ehreader.TenantId("42"),
35+
eventLog,
36+
ehreader.NewInMemSnapshotStore()),
37+
nil)
38+
assert.Ok(t, err)
39+
40+
alertAcked, err := deadmansswitchCheckin(
41+
ctx,
42+
"My test switch",
43+
t0.Add(1*time.Hour),
44+
app,
45+
t0)
46+
assert.Ok(t, err)
47+
assert.Assert(t, !alertAcked)
48+
49+
dumper := newEventDumper(testStreamName, eventLog, amdomain.Types)
50+
51+
assert.EqualString(t, dumper.Dump(), `
52+
2019-09-07T12:00:00.000Z UnnoticedAlertsNotified {"AlertIds":["dummyid"]}
53+
2019-09-07T12:00:00.000Z DeadMansSwitchCreated {"Subject":"My test switch","Ttl":"2019-09-07T13:00:00Z"}
54+
2019-09-07T12:00:00.000Z DeadMansSwitchCheckin {"Subject":"My test switch","Ttl":"2019-09-07T13:00:00Z"}`)
55+
56+
// 30 minutes lapses, and we send another checkin
57+
58+
alertAcked, err = deadmansswitchCheckin(
59+
ctx,
60+
"My test switch",
61+
t0.Add(90*time.Minute),
62+
app,
63+
t0.Add(30*time.Minute))
64+
assert.Ok(t, err)
65+
assert.Assert(t, !alertAcked)
66+
67+
assert.EqualString(t, dumper.Dump(), `
68+
2019-09-07T12:00:00.000Z UnnoticedAlertsNotified {"AlertIds":["dummyid"]}
69+
2019-09-07T12:00:00.000Z DeadMansSwitchCreated {"Subject":"My test switch","Ttl":"2019-09-07T13:00:00Z"}
70+
2019-09-07T12:00:00.000Z DeadMansSwitchCheckin {"Subject":"My test switch","Ttl":"2019-09-07T13:00:00Z"}
71+
2019-09-07T12:30:00.000Z DeadMansSwitchCheckin {"Subject":"My test switch","Ttl":"2019-09-07T13:30:00Z"}`)
72+
}
73+
74+
func newEventDumper(stream string, eventLog ehclient.Reader, types ehevent.Allocators) *eventDumper {
75+
d := &eventDumper{
76+
cur: ehclient.Beginning(stream),
77+
dump: []string{""}, // to get newline at beginning
78+
types: types,
79+
}
80+
d.reader = ehreader.New(d, eventLog, nil)
81+
return d
82+
}
83+
84+
// For testing, allows you to print your event log
85+
// TODO: move this to eventhorizon testing helper package?
86+
type eventDumper struct {
87+
cur ehclient.Cursor
88+
reader *ehreader.Reader
89+
dump []string
90+
types ehevent.Allocators
91+
}
92+
93+
func (e *eventDumper) Dump() string {
94+
if err := e.reader.LoadUntilRealtime(context.Background()); err != nil {
95+
panic(err)
96+
}
97+
98+
return strings.Join(e.dump, "\n")
99+
}
100+
101+
func (e *eventDumper) GetEventTypes() ehevent.Allocators {
102+
return e.types
103+
}
104+
105+
func (e *eventDumper) ProcessEvents(ctx context.Context, handle ehreader.EventProcessorHandler) error {
106+
return handle(
107+
e.cur,
108+
func(ev ehevent.Event) error {
109+
e.dump = append(e.dump, ehevent.Serialize(ev))
110+
return nil
111+
},
112+
func(commitCursor ehclient.Cursor) error {
113+
e.cur = commitCursor
114+
return nil
115+
})
116+
}

cmd/alertmanager/restapi.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func handleDeadMansSwitchCheckin(
116116
return
117117
}
118118

119-
alertAcked, err := deadmansswitchCheckin(r.Context(), raw.Subject, ttl, app)
119+
alertAcked, err := deadmansswitchCheckin(r.Context(), raw.Subject, ttl, app, time.Now())
120120
if err != nil {
121121
http.Error(w, err.Error(), http.StatusInternalServerError)
122122
return

0 commit comments

Comments
 (0)