diff --git a/docs/sources/reference/commandline/cli.md b/docs/sources/reference/commandline/cli.md index 8ffaa5adc3..0626fe6fb6 100644 --- a/docs/sources/reference/commandline/cli.md +++ b/docs/sources/reference/commandline/cli.md @@ -988,6 +988,12 @@ You'll need two shells for this example. $ sudo docker events --filter 'container=7805c1d35632' --filter 'event=stop' 2014-09-03T15:49:29.999999999Z07:00 7805c1d35632: (from redis:2.8) stop + $ sudo docker events --filter 'container=container_1' --filter 'container=container_2' + 2014-09-03T15:49:29.999999999Z07:00 4386fb97867d: (from ubuntu-1:14.04) die + 2014-05-10T17:42:14.999999999Z07:00 4386fb97867d: (from ubuntu-1:14.04) stop + 2014-05-10T17:42:14.999999999Z07:00 7805c1d35632: (from redis:2.8) die + 2014-09-03T15:49:29.999999999Z07:00 7805c1d35632: (from redis:2.8) stop + ## exec Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...] diff --git a/events/events.go b/events/events.go index 91babd1356..559bf687e7 100644 --- a/events/events.go +++ b/events/events.go @@ -1,7 +1,9 @@ package events import ( + "bytes" "encoding/json" + "io" "strings" "sync" "time" @@ -123,7 +125,13 @@ func writeEvent(job *engine.Job, event *utils.JSONMessage, eventFilters filters. return true } - if isFiltered(event.Status, eventFilters["event"]) || isFiltered(event.From, eventFilters["image"]) || isFiltered(event.ID, eventFilters["container"]) { + //incoming container filter can be name,id or partial id, convert and replace as a full container id + for i, cn := range eventFilters["container"] { + eventFilters["container"][i] = GetContainerId(job.Eng, cn) + } + + if isFiltered(event.Status, eventFilters["event"]) || isFiltered(event.From, eventFilters["image"]) || + isFiltered(event.ID, eventFilters["container"]) { return nil } @@ -203,3 +211,20 @@ func (e *Events) unsubscribe(l listener) bool { e.mu.Unlock() return false } + +func GetContainerId(eng *engine.Engine, name string) string { + var buf bytes.Buffer + job := eng.Job("container_inspect", name) + + var outStream io.Writer + + outStream = &buf + job.Stdout.Set(outStream) + + if err := job.Run(); err != nil { + return "" + } + var out struct{ ID string } + json.NewDecoder(&buf).Decode(&out) + return out.ID +} diff --git a/integration-cli/docker_cli_events_test.go b/integration-cli/docker_cli_events_test.go index a9baeb8e01..25efcbe6c7 100644 --- a/integration-cli/docker_cli_events_test.go +++ b/integration-cli/docker_cli_events_test.go @@ -258,6 +258,7 @@ func TestEventsFilterImageName(t *testing.T) { t.Fatal(out, err) } container1 := stripTrailingCharacters(out) + out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "container_2", "-d", "busybox", "true")) if err != nil { t.Fatal(out, err) @@ -290,5 +291,98 @@ func TestEventsFilterImageName(t *testing.T) { } logDone("events - filters using image") - +} + +func TestEventsFilterContainerID(t *testing.T) { + since := time.Now().Unix() + defer deleteAllContainers() + + out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "busybox", "true")) + if err != nil { + t.Fatal(out, err) + } + container1 := stripTrailingCharacters(out) + + out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "busybox", "true")) + if err != nil { + t.Fatal(out, err) + } + container2 := stripTrailingCharacters(out) + + for _, s := range []string{container1, container2, container1[:12], container2[:12]} { + eventsCmd := exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", time.Now().Unix()), "--filter", fmt.Sprintf("container=%s", s)) + out, _, err := runCommandWithOutput(eventsCmd) + if err != nil { + t.Fatalf("Failed to get events, error: %s(%s)", err, out) + } + events := strings.Split(out, "\n") + events = events[:len(events)-1] + if len(events) == 0 || len(events) > 3 { + t.Fatalf("Expected 3 events, got %d: %v", len(events), events) + } + createEvent := strings.Fields(events[0]) + if createEvent[len(createEvent)-1] != "create" { + t.Fatalf("first event should be create, not %#v", createEvent) + } + if len(events) > 1 { + startEvent := strings.Fields(events[1]) + if startEvent[len(startEvent)-1] != "start" { + t.Fatalf("second event should be start, not %#v", startEvent) + } + } + if len(events) == 3 { + dieEvent := strings.Fields(events[len(events)-1]) + if dieEvent[len(dieEvent)-1] != "die" { + t.Fatalf("event should be die, not %#v", dieEvent) + } + } + } + + logDone("events - filters using container id") +} + +func TestEventsFilterContainerName(t *testing.T) { + since := time.Now().Unix() + defer deleteAllContainers() + + _, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "container_1", "busybox", "true")) + if err != nil { + t.Fatal(err) + } + + _, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "container_2", "busybox", "true")) + if err != nil { + t.Fatal(err) + } + + for _, s := range []string{"container_1", "container_2"} { + eventsCmd := exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", time.Now().Unix()), "--filter", fmt.Sprintf("container=%s", s)) + out, _, err := runCommandWithOutput(eventsCmd) + if err != nil { + t.Fatalf("Failed to get events, error : %s(%s)", err, out) + } + events := strings.Split(out, "\n") + events = events[:len(events)-1] + if len(events) == 0 || len(events) > 3 { + t.Fatalf("Expected 3 events, got %d: %v", len(events), events) + } + createEvent := strings.Fields(events[0]) + if createEvent[len(createEvent)-1] != "create" { + t.Fatalf("first event should be create, not %#v", createEvent) + } + if len(events) > 1 { + startEvent := strings.Fields(events[1]) + if startEvent[len(startEvent)-1] != "start" { + t.Fatalf("second event should be start, not %#v", startEvent) + } + } + if len(events) == 3 { + dieEvent := strings.Fields(events[len(events)-1]) + if dieEvent[len(dieEvent)-1] != "die" { + t.Fatalf("event should be die, not %#v", dieEvent) + } + } + } + + logDone("events - filters using container name") }