Add event types.

- Stop serializing JSONMessage in favor of events.Message.
- Keep backwards compatibility with JSONMessage for container events.

Signed-off-by: David Calavera <david.calavera@gmail.com>
Upstream-commit: 72f1881df102fce9ad31e98045b91c204dd44513
Component: engine
This commit is contained in:
David Calavera
2015-12-21 17:55:23 -05:00
parent 75ad76df88
commit 3580481051
23 changed files with 665 additions and 317 deletions

View File

@ -7,7 +7,6 @@ import (
"net/http"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
"sync"
@ -67,7 +66,6 @@ func (s *DockerSuite) TestEventsUntag(c *check.C) {
}
func (s *DockerSuite) TestEventsContainerFailStartDie(c *check.C) {
out, _ := dockerCmd(c, "images", "-q")
image := strings.Split(out, "\n")[0]
_, _, err := dockerCmdWithError("run", "--name", "testeventdie", image, "blerg")
@ -75,14 +73,12 @@ func (s *DockerSuite) TestEventsContainerFailStartDie(c *check.C) {
out, _ = dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
events := strings.Split(out, "\n")
c.Assert(len(events), checker.GreaterThan, 1) //Missing expected event
startEvent := strings.Fields(events[len(events)-3])
dieEvent := strings.Fields(events[len(events)-2])
c.Assert(startEvent[len(startEvent)-1], checker.Equals, "start", check.Commentf("event should be start, not %#v", startEvent))
c.Assert(dieEvent[len(dieEvent)-1], checker.Equals, "die", check.Commentf("event should be die, not %#v", dieEvent))
nEvents := len(events)
c.Assert(nEvents, checker.GreaterOrEqualThan, 1) //Missing expected event
c.Assert(parseEventAction(c, events[nEvents-3]), checker.Equals, "start")
c.Assert(parseEventAction(c, events[nEvents-2]), checker.Equals, "die")
}
func (s *DockerSuite) TestEventsLimit(c *check.C) {
@ -114,65 +110,83 @@ func (s *DockerSuite) TestEventsLimit(c *check.C) {
func (s *DockerSuite) TestEventsContainerEvents(c *check.C) {
testRequires(c, DaemonIsLinux)
dockerCmd(c, "run", "--rm", "busybox", "true")
containerID, _ := dockerCmd(c, "run", "--rm", "--name", "container-events-test", "busybox", "true")
containerID = strings.TrimSpace(containerID)
out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
events := strings.Split(out, "\n")
events = events[:len(events)-1]
c.Assert(len(events), checker.GreaterOrEqualThan, 5) //Missing expected event
createEvent := strings.Fields(events[len(events)-5])
attachEvent := strings.Fields(events[len(events)-4])
startEvent := strings.Fields(events[len(events)-3])
dieEvent := strings.Fields(events[len(events)-2])
destroyEvent := strings.Fields(events[len(events)-1])
c.Assert(createEvent[len(createEvent)-1], checker.Equals, "create", check.Commentf("event should be create, not %#v", createEvent))
c.Assert(attachEvent[len(attachEvent)-1], checker.Equals, "attach", check.Commentf("event should be attach, not %#v", attachEvent))
c.Assert(startEvent[len(startEvent)-1], checker.Equals, "start", check.Commentf("event should be start, not %#v", startEvent))
c.Assert(dieEvent[len(dieEvent)-1], checker.Equals, "die", check.Commentf("event should be die, not %#v", dieEvent))
c.Assert(destroyEvent[len(destroyEvent)-1], checker.Equals, "destroy", check.Commentf("event should be destroy, not %#v", destroyEvent))
nEvents := len(events)
c.Assert(nEvents, checker.GreaterOrEqualThan, 5) //Missing expected event
containerEvents := eventActionsByIDAndType(c, events, "container-events-test", "container")
c.Assert(containerEvents, checker.HasLen, 5, check.Commentf("events: %v", events))
c.Assert(containerEvents[0], checker.Equals, "create", check.Commentf(out))
c.Assert(containerEvents[1], checker.Equals, "attach", check.Commentf(out))
c.Assert(containerEvents[2], checker.Equals, "start", check.Commentf(out))
c.Assert(containerEvents[3], checker.Equals, "die", check.Commentf(out))
c.Assert(containerEvents[4], checker.Equals, "destroy", check.Commentf(out))
}
func (s *DockerSuite) TestEventsContainerEventsSinceUnixEpoch(c *check.C) {
testRequires(c, DaemonIsLinux)
dockerCmd(c, "run", "--rm", "busybox", "true")
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", fmt.Sprintf("--since='%s'", timeBeginning), fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
events := strings.Split(out, "\n")
events = events[:len(events)-1]
c.Assert(len(events), checker.GreaterOrEqualThan, 5) //Missing expected event
createEvent := strings.Fields(events[len(events)-5])
attachEvent := strings.Fields(events[len(events)-4])
startEvent := strings.Fields(events[len(events)-3])
dieEvent := strings.Fields(events[len(events)-2])
destroyEvent := strings.Fields(events[len(events)-1])
c.Assert(createEvent[len(createEvent)-1], checker.Equals, "create", check.Commentf("event should be create, not %#v", createEvent))
c.Assert(attachEvent[len(attachEvent)-1], checker.Equals, "attach", check.Commentf("event should be attach, not %#v", attachEvent))
c.Assert(startEvent[len(startEvent)-1], checker.Equals, "start", check.Commentf("event should be start, not %#v", startEvent))
c.Assert(dieEvent[len(dieEvent)-1], checker.Equals, "die", check.Commentf("event should be die, not %#v", dieEvent))
c.Assert(destroyEvent[len(destroyEvent)-1], checker.Equals, "destroy", check.Commentf("event should be destroy, not %#v", destroyEvent))
nEvents := len(events)
c.Assert(nEvents, checker.GreaterOrEqualThan, 5) //Missing expected event
containerEvents := eventActionsByIDAndType(c, events, "since-epoch-test", "container")
c.Assert(containerEvents, checker.HasLen, 5, check.Commentf("events: %v", events))
c.Assert(containerEvents[0], checker.Equals, "create", check.Commentf(out))
c.Assert(containerEvents[1], checker.Equals, "attach", check.Commentf(out))
c.Assert(containerEvents[2], checker.Equals, "start", check.Commentf(out))
c.Assert(containerEvents[3], checker.Equals, "die", check.Commentf(out))
c.Assert(containerEvents[4], checker.Equals, "destroy", check.Commentf(out))
}
func (s *DockerSuite) TestEventsImageUntagDelete(c *check.C) {
testRequires(c, DaemonIsLinux)
observer, err := newEventObserver(c)
c.Assert(err, checker.IsNil)
err = observer.Start()
c.Assert(err, checker.IsNil)
defer observer.Stop()
name := "testimageevents"
_, err := buildImage(name,
imageID, err := buildImage(name,
`FROM scratch
MAINTAINER "docker"`,
true)
c.Assert(err, checker.IsNil)
c.Assert(deleteImages(name), checker.IsNil)
out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
events := strings.Split(out, "\n")
events = events[:len(events)-1]
c.Assert(len(events), checker.GreaterOrEqualThan, 2) //Missing expected event
untagEvent := strings.Fields(events[len(events)-2])
deleteEvent := strings.Fields(events[len(events)-1])
c.Assert(untagEvent[len(untagEvent)-1], checker.Equals, "untag", check.Commentf("untag should be untag, not %#v", untagEvent))
c.Assert(deleteEvent[len(deleteEvent)-1], checker.Equals, "delete", check.Commentf("untag should be delete, not %#v", untagEvent))
testActions := map[string]chan bool{
"untag": make(chan bool),
"delete": make(chan bool),
}
go observer.Match(matchEventLine(imageID, "image", testActions))
select {
case <-time.After(10 * time.Second):
c.Fatal(observer.TimeoutError(imageID, "untag"))
case <-testActions["untag"]:
// ignore, done
}
select {
case <-time.After(10 * time.Second):
c.Fatal(observer.TimeoutError(imageID, "delete"))
case <-testActions["delete"]:
// ignore, done
}
}
func (s *DockerSuite) TestEventsImageTag(c *check.C) {
@ -189,10 +203,11 @@ func (s *DockerSuite) TestEventsImageTag(c *check.C) {
events := strings.Split(strings.TrimSpace(out), "\n")
c.Assert(events, checker.HasLen, 1, check.Commentf("was expecting 1 event. out=%s", out))
event := strings.TrimSpace(events[0])
expectedStr := image + ": tag"
c.Assert(event, checker.HasSuffix, expectedStr, check.Commentf("wrong event format. expected='%s' got=%s", expectedStr, event))
matches := parseEventText(event)
c.Assert(matches, checker.Not(checker.IsNil))
c.Assert(matchEventID(matches, image), checker.True, check.Commentf("matches: %v\nout:\n%s", matches, out))
c.Assert(matches["action"], checker.Equals, "tag")
}
func (s *DockerSuite) TestEventsImagePull(c *check.C) {
@ -208,68 +223,46 @@ func (s *DockerSuite) TestEventsImagePull(c *check.C) {
events := strings.Split(strings.TrimSpace(out), "\n")
event := strings.TrimSpace(events[len(events)-1])
c.Assert(event, checker.HasSuffix, "hello-world:latest: pull", check.Commentf("Missing pull event - got:%q", event))
matches := parseEventText(event)
c.Assert(matches, checker.Not(checker.IsNil))
c.Assert(matches["id"], checker.Equals, "hello-world:latest")
c.Assert(matches["action"], checker.Equals, "pull")
}
func (s *DockerSuite) TestEventsImageImport(c *check.C) {
testRequires(c, DaemonIsLinux)
observer, err := newEventObserver(c)
c.Assert(err, checker.IsNil)
err = observer.Start()
c.Assert(err, checker.IsNil)
defer observer.Stop()
out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
cleanedContainerID := strings.TrimSpace(out)
out, _, err = runCommandPipelineWithOutput(
since := daemonTime(c).Unix()
out, _, err := runCommandPipelineWithOutput(
exec.Command(dockerBinary, "export", cleanedContainerID),
exec.Command(dockerBinary, "import", "-"),
)
c.Assert(err, checker.IsNil, check.Commentf("import failed with output: %q", out))
imageRef := strings.TrimSpace(out)
eventImport := make(chan bool)
matchImport := regexp.MustCompile(imageRef + `: import\z`)
matcher := func(text string) {
if matchImport.MatchString(text) {
close(eventImport)
}
}
go observer.Match(matcher)
select {
case <-time.After(5 * time.Second):
c.Fatal(observer.TimeoutError(imageRef, "import"))
case <-eventImport:
// ignore, done
}
out, _ = dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", "event=import")
events := strings.Split(strings.TrimSpace(out), "\n")
c.Assert(events, checker.HasLen, 1)
matches := parseEventText(events[0])
c.Assert(matches["id"], checker.Equals, imageRef, check.Commentf("matches: %v\nout:\n%s\n", matches, out))
c.Assert(matches["action"], checker.Equals, "import", check.Commentf("matches: %v\nout:\n%s\n", matches, out))
}
func (s *DockerSuite) TestEventsFilters(c *check.C) {
testRequires(c, DaemonIsLinux)
parseEvents := func(out, match string) {
events := strings.Split(out, "\n")
events = events[:len(events)-1]
for _, event := range events {
eventFields := strings.Fields(event)
eventName := eventFields[len(eventFields)-1]
c.Assert(eventName, checker.Matches, match)
}
}
since := daemonTime(c).Unix()
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")
parseEvents(out, "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")
parseEvents(out, "((die)|(start))")
parseEvents(c, out, "die|start")
// make sure we at least got 2 start events
count := strings.Count(out, "start")
@ -385,15 +378,9 @@ func (s *DockerSuite) TestEventsFilterContainer(c *check.C) {
return fmt.Errorf("expected 4 events, got %v", events)
}
for _, event := range events {
e := strings.Fields(event)
if len(e) < 3 {
return fmt.Errorf("got malformed event: %s", event)
}
// Check the id
parsedID := strings.TrimSuffix(e[1], ":")
if parsedID != id {
return fmt.Errorf("expected event for container id %s: %s - parsed container id: %s", id, event, parsedID)
matches := parseEventText(event)
if !matchEventID(matches, id) {
return fmt.Errorf("expected event for container id %s: %s - parsed container id: %s", id, event, matches["id"])
}
}
return nil
@ -450,21 +437,21 @@ func (s *DockerSuite) TestEventsStreaming(c *check.C) {
select {
case <-time.After(5 * time.Second):
c.Fatal(observer.TimeoutError(containerID, "create"))
case <-eventCreate:
case <-testActions["create"]:
// ignore, done
}
select {
case <-time.After(5 * time.Second):
c.Fatal(observer.TimeoutError(containerID, "start"))
case <-eventStart:
case <-testActions["start"]:
// ignore, done
}
select {
case <-time.After(5 * time.Second):
c.Fatal(observer.TimeoutError(containerID, "die"))
case <-eventDie:
case <-testActions["die"]:
// ignore, done
}
@ -490,7 +477,7 @@ func (s *DockerSuite) TestEventsCommit(c *check.C) {
dockerCmd(c, "stop", cID)
out, _ = dockerCmd(c, "events", "--since=0", "-f", "container="+cID, "--until="+strconv.Itoa(int(since)))
c.Assert(out, checker.Contains, " commit\n", check.Commentf("Missing 'commit' log event"))
c.Assert(out, checker.Contains, "commit", check.Commentf("Missing 'commit' log event"))
}
func (s *DockerSuite) TestEventsCopy(c *check.C) {
@ -515,12 +502,12 @@ func (s *DockerSuite) TestEventsCopy(c *check.C) {
dockerCmd(c, "cp", "cptest:/tmp/file", tempFile.Name())
out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=cptest", "--until="+strconv.Itoa(int(since)))
c.Assert(out, checker.Contains, " archive-path\n", check.Commentf("Missing 'archive-path' log event\n"))
c.Assert(out, checker.Contains, "archive-path", check.Commentf("Missing 'archive-path' log event\n"))
dockerCmd(c, "cp", tempFile.Name(), "cptest:/tmp/filecopy")
out, _ = dockerCmd(c, "events", "--since=0", "-f", "container=cptest", "--until="+strconv.Itoa(int(since)))
c.Assert(out, checker.Contains, " extract-to-dir\n", check.Commentf("Missing 'extract-to-dir' log event"))
c.Assert(out, checker.Contains, "extract-to-dir", check.Commentf("Missing 'extract-to-dir' log event"))
}
func (s *DockerSuite) TestEventsResize(c *check.C) {
@ -539,7 +526,7 @@ 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)))
c.Assert(out, checker.Contains, " resize\n", check.Commentf("Missing 'resize' log event"))
c.Assert(out, checker.Contains, "resize", check.Commentf("Missing 'resize' log event"))
}
func (s *DockerSuite) TestEventsAttach(c *check.C) {
@ -571,7 +558,7 @@ func (s *DockerSuite) TestEventsAttach(c *check.C) {
dockerCmd(c, "stop", cID)
out, _ = dockerCmd(c, "events", "--since=0", "-f", "container="+cID, "--until="+strconv.Itoa(int(since)))
c.Assert(out, checker.Contains, " attach\n", check.Commentf("Missing 'attach' log event"))
c.Assert(out, checker.Contains, "attach", check.Commentf("Missing 'attach' log event"))
}
func (s *DockerSuite) TestEventsRename(c *check.C) {
@ -582,7 +569,7 @@ func (s *DockerSuite) TestEventsRename(c *check.C) {
dockerCmd(c, "rename", "oldName", "newName")
out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=newName", "--until="+strconv.Itoa(int(since)))
c.Assert(out, checker.Contains, " rename\n", check.Commentf("Missing 'rename' log event\n"))
c.Assert(out, checker.Contains, "rename", check.Commentf("Missing 'rename' log event\n"))
}
func (s *DockerSuite) TestEventsTop(c *check.C) {
@ -597,7 +584,7 @@ func (s *DockerSuite) TestEventsTop(c *check.C) {
dockerCmd(c, "stop", cID)
out, _ = dockerCmd(c, "events", "--since=0", "-f", "container="+cID, "--until="+strconv.Itoa(int(since)))
c.Assert(out, checker.Contains, " top\n", check.Commentf("Missing 'top' log event"))
c.Assert(out, checker.Contains, " top", check.Commentf("Missing 'top' log event"))
}
// #13753
@ -624,5 +611,5 @@ func (s *DockerRegistrySuite) TestEventsImageFilterPush(c *check.C) {
dockerCmd(c, "push", repoName)
out, _ = dockerCmd(c, "events", "--since=0", "-f", "image="+repoName, "-f", "event=push", "--until="+strconv.Itoa(int(since)))
c.Assert(out, checker.Contains, repoName+": push\n", check.Commentf("Missing 'push' log event"))
c.Assert(out, checker.Contains, repoName, check.Commentf("Missing 'push' log event for %s", repoName))
}