From 55053d3537100eaeaad9c83b43e31f22d14fde7b Mon Sep 17 00:00:00 2001 From: David Calavera Date: Mon, 11 Apr 2016 11:52:34 -0700 Subject: [PATCH] Get events until a time in the past. This change allow to filter events that happened in the past without waiting for future events. Example: docker events --since -1h --until -30m Signed-off-by: David Calavera --- api/server/router/system/backend.go | 4 +- api/server/router/system/system_routes.go | 45 ++++- daemon/daemon.go | 14 -- daemon/events.go | 15 ++ daemon/events/events.go | 32 ++-- daemon/events/events_test.go | 89 +++++++++- integration-cli/docker_cli_build_test.go | 5 +- integration-cli/docker_cli_events_test.go | 165 ++++++++++-------- .../docker_cli_events_unix_test.go | 40 +++-- integration-cli/docker_cli_pause_test.go | 5 +- integration-cli/docker_utils.go | 10 ++ integration-cli/events_utils.go | 2 +- 12 files changed, 291 insertions(+), 135 deletions(-) diff --git a/api/server/router/system/backend.go b/api/server/router/system/backend.go index e6284cd4ab..83609ab55a 100644 --- a/api/server/router/system/backend.go +++ b/api/server/router/system/backend.go @@ -1,6 +1,8 @@ package system import ( + "time" + "github.com/docker/engine-api/types" "github.com/docker/engine-api/types/events" "github.com/docker/engine-api/types/filters" @@ -12,7 +14,7 @@ import ( type Backend interface { SystemInfo() (*types.Info, error) SystemVersion() types.Version - SubscribeToEvents(since, sinceNano int64, ef filters.Args) ([]events.Message, chan interface{}) + SubscribeToEvents(since, until time.Time, ef filters.Args) ([]events.Message, chan interface{}) UnsubscribeFromEvents(chan interface{}) AuthenticateToRegistry(ctx context.Context, authConfig *types.AuthConfig) (string, string, error) } diff --git a/api/server/router/system/system_routes.go b/api/server/router/system/system_routes.go index 93ce6fe67b..901d7f606e 100644 --- a/api/server/router/system/system_routes.go +++ b/api/server/router/system/system_routes.go @@ -2,12 +2,14 @@ package system import ( "encoding/json" + "fmt" "net/http" "time" "github.com/Sirupsen/logrus" "github.com/docker/docker/api" "github.com/docker/docker/api/server/httputils" + "github.com/docker/docker/errors" "github.com/docker/docker/pkg/ioutils" "github.com/docker/engine-api/types" "github.com/docker/engine-api/types/events" @@ -46,19 +48,33 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r * if err := httputils.ParseForm(r); err != nil { return err } - since, sinceNano, err := timetypes.ParseTimestamps(r.Form.Get("since"), -1) + + since, err := eventTime(r.Form.Get("since")) if err != nil { return err } - until, untilNano, err := timetypes.ParseTimestamps(r.Form.Get("until"), -1) + until, err := eventTime(r.Form.Get("until")) if err != nil { return err } - var timeout <-chan time.Time - if until > 0 || untilNano > 0 { - dur := time.Unix(until, untilNano).Sub(time.Now()) - timeout = time.NewTimer(dur).C + var ( + timeout <-chan time.Time + onlyPastEvents bool + ) + if !until.IsZero() { + if until.Before(since) { + return errors.NewBadRequestError(fmt.Errorf("`since` time (%s) cannot be after `until` time (%s)", r.Form.Get("since"), r.Form.Get("until"))) + } + + now := time.Now() + + onlyPastEvents = until.Before(now) + + if !onlyPastEvents { + dur := until.Sub(now) + timeout = time.NewTimer(dur).C + } } ef, err := filters.FromParam(r.Form.Get("filters")) @@ -73,7 +89,7 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r * enc := json.NewEncoder(output) - buffered, l := s.backend.SubscribeToEvents(since, sinceNano, ef) + buffered, l := s.backend.SubscribeToEvents(since, until, ef) defer s.backend.UnsubscribeFromEvents(l) for _, ev := range buffered { @@ -82,6 +98,10 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r * } } + if onlyPastEvents { + return nil + } + for { select { case ev := <-l: @@ -118,3 +138,14 @@ func (s *systemRouter) postAuth(ctx context.Context, w http.ResponseWriter, r *h IdentityToken: token, }) } + +func eventTime(formTime string) (time.Time, error) { + t, tNano, err := timetypes.ParseTimestamps(formTime, -1) + if err != nil { + return time.Time{}, err + } + if t == -1 { + return time.Time{}, nil + } + return time.Unix(t, tNano), nil +} diff --git a/daemon/daemon.go b/daemon/daemon.go index af25910a5e..a60fe637f8 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -29,8 +29,6 @@ import ( "github.com/docker/docker/errors" "github.com/docker/engine-api/types" containertypes "github.com/docker/engine-api/types/container" - eventtypes "github.com/docker/engine-api/types/events" - "github.com/docker/engine-api/types/filters" networktypes "github.com/docker/engine-api/types/network" registrytypes "github.com/docker/engine-api/types/registry" "github.com/docker/engine-api/types/strslice" @@ -547,18 +545,6 @@ func (daemon *Daemon) GetByName(name string) (*container.Container, error) { return e, nil } -// SubscribeToEvents returns the currently record of events, a channel to stream new events from, and a function to cancel the stream of events. -func (daemon *Daemon) SubscribeToEvents(since, sinceNano int64, filter filters.Args) ([]eventtypes.Message, chan interface{}) { - ef := events.NewFilter(filter) - return daemon.EventsService.SubscribeTopic(since, sinceNano, ef) -} - -// UnsubscribeFromEvents stops the event subscription for a client by closing the -// channel where the daemon sends events to. -func (daemon *Daemon) UnsubscribeFromEvents(listener chan interface{}) { - daemon.EventsService.Evict(listener) -} - // GetLabels for a container or image id func (daemon *Daemon) GetLabels(id string) map[string]string { // TODO: TestCase diff --git a/daemon/events.go b/daemon/events.go index 0ce0eaf0d9..4b40e2e73b 100644 --- a/daemon/events.go +++ b/daemon/events.go @@ -2,9 +2,12 @@ package daemon import ( "strings" + "time" "github.com/docker/docker/container" + daemonevents "github.com/docker/docker/daemon/events" "github.com/docker/engine-api/types/events" + "github.com/docker/engine-api/types/filters" "github.com/docker/libnetwork" ) @@ -77,6 +80,18 @@ func (daemon *Daemon) LogNetworkEventWithAttributes(nw libnetwork.Network, actio daemon.EventsService.Log(action, events.NetworkEventType, actor) } +// SubscribeToEvents returns the currently record of events, a channel to stream new events from, and a function to cancel the stream of events. +func (daemon *Daemon) SubscribeToEvents(since, until time.Time, filter filters.Args) ([]events.Message, chan interface{}) { + ef := daemonevents.NewFilter(filter) + return daemon.EventsService.SubscribeTopic(since, until, ef) +} + +// UnsubscribeFromEvents stops the event subscription for a client by closing the +// channel where the daemon sends events to. +func (daemon *Daemon) UnsubscribeFromEvents(listener chan interface{}) { + daemon.EventsService.Evict(listener) +} + // copyAttributes guarantees that labels are not mutated by event triggers. func copyAttributes(attributes, labels map[string]string) { if labels == nil { diff --git a/daemon/events/events.go b/daemon/events/events.go index ac1c98cd46..df2181fb09 100644 --- a/daemon/events/events.go +++ b/daemon/events/events.go @@ -48,7 +48,7 @@ func (e *Events) Subscribe() ([]eventtypes.Message, chan interface{}, func()) { // SubscribeTopic adds new listener to events, returns slice of 64 stored // last events, a channel in which you can expect new events (in form // of interface{}, so you need type assertion). -func (e *Events) SubscribeTopic(since, sinceNano int64, ef *Filter) ([]eventtypes.Message, chan interface{}) { +func (e *Events) SubscribeTopic(since, until time.Time, ef *Filter) ([]eventtypes.Message, chan interface{}) { e.mu.Lock() var topic func(m interface{}) bool @@ -56,7 +56,7 @@ func (e *Events) SubscribeTopic(since, sinceNano int64, ef *Filter) ([]eventtype topic = func(m interface{}) bool { return ef.Include(m.(eventtypes.Message)) } } - buffered := e.loadBufferedEvents(since, sinceNano, topic) + buffered := e.loadBufferedEvents(since, until, topic) var ch chan interface{} if topic != nil { @@ -116,24 +116,36 @@ func (e *Events) SubscribersCount() int { } // loadBufferedEvents iterates over the cached events in the buffer -// and returns those that were emitted before a specific date. -// The date is splitted in two values: -// - the `since` argument is a date timestamp without nanoseconds, or -1 to return an empty slice. -// - the `sinceNano` argument is the nanoseconds offset from the timestamp. -// It uses `time.Unix(seconds, nanoseconds)` to generate a valid date with those two first arguments. +// and returns those that were emitted between two specific dates. +// It uses `time.Unix(seconds, nanoseconds)` to generate valid dates with those arguments. // It filters those buffered messages with a topic function if it's not nil, otherwise it adds all messages. -func (e *Events) loadBufferedEvents(since, sinceNano int64, topic func(interface{}) bool) []eventtypes.Message { +func (e *Events) loadBufferedEvents(since, until time.Time, topic func(interface{}) bool) []eventtypes.Message { var buffered []eventtypes.Message - if since == -1 { + if since.IsZero() && until.IsZero() { return buffered } - sinceNanoUnix := time.Unix(since, sinceNano).UnixNano() + var sinceNanoUnix int64 + if !since.IsZero() { + sinceNanoUnix = since.UnixNano() + } + + var untilNanoUnix int64 + if !until.IsZero() { + untilNanoUnix = until.UnixNano() + } + for i := len(e.events) - 1; i >= 0; i-- { ev := e.events[i] + if ev.TimeNano < sinceNanoUnix { break } + + if untilNanoUnix > 0 && ev.TimeNano > untilNanoUnix { + continue + } + if topic == nil || topic(ev) { buffered = append([]eventtypes.Message{ev}, buffered...) } diff --git a/daemon/events/events_test.go b/daemon/events/events_test.go index 5fd577b992..0c8ee6b920 100644 --- a/daemon/events/events_test.go +++ b/daemon/events/events_test.go @@ -165,7 +165,7 @@ func TestLoadBufferedEvents(t *testing.T) { if err != nil { t.Fatal(err) } - since, sinceNano, err := timetypes.ParseTimestamps(f, -1) + s, sNano, err := timetypes.ParseTimestamps(f, -1) if err != nil { t.Fatal(err) } @@ -183,14 +183,93 @@ func TestLoadBufferedEvents(t *testing.T) { t.Fatal(err) } - buffered := []events.Message{*m1, *m2, *m3} - events := &Events{ - events: buffered, + events: []events.Message{*m1, *m2, *m3}, } - out := events.loadBufferedEvents(since, sinceNano, nil) + since := time.Unix(s, sNano) + until := time.Time{} + + out := events.loadBufferedEvents(since, until, nil) if len(out) != 1 { t.Fatalf("expected 1 message, got %d: %v", len(out), out) } } + +func TestLoadBufferedEventsOnlyFromPast(t *testing.T) { + now := time.Now() + f, err := timetypes.GetTimestamp("2016-03-07T17:28:03.090000000+02:00", now) + if err != nil { + t.Fatal(err) + } + s, sNano, err := timetypes.ParseTimestamps(f, 0) + if err != nil { + t.Fatal(err) + } + + f, err = timetypes.GetTimestamp("2016-03-07T17:28:03.100000000+02:00", now) + if err != nil { + t.Fatal(err) + } + u, uNano, err := timetypes.ParseTimestamps(f, 0) + if err != nil { + t.Fatal(err) + } + + m1, err := eventstestutils.Scan("2016-03-07T17:28:03.022433271+02:00 container die 0b863f2a26c18557fc6cdadda007c459f9ec81b874780808138aea78a3595079 (image=ubuntu, name=small_hoover)") + if err != nil { + t.Fatal(err) + } + m2, err := eventstestutils.Scan("2016-03-07T17:28:03.091719377+02:00 network disconnect 19c5ed41acb798f26b751e0035cd7821741ab79e2bbd59a66b5fd8abf954eaa0 (type=bridge, container=0b863f2a26c18557fc6cdadda007c459f9ec81b874780808138aea78a3595079, name=bridge)") + if err != nil { + t.Fatal(err) + } + m3, err := eventstestutils.Scan("2016-03-07T17:28:03.129014751+02:00 container destroy 0b863f2a26c18557fc6cdadda007c459f9ec81b874780808138aea78a3595079 (image=ubuntu, name=small_hoover)") + if err != nil { + t.Fatal(err) + } + + events := &Events{ + events: []events.Message{*m1, *m2, *m3}, + } + + since := time.Unix(s, sNano) + until := time.Unix(u, uNano) + + out := events.loadBufferedEvents(since, until, nil) + if len(out) != 1 { + t.Fatalf("expected 1 message, got %d: %v", len(out), out) + } + + if out[0].Type != "network" { + t.Fatalf("expected network event, got %s", out[0].Type) + } +} + +// #13753 +func TestIngoreBufferedWhenNoTimes(t *testing.T) { + m1, err := eventstestutils.Scan("2016-03-07T17:28:03.022433271+02:00 container die 0b863f2a26c18557fc6cdadda007c459f9ec81b874780808138aea78a3595079 (image=ubuntu, name=small_hoover)") + if err != nil { + t.Fatal(err) + } + m2, err := eventstestutils.Scan("2016-03-07T17:28:03.091719377+02:00 network disconnect 19c5ed41acb798f26b751e0035cd7821741ab79e2bbd59a66b5fd8abf954eaa0 (type=bridge, container=0b863f2a26c18557fc6cdadda007c459f9ec81b874780808138aea78a3595079, name=bridge)") + if err != nil { + t.Fatal(err) + } + m3, err := eventstestutils.Scan("2016-03-07T17:28:03.129014751+02:00 container destroy 0b863f2a26c18557fc6cdadda007c459f9ec81b874780808138aea78a3595079 (image=ubuntu, name=small_hoover)") + if err != nil { + t.Fatal(err) + } + + events := &Events{ + events: []events.Message{*m1, *m2, *m3}, + } + + since := time.Time{} + until := time.Time{} + + out := events.loadBufferedEvents(since, until, nil) + if len(out) != 0 { + t.Fatalf("expected 0 buffered events, got %q", out) + } +} diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index fa0bf46118..137f42f83a 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -6450,7 +6450,7 @@ func (s *DockerSuite) TestBuildNoNamedVolume(c *check.C) { } func (s *DockerSuite) TestBuildTagEvent(c *check.C) { - since := daemonTime(c).Unix() + since := daemonUnixTime(c) dockerFile := `FROM busybox RUN echo events @@ -6458,7 +6458,8 @@ func (s *DockerSuite) TestBuildTagEvent(c *check.C) { _, err := buildImage("test", dockerFile, false) c.Assert(err, check.IsNil) - out, _ := dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", "type=image") + until := daemonUnixTime(c) + out, _ := dockerCmd(c, "events", "--since", since, "--until", until, "--filter", "type=image") events := strings.Split(strings.TrimSpace(out), "\n") actions := eventActionsByIDAndType(c, events, "test:latest", "image") var foundTag bool diff --git a/integration-cli/docker_cli_events_test.go b/integration-cli/docker_cli_events_test.go index 9f0550575b..333a58716d 100644 --- a/integration-cli/docker_cli_events_test.go +++ b/integration-cli/docker_cli_events_test.go @@ -7,7 +7,6 @@ import ( "net/http" "os" "os/exec" - "strconv" "strings" "sync" "time" @@ -50,7 +49,6 @@ func (s *DockerSuite) TestEventsTimestampFormats(c *check.C) { c.Assert(containerEvents[3], checker.Equals, "die", check.Commentf(out)) c.Assert(containerEvents[4], checker.Equals, "destroy", check.Commentf(out)) } - } func (s *DockerSuite) TestEventsUntag(c *check.C) { @@ -77,7 +75,7 @@ func (s *DockerSuite) TestEventsContainerFailStartDie(c *check.C) { _, _, err := dockerCmdWithError("run", "--name", "testeventdie", "busybox", "blerg") c.Assert(err, checker.NotNil, check.Commentf("Container run with command blerg should have failed, but it did not")) - out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c)) events := strings.Split(strings.TrimSpace(out), "\n") nEvents := len(events) @@ -128,17 +126,16 @@ func (s *DockerSuite) TestEventsLimit(c *check.C) { c.Assert(err, checker.IsNil, check.Commentf("%q failed with error", strings.Join(args, " "))) } - out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c)) events := strings.Split(out, "\n") nEvents := len(events) - 1 c.Assert(nEvents, checker.Equals, 64, check.Commentf("events should be limited to 64, but received %d", nEvents)) } func (s *DockerSuite) TestEventsContainerEvents(c *check.C) { - containerID, _ := dockerCmd(c, "run", "--rm", "--name", "container-events-test", "busybox", "true") - containerID = strings.TrimSpace(containerID) + dockerCmd(c, "run", "--rm", "--name", "container-events-test", "busybox", "true") - out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--until", daemonUnixTime(c)) events := strings.Split(out, "\n") events = events[:len(events)-1] @@ -155,11 +152,10 @@ func (s *DockerSuite) TestEventsContainerEvents(c *check.C) { } func (s *DockerSuite) TestEventsContainerEventsAttrSort(c *check.C) { - since := daemonTime(c).Unix() - containerID, _ := dockerCmd(c, "run", "-d", "--name", "container-events-test", "busybox", "true") - containerID = strings.TrimSpace(containerID) + since := daemonUnixTime(c) + dockerCmd(c, "run", "--rm", "--name", "container-events-test", "busybox", "true") - out, _ := dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--filter", "container=container-events-test", "--since", since, "--until", daemonUnixTime(c)) events := strings.Split(out, "\n") nEvents := len(events) @@ -167,9 +163,6 @@ func (s *DockerSuite) TestEventsContainerEventsAttrSort(c *check.C) { matchedEvents := 0 for _, event := range events { matches := eventstestutils.ScanMap(event) - if matches["id"] != containerID { - continue - } if matches["eventType"] == "container" && matches["action"] == "create" { matchedEvents++ c.Assert(out, checker.Contains, "(image=busybox, name=container-events-test)", check.Commentf("Event attributes not sorted")) @@ -178,14 +171,14 @@ func (s *DockerSuite) TestEventsContainerEventsAttrSort(c *check.C) { c.Assert(out, checker.Contains, "(image=busybox, name=container-events-test)", check.Commentf("Event attributes not sorted")) } } - c.Assert(matchedEvents, checker.Equals, 2) + c.Assert(matchedEvents, checker.Equals, 2, check.Commentf("missing events for container container-events-test:\n%s", out)) } func (s *DockerSuite) TestEventsContainerEventsSinceUnixEpoch(c *check.C) { dockerCmd(c, "run", "--rm", "--name", "since-epoch-test", "busybox", "true") timeBeginning := time.Unix(0, 0).Format(time.RFC3339Nano) timeBeginning = strings.Replace(timeBeginning, "Z", ".000000000Z", -1) - out, _ := dockerCmd(c, "events", fmt.Sprintf("--since='%s'", timeBeginning), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--since", timeBeginning, "--until", daemonUnixTime(c)) events := strings.Split(out, "\n") events = events[:len(events)-1] @@ -203,13 +196,12 @@ func (s *DockerSuite) TestEventsContainerEventsSinceUnixEpoch(c *check.C) { func (s *DockerSuite) TestEventsImageTag(c *check.C) { time.Sleep(1 * time.Second) // because API has seconds granularity - since := daemonTime(c).Unix() + since := daemonUnixTime(c) image := "testimageevents:tag" dockerCmd(c, "tag", "busybox", image) out, _ := dockerCmd(c, "events", - fmt.Sprintf("--since=%d", since), - fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + "--since", since, "--until", daemonUnixTime(c)) events := strings.Split(strings.TrimSpace(out), "\n") c.Assert(events, checker.HasLen, 1, check.Commentf("was expecting 1 event. out=%s", out)) @@ -223,14 +215,13 @@ func (s *DockerSuite) TestEventsImageTag(c *check.C) { func (s *DockerSuite) TestEventsImagePull(c *check.C) { // TODO Windows: Enable this test once pull and reliable image names are available testRequires(c, DaemonIsLinux) - since := daemonTime(c).Unix() + since := daemonUnixTime(c) testRequires(c, Network) dockerCmd(c, "pull", "hello-world") out, _ := dockerCmd(c, "events", - fmt.Sprintf("--since=%d", since), - fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + "--since", since, "--until", daemonUnixTime(c)) events := strings.Split(strings.TrimSpace(out), "\n") event := strings.TrimSpace(events[len(events)-1]) @@ -248,7 +239,7 @@ func (s *DockerSuite) TestEventsImageImport(c *check.C) { out, _ := dockerCmd(c, "run", "-d", "busybox", "true") cleanedContainerID := strings.TrimSpace(out) - since := daemonTime(c).Unix() + since := daemonUnixTime(c) out, _, err := runCommandPipelineWithOutput( exec.Command(dockerBinary, "export", cleanedContainerID), exec.Command(dockerBinary, "import", "-"), @@ -256,7 +247,7 @@ func (s *DockerSuite) TestEventsImageImport(c *check.C) { c.Assert(err, checker.IsNil, check.Commentf("import failed with output: %q", out)) imageRef := strings.TrimSpace(out) - out, _ = dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", "event=import") + out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=import") events := strings.Split(strings.TrimSpace(out), "\n") c.Assert(events, checker.HasLen, 1) matches := eventstestutils.ScanMap(events[0]) @@ -265,13 +256,13 @@ func (s *DockerSuite) TestEventsImageImport(c *check.C) { } func (s *DockerSuite) TestEventsFilters(c *check.C) { - since := daemonTime(c).Unix() + since := daemonUnixTime(c) dockerCmd(c, "run", "--rm", "busybox", "true") dockerCmd(c, "run", "--rm", "busybox", "true") - out, _ := dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", "event=die") + out, _ := dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=die") parseEvents(c, out, "die") - out, _ = dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", "event=die", "--filter", "event=start") + out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=die", "--filter", "event=start") parseEvents(c, out, "die|start") // make sure we at least got 2 start events @@ -281,7 +272,7 @@ func (s *DockerSuite) TestEventsFilters(c *check.C) { } func (s *DockerSuite) TestEventsFilterImageName(c *check.C) { - since := daemonTime(c).Unix() + since := daemonUnixTime(c) out, _ := dockerCmd(c, "run", "--name", "container_1", "-d", "busybox:latest", "true") container1 := strings.TrimSpace(out) @@ -290,7 +281,7 @@ func (s *DockerSuite) TestEventsFilterImageName(c *check.C) { container2 := strings.TrimSpace(out) name := "busybox" - out, _ = dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", fmt.Sprintf("image=%s", name)) + out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", fmt.Sprintf("image=%s", name)) events := strings.Split(out, "\n") events = events[:len(events)-1] c.Assert(events, checker.Not(checker.HasLen), 0) //Expected events but found none for the image busybox:latest @@ -310,7 +301,7 @@ func (s *DockerSuite) TestEventsFilterImageName(c *check.C) { } func (s *DockerSuite) TestEventsFilterLabels(c *check.C) { - since := daemonTime(c).Unix() + since := daemonUnixTime(c) label := "io.docker.testing=foo" out, _ := dockerCmd(c, "run", "-d", "-l", label, "busybox:latest", "true") @@ -322,8 +313,8 @@ func (s *DockerSuite) TestEventsFilterLabels(c *check.C) { out, _ = dockerCmd( c, "events", - fmt.Sprintf("--since=%d", since), - fmt.Sprintf("--until=%d", daemonTime(c).Unix()), + "--since", since, + "--until", daemonUnixTime(c), "--filter", fmt.Sprintf("label=%s", label)) events := strings.Split(strings.TrimSpace(out), "\n") @@ -336,7 +327,7 @@ func (s *DockerSuite) TestEventsFilterLabels(c *check.C) { } func (s *DockerSuite) TestEventsFilterImageLabels(c *check.C) { - since := daemonTime(c).Unix() + since := daemonUnixTime(c) name := "labelfiltertest" label := "io.docker.testing=image" @@ -353,8 +344,8 @@ func (s *DockerSuite) TestEventsFilterImageLabels(c *check.C) { out, _ := dockerCmd( c, "events", - fmt.Sprintf("--since=%d", since), - fmt.Sprintf("--until=%d", daemonTime(c).Unix()), + "--since", since, + "--until", daemonUnixTime(c), "--filter", fmt.Sprintf("label=%s", label), "--filter", "type=image") @@ -368,7 +359,7 @@ func (s *DockerSuite) TestEventsFilterImageLabels(c *check.C) { } func (s *DockerSuite) TestEventsFilterContainer(c *check.C) { - since := fmt.Sprintf("%d", daemonTime(c).Unix()) + since := daemonUnixTime(c) nameID := make(map[string]string) for _, name := range []string{"container_1", "container_2"} { @@ -377,7 +368,7 @@ func (s *DockerSuite) TestEventsFilterContainer(c *check.C) { nameID[name] = id } - until := fmt.Sprintf("%d", daemonTime(c).Unix()) + until := daemonUnixTime(c) checkEvents := func(id string, events []string) error { if len(events) != 4 { // create, attach, start, die @@ -408,22 +399,21 @@ func (s *DockerSuite) TestEventsFilterContainer(c *check.C) { func (s *DockerSuite) TestEventsCommit(c *check.C) { // Problematic on Windows as cannot commit a running container testRequires(c, DaemonIsLinux) - since := daemonTime(c).Unix() - out, _ := runSleepingContainer(c, "-d") + out, _ := runSleepingContainer(c) cID := strings.TrimSpace(out) c.Assert(waitRun(cID), checker.IsNil) dockerCmd(c, "commit", "-m", "test", cID) dockerCmd(c, "stop", cID) + c.Assert(waitExited(cID, 5*time.Second), checker.IsNil) - out, _ = dockerCmd(c, "events", "--since=0", "-f", "container="+cID, "--until="+strconv.Itoa(int(since))) + until := daemonUnixTime(c) + out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until="+until) c.Assert(out, checker.Contains, "commit", check.Commentf("Missing 'commit' log event")) } func (s *DockerSuite) TestEventsCopy(c *check.C) { - since := daemonTime(c).Unix() - // Build a test image. id, err := buildImage("cpimg", ` FROM busybox @@ -441,18 +431,18 @@ func (s *DockerSuite) TestEventsCopy(c *check.C) { dockerCmd(c, "cp", "cptest:/file", tempFile.Name()) - out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=cptest", "--until="+strconv.Itoa(int(since))) + until := daemonUnixTime(c) + out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=cptest", "--until="+until) c.Assert(out, checker.Contains, "archive-path", check.Commentf("Missing 'archive-path' log event\n")) dockerCmd(c, "cp", tempFile.Name(), "cptest:/filecopy") - out, _ = dockerCmd(c, "events", "--since=0", "-f", "container=cptest", "--until="+strconv.Itoa(int(since))) + until = daemonUnixTime(c) + out, _ = dockerCmd(c, "events", "-f", "container=cptest", "--until="+until) c.Assert(out, checker.Contains, "extract-to-dir", check.Commentf("Missing 'extract-to-dir' log event")) } func (s *DockerSuite) TestEventsResize(c *check.C) { - since := daemonTime(c).Unix() - out, _ := runSleepingContainer(c, "-d") cID := strings.TrimSpace(out) c.Assert(waitRun(cID), checker.IsNil) @@ -464,17 +454,18 @@ func (s *DockerSuite) TestEventsResize(c *check.C) { dockerCmd(c, "stop", cID) - out, _ = dockerCmd(c, "events", "--since=0", "-f", "container="+cID, "--until="+strconv.Itoa(int(since))) + until := daemonUnixTime(c) + out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until="+until) c.Assert(out, checker.Contains, "resize", check.Commentf("Missing 'resize' log event")) } func (s *DockerSuite) TestEventsAttach(c *check.C) { // TODO Windows CI: Figure out why this test fails intermittently (TP4 and TP5). testRequires(c, DaemonIsLinux) - since := daemonTime(c).Unix() out, _ := dockerCmd(c, "run", "-di", "busybox", "cat") cID := strings.TrimSpace(out) + c.Assert(waitRun(cID), checker.IsNil) cmd := exec.Command(dockerBinary, "attach", cID) stdin, err := cmd.StdinPipe() @@ -496,25 +487,27 @@ func (s *DockerSuite) TestEventsAttach(c *check.C) { c.Assert(stdin.Close(), checker.IsNil) dockerCmd(c, "kill", cID) + c.Assert(waitExited(cID, 5*time.Second), checker.IsNil) - out, _ = dockerCmd(c, "events", "--since=0", "-f", "container="+cID, "--until="+strconv.Itoa(int(since))) + until := daemonUnixTime(c) + out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until="+until) c.Assert(out, checker.Contains, "attach", check.Commentf("Missing 'attach' log event")) } func (s *DockerSuite) TestEventsRename(c *check.C) { - since := daemonTime(c).Unix() - - dockerCmd(c, "run", "--name", "oldName", "busybox", "true") + out, _ := dockerCmd(c, "run", "--name", "oldName", "busybox", "true") + cID := strings.TrimSpace(out) dockerCmd(c, "rename", "oldName", "newName") - out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=newName", "--until="+strconv.Itoa(int(since))) + until := daemonUnixTime(c) + // filter by the container id because the name in the event will be the new name. + out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until", until) c.Assert(out, checker.Contains, "rename", check.Commentf("Missing 'rename' log event\n")) } func (s *DockerSuite) TestEventsTop(c *check.C) { // Problematic on Windows as Windows does not support top testRequires(c, DaemonIsLinux) - since := daemonTime(c).Unix() out, _ := runSleepingContainer(c, "-d") cID := strings.TrimSpace(out) @@ -523,24 +516,17 @@ func (s *DockerSuite) TestEventsTop(c *check.C) { dockerCmd(c, "top", cID) dockerCmd(c, "stop", cID) - out, _ = dockerCmd(c, "events", "--since=0", "-f", "container="+cID, "--until="+strconv.Itoa(int(since))) + until := daemonUnixTime(c) + out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until="+until) c.Assert(out, checker.Contains, " top", check.Commentf("Missing 'top' log event")) } -// #13753 -func (s *DockerSuite) TestEventsDefaultEmpty(c *check.C) { - dockerCmd(c, "run", "busybox") - out, _ := dockerCmd(c, "events", fmt.Sprintf("--until=%d", daemonTime(c).Unix())) - c.Assert(strings.TrimSpace(out), checker.Equals, "") -} - // #14316 func (s *DockerRegistrySuite) TestEventsImageFilterPush(c *check.C) { // Problematic to port for Windows CI during TP4/TP5 timeframe while // not supporting push testRequires(c, DaemonIsLinux) testRequires(c, Network) - since := daemonTime(c).Unix() repoName := fmt.Sprintf("%v/dockercli/testf", privateRegistryURL) out, _ := dockerCmd(c, "run", "-d", "busybox", "top") @@ -551,12 +537,13 @@ func (s *DockerRegistrySuite) TestEventsImageFilterPush(c *check.C) { dockerCmd(c, "stop", cID) dockerCmd(c, "push", repoName) - out, _ = dockerCmd(c, "events", "--since=0", "-f", "image="+repoName, "-f", "event=push", "--until="+strconv.Itoa(int(since))) + until := daemonUnixTime(c) + out, _ = dockerCmd(c, "events", "-f", "image="+repoName, "-f", "event=push", "--until", until) c.Assert(out, checker.Contains, repoName, check.Commentf("Missing 'push' log event for %s", repoName)) } func (s *DockerSuite) TestEventsFilterType(c *check.C) { - since := daemonTime(c).Unix() + since := daemonUnixTime(c) name := "labelfiltertest" label := "io.docker.testing=image" @@ -573,8 +560,8 @@ func (s *DockerSuite) TestEventsFilterType(c *check.C) { out, _ := dockerCmd( c, "events", - fmt.Sprintf("--since=%d", since), - fmt.Sprintf("--until=%d", daemonTime(c).Unix()), + "--since", since, + "--until", daemonUnixTime(c), "--filter", fmt.Sprintf("label=%s", label), "--filter", "type=image") @@ -589,8 +576,8 @@ func (s *DockerSuite) TestEventsFilterType(c *check.C) { out, _ = dockerCmd( c, "events", - fmt.Sprintf("--since=%d", since), - fmt.Sprintf("--until=%d", daemonTime(c).Unix()), + "--since", since, + "--until", daemonUnixTime(c), "--filter", fmt.Sprintf("label=%s", label), "--filter", "type=container") events = strings.Split(strings.TrimSpace(out), "\n") @@ -601,19 +588,19 @@ func (s *DockerSuite) TestEventsFilterType(c *check.C) { out, _ = dockerCmd( c, "events", - fmt.Sprintf("--since=%d", since), - fmt.Sprintf("--until=%d", daemonTime(c).Unix()), + "--since", since, + "--until", daemonUnixTime(c), "--filter", "type=network") events = strings.Split(strings.TrimSpace(out), "\n") c.Assert(len(events), checker.GreaterOrEqualThan, 1, check.Commentf("Events == %s", events)) } func (s *DockerSuite) TestEventsFilterImageInContainerAction(c *check.C) { - since := daemonTime(c).Unix() + since := daemonUnixTime(c) dockerCmd(c, "run", "--name", "test-container", "-d", "busybox", "true") waitRun("test-container") - out, _ := dockerCmd(c, "events", "--filter", "image=busybox", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--filter", "image=busybox", "--since", since, "--until", daemonUnixTime(c)) events := strings.Split(strings.TrimSpace(out), "\n") c.Assert(len(events), checker.GreaterThan, 1, check.Commentf(out)) } @@ -636,7 +623,7 @@ func (s *DockerSuite) TestEventsContainerRestart(c *check.C) { startCount int dieCount int ) - out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "-f", "container=testEvent") + out, _ := dockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c), "-f", "container=testEvent") events := strings.Split(strings.TrimSpace(out), "\n") nEvents := len(events) @@ -656,5 +643,33 @@ func (s *DockerSuite) TestEventsContainerRestart(c *check.C) { c.Assert(createCount, checker.Equals, 1, check.Commentf("testEvent should be created 1 times: %v", actions)) c.Assert(startCount, checker.Equals, 4, check.Commentf("testEvent should start 4 times: %v", actions)) c.Assert(dieCount, checker.Equals, 4, check.Commentf("testEvent should die 4 times: %v", actions)) - +} + +func (s *DockerSuite) TestEventsSinceInTheFuture(c *check.C) { + dockerCmd(c, "run", "--name", "test-container", "-d", "busybox", "true") + waitRun("test-container") + + since := daemonTime(c) + until := since.Add(time.Duration(-24) * time.Hour) + out, _, err := dockerCmdWithError("events", "--filter", "image=busybox", "--since", parseEventTime(since), "--until", parseEventTime(until)) + + c.Assert(err, checker.NotNil) + c.Assert(out, checker.Contains, "cannot be after `until`") +} + +func (s *DockerSuite) TestEventsUntilInThePast(c *check.C) { + since := daemonUnixTime(c) + + dockerCmd(c, "run", "--name", "test-container", "-d", "busybox", "true") + waitRun("test-container") + + until := daemonUnixTime(c) + + dockerCmd(c, "run", "--name", "test-container2", "-d", "busybox", "true") + waitRun("test-container2") + + out, _ := dockerCmd(c, "events", "--filter", "image=busybox", "--since", since, "--until", until) + + c.Assert(out, checker.Not(checker.Contains), "test-container2") + c.Assert(out, checker.Contains, "test-container") } diff --git a/integration-cli/docker_cli_events_unix_test.go b/integration-cli/docker_cli_events_unix_test.go index c5e48f2197..8ba67f1f67 100644 --- a/integration-cli/docker_cli_events_unix_test.go +++ b/integration-cli/docker_cli_events_unix_test.go @@ -19,14 +19,14 @@ import ( // #5979 func (s *DockerSuite) TestEventsRedirectStdout(c *check.C) { - since := daemonTime(c).Unix() + since := daemonUnixTime(c) dockerCmd(c, "run", "busybox", "true") file, err := ioutil.TempFile("", "") c.Assert(err, checker.IsNil, check.Commentf("could not create temp file")) defer os.Remove(file.Name()) - command := fmt.Sprintf("%s events --since=%d --until=%d > %s", dockerBinary, since, daemonTime(c).Unix(), file.Name()) + command := fmt.Sprintf("%s events --since=%s --until=%s > %s", dockerBinary, since, daemonUnixTime(c), file.Name()) _, tty, err := pty.Open() c.Assert(err, checker.IsNil, check.Commentf("Could not open pty")) cmd := exec.Command("sh", "-c", command) @@ -63,7 +63,7 @@ func (s *DockerSuite) TestEventsOOMDisableFalse(c *check.C) { c.Fatal("Timeout waiting for container to die on OOM") } - out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=oomFalse", fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=oomFalse", "--until", daemonUnixTime(c)) events := strings.Split(strings.TrimSuffix(out, "\n"), "\n") nEvents := len(events) @@ -131,7 +131,7 @@ func (s *DockerSuite) TestEventsContainerFilterByName(c *check.C) { cOut, _ = dockerCmd(c, "run", "--name=bar", "-d", "busybox", "top") c2 := strings.TrimSpace(cOut) waitRun("bar") - out, _ := dockerCmd(c, "events", "-f", "container=foo", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "-f", "container=foo", "--since=0", "--until", daemonUnixTime(c)) c.Assert(out, checker.Contains, c1, check.Commentf(out)) c.Assert(out, checker.Not(checker.Contains), c2, check.Commentf(out)) } @@ -147,15 +147,19 @@ func (s *DockerSuite) TestEventsContainerFilterBeforeCreate(c *check.C) { // calculate the time it takes to create and start a container and sleep 2 seconds // this is to make sure the docker event will recevie the event of container - since := daemonTime(c).Unix() + since := daemonTime(c) id, _ := dockerCmd(c, "run", "-d", "busybox", "top") cID := strings.TrimSpace(id) waitRun(cID) time.Sleep(2 * time.Second) - duration := daemonTime(c).Unix() - since + duration := daemonTime(c).Sub(since) go func() { - out, _ = dockerCmd(c, "events", "-f", "container=foo", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()+2*duration)) + // start events and wait for future events to + // make sure the new container shows up even when + // the event stream was created before the container. + t := daemonTime(c).Add(2 * duration) + out, _ = dockerCmd(c, "events", "-f", "container=foo", "--since=0", "--until", parseEventTime(t)) close(ch) }() // Sleep 2 second to wait docker event to start @@ -170,7 +174,7 @@ func (s *DockerSuite) TestEventsContainerFilterBeforeCreate(c *check.C) { func (s *DockerSuite) TestVolumeEvents(c *check.C) { testRequires(c, DaemonIsLinux) - since := daemonTime(c).Unix() + since := daemonUnixTime(c) // Observe create/mount volume actions dockerCmd(c, "volume", "create", "--name", "test-event-volume-local") @@ -181,7 +185,8 @@ func (s *DockerSuite) TestVolumeEvents(c *check.C) { dockerCmd(c, "rm", "-f", "test-volume-container") dockerCmd(c, "volume", "rm", "test-event-volume-local") - out, _ := dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + until := daemonUnixTime(c) + out, _ := dockerCmd(c, "events", "--since", since, "--until", until) events := strings.Split(strings.TrimSpace(out), "\n") c.Assert(len(events), checker.GreaterThan, 4) @@ -196,7 +201,7 @@ func (s *DockerSuite) TestVolumeEvents(c *check.C) { func (s *DockerSuite) TestNetworkEvents(c *check.C) { testRequires(c, DaemonIsLinux) - since := daemonTime(c).Unix() + since := daemonUnixTime(c) // Observe create/connect network actions dockerCmd(c, "network", "create", "test-event-network-local") @@ -207,7 +212,8 @@ func (s *DockerSuite) TestNetworkEvents(c *check.C) { dockerCmd(c, "rm", "-f", "test-network-container") dockerCmd(c, "network", "rm", "test-event-network-local") - out, _ := dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + until := daemonUnixTime(c) + out, _ := dockerCmd(c, "events", "--since", since, "--until", until) events := strings.Split(strings.TrimSpace(out), "\n") c.Assert(len(events), checker.GreaterThan, 4) @@ -317,12 +323,12 @@ func (s *DockerSuite) TestEventsImageUntagDelete(c *check.C) { func (s *DockerSuite) TestEventsFilterVolumeAndNetworkType(c *check.C) { testRequires(c, DaemonIsLinux) - since := daemonTime(c).Unix() + since := daemonUnixTime(c) dockerCmd(c, "network", "create", "test-event-network-type") dockerCmd(c, "volume", "create", "--name", "test-event-volume-type") - out, _ := dockerCmd(c, "events", "--filter", "type=volume", "--filter", "type=network", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--filter", "type=volume", "--filter", "type=network", "--since", since, "--until", daemonUnixTime(c)) events := strings.Split(strings.TrimSpace(out), "\n") c.Assert(len(events), checker.GreaterOrEqualThan, 2, check.Commentf(out)) @@ -336,10 +342,10 @@ func (s *DockerSuite) TestEventsFilterVolumeAndNetworkType(c *check.C) { func (s *DockerSuite) TestEventsFilterVolumeID(c *check.C) { testRequires(c, DaemonIsLinux) - since := daemonTime(c).Unix() + since := daemonUnixTime(c) dockerCmd(c, "volume", "create", "--name", "test-event-volume-id") - out, _ := dockerCmd(c, "events", "--filter", "volume=test-event-volume-id", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--filter", "volume=test-event-volume-id", "--since", since, "--until", daemonUnixTime(c)) events := strings.Split(strings.TrimSpace(out), "\n") c.Assert(events, checker.HasLen, 1) @@ -350,10 +356,10 @@ func (s *DockerSuite) TestEventsFilterVolumeID(c *check.C) { func (s *DockerSuite) TestEventsFilterNetworkID(c *check.C) { testRequires(c, DaemonIsLinux) - since := daemonTime(c).Unix() + since := daemonUnixTime(c) dockerCmd(c, "network", "create", "test-event-network-local") - out, _ := dockerCmd(c, "events", "--filter", "network=test-event-network-local", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--filter", "network=test-event-network-local", "--since", since, "--until", daemonUnixTime(c)) events := strings.Split(strings.TrimSpace(out), "\n") c.Assert(events, checker.HasLen, 1) diff --git a/integration-cli/docker_cli_pause_test.go b/integration-cli/docker_cli_pause_test.go index a42c2f54b6..e546ad45d5 100644 --- a/integration-cli/docker_cli_pause_test.go +++ b/integration-cli/docker_cli_pause_test.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "strings" "github.com/docker/docker/pkg/integration/checker" @@ -22,7 +21,7 @@ func (s *DockerSuite) TestPause(c *check.C) { dockerCmd(c, "unpause", name) - out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c)) events := strings.Split(strings.TrimSpace(out), "\n") actions := eventActionsByIDAndType(c, events, name, "container") @@ -48,7 +47,7 @@ func (s *DockerSuite) TestPauseMultipleContainers(c *check.C) { dockerCmd(c, append([]string{"unpause"}, containers...)...) - out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix())) + out, _ := dockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c)) events := strings.Split(strings.TrimSpace(out), "\n") for _, name := range containers { diff --git a/integration-cli/docker_utils.go b/integration-cli/docker_utils.go index a994c79785..38385d4df8 100644 --- a/integration-cli/docker_utils.go +++ b/integration-cli/docker_utils.go @@ -1246,6 +1246,16 @@ func daemonTime(c *check.C) time.Time { return dt } +// daemonUnixTime returns the current time on the daemon host with nanoseconds precission. +// It return the time formatted how the client sends timestamps to the server. +func daemonUnixTime(c *check.C) string { + return parseEventTime(daemonTime(c)) +} + +func parseEventTime(t time.Time) string { + return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())) +} + func setupRegistry(c *check.C, schema1 bool, auth, tokenURL string) *testRegistryV2 { reg, err := newTestRegistryV2(c, schema1, auth, tokenURL) c.Assert(err, check.IsNil) diff --git a/integration-cli/events_utils.go b/integration-cli/events_utils.go index cdd3106b8d..8aa139c03f 100644 --- a/integration-cli/events_utils.go +++ b/integration-cli/events_utils.go @@ -98,7 +98,7 @@ func (e *eventObserver) CheckEventError(c *check.C, id, event string, match even scannerOut := e.buffer.String() if e.disconnectionError != nil { - until := strconv.FormatInt(daemonTime(c).Unix(), 10) + until := daemonUnixTime(c) out, _ := dockerCmd(c, "events", "--since", e.startTime, "--until", until) events := strings.Split(strings.TrimSpace(out), "\n") for _, e := range events {