-
Notifications
You must be signed in to change notification settings - Fork 0
/
watch.go
80 lines (65 loc) · 1.57 KB
/
watch.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package runrunc
import (
"encoding/json"
"fmt"
"io"
"code.cloudfoundry.org/commandrunner"
"code.cloudfoundry.org/lager"
)
//go:generate counterfeiter . EventsNotifier
type EventsNotifier interface {
OnEvent(handle string, event string) error
}
type OomWatcher struct {
commandRunner commandrunner.CommandRunner
runc RuncBinary
}
func NewOomWatcher(runner commandrunner.CommandRunner, runc RuncBinary) *OomWatcher {
return &OomWatcher{runner, runc}
}
type runcEvent struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
}
func (r *OomWatcher) WatchEvents(log lager.Logger, handle string, eventsNotifier EventsNotifier) error {
stdoutR, w := io.Pipe()
cmd := r.runc.EventsCommand(handle)
cmd.Stdout = w
log = log.Session("watch", lager.Data{
"handle": handle,
})
log.Info("watching")
defer func() {
stdoutR.Close()
log.Info("done")
}()
if err := r.commandRunner.Start(cmd); err != nil {
log.Error("run-events", err)
return fmt.Errorf("start: %s", err)
}
go func() {
defer w.Close()
r.commandRunner.Wait(cmd) // avoid zombie
}()
decoder := json.NewDecoder(stdoutR)
for {
log.Debug("wait-next-event")
var event runcEvent
err := decoder.Decode(&event)
if err == io.EOF {
return nil
}
if err != nil {
return fmt.Errorf("decode event: %s", err)
}
log.Debug("got-event", lager.Data{
"type": event.Type,
})
if event.Type == "oom" {
err := eventsNotifier.OnEvent(handle, "Out of memory")
if err != nil {
log.Debug("failed-to-notify-oom-event", lager.Data{"event": event.Data})
}
}
}
}