Skip to content

Commit bbb5f84

Browse files
authored
feat: configurable event filter (#610)
* feat: watch network connect / disconnect event * refactor: use go-dockerclient builtin event filtering * refactor: make event filter configurable
1 parent 48c3b98 commit bbb5f84

File tree

4 files changed

+44
-28
lines changed

4 files changed

+44
-28
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ Options:
9191
config files with template directives. Config files will be merged if this option is specified multiple times. (default [])
9292
-endpoint string
9393
docker api endpoint (tcp|unix://..). Default unix:///var/run/docker.sock
94+
-event-filter value
95+
additional filter for event watched by docker-gen (e.g -event-filter event=connect -event-filter event=disconnect).
96+
You can pass this option multiple times to combine filters.
97+
By default docker-gen listen for container events start, stop, die and health_status.
98+
https://docs.docker.com/engine/reference/commandline/events/#filtering-events
9499
-interval int
95100
notify command interval (secs)
96101
-keep-blank-lines

cmd/docker-gen/main.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var (
3636
includeStopped bool
3737
configFiles stringslice
3838
configs config.ConfigFile
39+
eventFilter mapstringslice = mapstringslice{"event": {"start", "stop", "die", "health_status"}}
3940
interval int
4041
keepBlankLines bool
4142
endpoint string
@@ -129,6 +130,9 @@ func initFlags() {
129130
flag.StringVar(&tlsCaCert, "tlscacert", filepath.Join(certPath, "ca.pem"), "path to TLS CA certificate file")
130131
flag.BoolVar(&tlsVerify, "tlsverify", os.Getenv("DOCKER_TLS_VERIFY") != "", "verify docker daemon's TLS certicate")
131132

133+
flag.Var(&eventFilter, "event-filter",
134+
"additional filter for event watched by docker-gen (e.g -event-filter event=connect -event-filter event=disconnect). You can pass this option multiple times to combine filters. By default docker-gen listen for container events start, stop, die and health_status. https://docs.docker.com/engine/reference/commandline/events/#filtering-events")
135+
132136
flag.Usage = usage
133137
flag.Parse()
134138
}
@@ -202,13 +206,14 @@ func main() {
202206
}
203207

204208
generator, err := generator.NewGenerator(generator.GeneratorConfig{
205-
Endpoint: endpoint,
206-
TLSKey: tlsKey,
207-
TLSCert: tlsCert,
208-
TLSCACert: tlsCaCert,
209-
TLSVerify: tlsVerify,
210-
All: all,
211-
ConfigFile: configs,
209+
Endpoint: endpoint,
210+
TLSKey: tlsKey,
211+
TLSCert: tlsCert,
212+
TLSCACert: tlsCaCert,
213+
TLSVerify: tlsVerify,
214+
All: all,
215+
EventFilter: eventFilter,
216+
ConfigFile: configs,
212217
})
213218

214219
if err != nil {

internal/generator/generator.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type generator struct {
2626
TLSVerify bool
2727
TLSCert, TLSCaCert, TLSKey string
2828
All bool
29+
EventFilter map[string][]string
2930

3031
wg sync.WaitGroup
3132
retry bool
@@ -40,6 +41,8 @@ type GeneratorConfig struct {
4041
TLSVerify bool
4142
All bool
4243

44+
EventFilter map[string][]string
45+
4346
ConfigFile config.ConfigFile
4447
}
4548

@@ -63,15 +66,16 @@ func NewGenerator(gc GeneratorConfig) (*generator, error) {
6366
context.SetDockerEnv(apiVersion)
6467

6568
return &generator{
66-
Client: client,
67-
Endpoint: gc.Endpoint,
68-
TLSVerify: gc.TLSVerify,
69-
TLSCert: gc.TLSCert,
70-
TLSCaCert: gc.TLSCACert,
71-
TLSKey: gc.TLSKey,
72-
All: gc.All,
73-
Configs: gc.ConfigFile,
74-
retry: true,
69+
Client: client,
70+
Endpoint: gc.Endpoint,
71+
TLSVerify: gc.TLSVerify,
72+
TLSCert: gc.TLSCert,
73+
TLSCaCert: gc.TLSCACert,
74+
TLSKey: gc.TLSKey,
75+
All: gc.All,
76+
EventFilter: gc.EventFilter,
77+
Configs: gc.ConfigFile,
78+
retry: true,
7579
}, nil
7680
}
7781

@@ -249,7 +253,11 @@ func (g *generator) generateFromEvents() {
249253
break
250254
}
251255
if !watching {
252-
err := client.AddEventListener(eventChan)
256+
options := docker.EventsOptions{
257+
Filters: g.EventFilter,
258+
}
259+
260+
err := client.AddEventListenerWithOptions(options, eventChan)
253261
if err != nil && err != docker.ErrListenerAlreadyExists {
254262
log.Printf("Error registering docker event listener: %s", err)
255263
time.Sleep(10 * time.Second)
@@ -281,12 +289,11 @@ func (g *generator) generateFromEvents() {
281289
time.Sleep(10 * time.Second)
282290
break
283291
}
284-
if event.Status == "start" || event.Status == "stop" || event.Status == "die" || strings.Contains(event.Status, "health_status:") {
285-
log.Printf("Received event %s for container %s", event.Status, event.ID[:12])
286-
// fanout event to all watchers
287-
for _, watcher := range watchers {
288-
watcher <- event
289-
}
292+
293+
log.Printf("Received event %s for %s %s", event.Action, event.Type, event.Actor.ID[:12])
294+
// fanout event to all watchers
295+
for _, watcher := range watchers {
296+
watcher <- event
290297
}
291298
case <-time.After(10 * time.Second):
292299
// check for docker liveness

internal/generator/generator_test.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,11 @@ func TestGenerateFromEvents(t *testing.T) {
2626
var counter atomic.Int32
2727

2828
eventsResponse := `
29-
{"status":"start","id":"8dfafdbc3a40","from":"base:latest","time":1374067924}
30-
{"status":"stop","id":"8dfafdbc3a40","from":"base:latest","time":1374067966}
31-
{"status":"start","id":"8dfafdbc3a40","from":"base:latest","time":1374067970}
32-
{"status":"destroy","id":"8dfafdbc3a40","from":"base:latest","time":1374067990}`
29+
{"Type":"container","Action":"start","Actor": {"ID":"8dfafdbc3a40"},"Time":1374067924}
30+
{"Type":"container","Action":"stop","Actor": {"ID":"8dfafdbc3a40"},"Time":1374067966}
31+
{"Type":"container","Action":"start","Actor": {"ID":"8dfafdbc3a40"},"Time":1374067970}`
3332
infoResponse := `{"Containers":1,"Images":1,"Debug":false,"NFd":11,"NGoroutines":21,"MemoryLimit":true,"SwapLimit":false}`
34-
versionResponse := `{"Version":"1.8.0","Os":"Linux","KernelVersion":"3.18.5-tinycore64","GoVersion":"go1.4.1","GitCommit":"a8a31ef","Arch":"amd64","ApiVersion":"1.19"}`
33+
versionResponse := `{"Version":"19.03.12","Os":"Linux","KernelVersion":"4.19.76-linuxkit","GoVersion":"go1.13.14","GitCommit":"48a66213fe","Arch":"amd64","ApiVersion":"1.40"}`
3534

3635
server, _ := dockertest.NewServer("127.0.0.1:0", nil, nil)
3736
server.CustomHandler("/events", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

0 commit comments

Comments
 (0)