| ... | ... |
@@ -992,6 +992,12 @@ You'll need two shells for this example. |
| 992 | 992 |
$ sudo docker events --filter 'container=7805c1d35632' --filter 'event=stop' |
| 993 | 993 |
2014-09-03T15:49:29.999999999Z07:00 7805c1d35632: (from redis:2.8) stop |
| 994 | 994 |
|
| 995 |
+ $ sudo docker events --filter 'container=container_1' --filter 'container=container_2' |
|
| 996 |
+ 2014-09-03T15:49:29.999999999Z07:00 4386fb97867d: (from ubuntu-1:14.04) die |
|
| 997 |
+ 2014-05-10T17:42:14.999999999Z07:00 4386fb97867d: (from ubuntu-1:14.04) stop |
|
| 998 |
+ 2014-05-10T17:42:14.999999999Z07:00 7805c1d35632: (from redis:2.8) die |
|
| 999 |
+ 2014-09-03T15:49:29.999999999Z07:00 7805c1d35632: (from redis:2.8) stop |
|
| 1000 |
+ |
|
| 995 | 1001 |
## exec |
| 996 | 1002 |
|
| 997 | 1003 |
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...] |
| ... | ... |
@@ -1,7 +1,9 @@ |
| 1 | 1 |
package events |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "bytes" |
|
| 4 | 5 |
"encoding/json" |
| 6 |
+ "io" |
|
| 5 | 7 |
"strings" |
| 6 | 8 |
"sync" |
| 7 | 9 |
"time" |
| ... | ... |
@@ -123,7 +125,13 @@ func writeEvent(job *engine.Job, event *utils.JSONMessage, eventFilters filters. |
| 123 | 123 |
return true |
| 124 | 124 |
} |
| 125 | 125 |
|
| 126 |
- if isFiltered(event.Status, eventFilters["event"]) || isFiltered(event.From, eventFilters["image"]) || isFiltered(event.ID, eventFilters["container"]) {
|
|
| 126 |
+ //incoming container filter can be name,id or partial id, convert and replace as a full container id |
|
| 127 |
+ for i, cn := range eventFilters["container"] {
|
|
| 128 |
+ eventFilters["container"][i] = GetContainerId(job.Eng, cn) |
|
| 129 |
+ } |
|
| 130 |
+ |
|
| 131 |
+ if isFiltered(event.Status, eventFilters["event"]) || isFiltered(event.From, eventFilters["image"]) || |
|
| 132 |
+ isFiltered(event.ID, eventFilters["container"]) {
|
|
| 127 | 133 |
return nil |
| 128 | 134 |
} |
| 129 | 135 |
|
| ... | ... |
@@ -203,3 +211,20 @@ func (e *Events) unsubscribe(l listener) bool {
|
| 203 | 203 |
e.mu.Unlock() |
| 204 | 204 |
return false |
| 205 | 205 |
} |
| 206 |
+ |
|
| 207 |
+func GetContainerId(eng *engine.Engine, name string) string {
|
|
| 208 |
+ var buf bytes.Buffer |
|
| 209 |
+ job := eng.Job("container_inspect", name)
|
|
| 210 |
+ |
|
| 211 |
+ var outStream io.Writer |
|
| 212 |
+ |
|
| 213 |
+ outStream = &buf |
|
| 214 |
+ job.Stdout.Set(outStream) |
|
| 215 |
+ |
|
| 216 |
+ if err := job.Run(); err != nil {
|
|
| 217 |
+ return "" |
|
| 218 |
+ } |
|
| 219 |
+ var out struct{ ID string }
|
|
| 220 |
+ json.NewDecoder(&buf).Decode(&out) |
|
| 221 |
+ return out.ID |
|
| 222 |
+} |
| ... | ... |
@@ -258,6 +258,7 @@ func TestEventsFilterImageName(t *testing.T) {
|
| 258 | 258 |
t.Fatal(out, err) |
| 259 | 259 |
} |
| 260 | 260 |
container1 := stripTrailingCharacters(out) |
| 261 |
+ |
|
| 261 | 262 |
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "container_2", "-d", "busybox", "true")) |
| 262 | 263 |
if err != nil {
|
| 263 | 264 |
t.Fatal(out, err) |
| ... | ... |
@@ -290,5 +291,98 @@ func TestEventsFilterImageName(t *testing.T) {
|
| 290 | 290 |
} |
| 291 | 291 |
|
| 292 | 292 |
logDone("events - filters using image")
|
| 293 |
+} |
|
| 294 |
+ |
|
| 295 |
+func TestEventsFilterContainerID(t *testing.T) {
|
|
| 296 |
+ since := time.Now().Unix() |
|
| 297 |
+ defer deleteAllContainers() |
|
| 298 |
+ |
|
| 299 |
+ out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "busybox", "true")) |
|
| 300 |
+ if err != nil {
|
|
| 301 |
+ t.Fatal(out, err) |
|
| 302 |
+ } |
|
| 303 |
+ container1 := stripTrailingCharacters(out) |
|
| 304 |
+ |
|
| 305 |
+ out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "busybox", "true")) |
|
| 306 |
+ if err != nil {
|
|
| 307 |
+ t.Fatal(out, err) |
|
| 308 |
+ } |
|
| 309 |
+ container2 := stripTrailingCharacters(out) |
|
| 310 |
+ |
|
| 311 |
+ for _, s := range []string{container1, container2, container1[:12], container2[:12]} {
|
|
| 312 |
+ eventsCmd := exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", time.Now().Unix()), "--filter", fmt.Sprintf("container=%s", s))
|
|
| 313 |
+ out, _, err := runCommandWithOutput(eventsCmd) |
|
| 314 |
+ if err != nil {
|
|
| 315 |
+ t.Fatalf("Failed to get events, error: %s(%s)", err, out)
|
|
| 316 |
+ } |
|
| 317 |
+ events := strings.Split(out, "\n") |
|
| 318 |
+ events = events[:len(events)-1] |
|
| 319 |
+ if len(events) == 0 || len(events) > 3 {
|
|
| 320 |
+ t.Fatalf("Expected 3 events, got %d: %v", len(events), events)
|
|
| 321 |
+ } |
|
| 322 |
+ createEvent := strings.Fields(events[0]) |
|
| 323 |
+ if createEvent[len(createEvent)-1] != "create" {
|
|
| 324 |
+ t.Fatalf("first event should be create, not %#v", createEvent)
|
|
| 325 |
+ } |
|
| 326 |
+ if len(events) > 1 {
|
|
| 327 |
+ startEvent := strings.Fields(events[1]) |
|
| 328 |
+ if startEvent[len(startEvent)-1] != "start" {
|
|
| 329 |
+ t.Fatalf("second event should be start, not %#v", startEvent)
|
|
| 330 |
+ } |
|
| 331 |
+ } |
|
| 332 |
+ if len(events) == 3 {
|
|
| 333 |
+ dieEvent := strings.Fields(events[len(events)-1]) |
|
| 334 |
+ if dieEvent[len(dieEvent)-1] != "die" {
|
|
| 335 |
+ t.Fatalf("event should be die, not %#v", dieEvent)
|
|
| 336 |
+ } |
|
| 337 |
+ } |
|
| 338 |
+ } |
|
| 339 |
+ |
|
| 340 |
+ logDone("events - filters using container id")
|
|
| 341 |
+} |
|
| 342 |
+ |
|
| 343 |
+func TestEventsFilterContainerName(t *testing.T) {
|
|
| 344 |
+ since := time.Now().Unix() |
|
| 345 |
+ defer deleteAllContainers() |
|
| 346 |
+ |
|
| 347 |
+ _, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "container_1", "busybox", "true")) |
|
| 348 |
+ if err != nil {
|
|
| 349 |
+ t.Fatal(err) |
|
| 350 |
+ } |
|
| 351 |
+ |
|
| 352 |
+ _, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "container_2", "busybox", "true")) |
|
| 353 |
+ if err != nil {
|
|
| 354 |
+ t.Fatal(err) |
|
| 355 |
+ } |
|
| 356 |
+ |
|
| 357 |
+ for _, s := range []string{"container_1", "container_2"} {
|
|
| 358 |
+ eventsCmd := exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", time.Now().Unix()), "--filter", fmt.Sprintf("container=%s", s))
|
|
| 359 |
+ out, _, err := runCommandWithOutput(eventsCmd) |
|
| 360 |
+ if err != nil {
|
|
| 361 |
+ t.Fatalf("Failed to get events, error : %s(%s)", err, out)
|
|
| 362 |
+ } |
|
| 363 |
+ events := strings.Split(out, "\n") |
|
| 364 |
+ events = events[:len(events)-1] |
|
| 365 |
+ if len(events) == 0 || len(events) > 3 {
|
|
| 366 |
+ t.Fatalf("Expected 3 events, got %d: %v", len(events), events)
|
|
| 367 |
+ } |
|
| 368 |
+ createEvent := strings.Fields(events[0]) |
|
| 369 |
+ if createEvent[len(createEvent)-1] != "create" {
|
|
| 370 |
+ t.Fatalf("first event should be create, not %#v", createEvent)
|
|
| 371 |
+ } |
|
| 372 |
+ if len(events) > 1 {
|
|
| 373 |
+ startEvent := strings.Fields(events[1]) |
|
| 374 |
+ if startEvent[len(startEvent)-1] != "start" {
|
|
| 375 |
+ t.Fatalf("second event should be start, not %#v", startEvent)
|
|
| 376 |
+ } |
|
| 377 |
+ } |
|
| 378 |
+ if len(events) == 3 {
|
|
| 379 |
+ dieEvent := strings.Fields(events[len(events)-1]) |
|
| 380 |
+ if dieEvent[len(dieEvent)-1] != "die" {
|
|
| 381 |
+ t.Fatalf("event should be die, not %#v", dieEvent)
|
|
| 382 |
+ } |
|
| 383 |
+ } |
|
| 384 |
+ } |
|
| 293 | 385 |
|
| 386 |
+ logDone("events - filters using container name")
|
|
| 294 | 387 |
} |