From 06561057103441fe176910e12674d998b8561b75 Mon Sep 17 00:00:00 2001 From: "Kai Qiang Wu(Kennan)" Date: Tue, 19 Apr 2016 04:45:59 +0000 Subject: [PATCH] Add load/save image event support For every docker load and save operations, it would log related image events. Signed-off-by: Kai Qiang Wu(Kennan) --- daemon/daemon.go | 4 +- docs/reference/api/docker_remote_api_v1.24.md | 2 +- docs/reference/commandline/events.md | 2 +- image/tarexport/load.go | 1 + image/tarexport/save.go | 1 + image/tarexport/tarexport.go | 22 +++++++---- integration-cli/docker_cli_events_test.go | 39 +++++++++++++++++++ man/docker-events.1.md | 14 +++++-- 8 files changed, 71 insertions(+), 14 deletions(-) diff --git a/daemon/daemon.go b/daemon/daemon.go index 1e91fd694c..6f51015dae 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -980,7 +980,7 @@ func isBrokenPipe(e error) bool { // the same tag are exported. names is the set of tags to export, and // outStream is the writer which the images are written to. func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error { - imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.referenceStore) + imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.referenceStore, daemon) return imageExporter.Save(names, outStream) } @@ -1059,7 +1059,7 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) { // complement of ImageExport. The input stream is an uncompressed tar // ball containing images and metadata. func (daemon *Daemon) LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error { - imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.referenceStore) + imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.referenceStore, daemon) return imageExporter.Load(inTar, outStream, quiet) } diff --git a/docs/reference/api/docker_remote_api_v1.24.md b/docs/reference/api/docker_remote_api_v1.24.md index 36b31b296d..c872daa892 100644 --- a/docs/reference/api/docker_remote_api_v1.24.md +++ b/docs/reference/api/docker_remote_api_v1.24.md @@ -2404,7 +2404,7 @@ Docker containers report the following events: Docker images report the following events: - delete, import, pull, push, tag, untag + delete, import, load, pull, push, save, tag, untag Docker volumes report the following events: diff --git a/docs/reference/commandline/events.md b/docs/reference/commandline/events.md index 22e94609d2..0abfdf4377 100644 --- a/docs/reference/commandline/events.md +++ b/docs/reference/commandline/events.md @@ -25,7 +25,7 @@ Docker containers report the following events: Docker images report the following events: - delete, import, pull, push, tag, untag + delete, import, load, pull, push, save, tag, untag Docker volumes report the following events: diff --git a/image/tarexport/load.go b/image/tarexport/load.go index 42eaa40b2e..25280d4491 100644 --- a/image/tarexport/load.go +++ b/image/tarexport/load.go @@ -122,6 +122,7 @@ func (l *tarexporter) Load(inTar io.ReadCloser, outStream io.Writer, quiet bool) } parentLinks = append(parentLinks, parentLink{imgID, m.Parent}) + l.loggerImgEvent.LogImageEvent(imgID.String(), imgID.String(), "load") } for _, p := range validatedParentLinks(parentLinks) { diff --git a/image/tarexport/save.go b/image/tarexport/save.go index 9ec3cc9f52..a87a7512d6 100644 --- a/image/tarexport/save.go +++ b/image/tarexport/save.go @@ -158,6 +158,7 @@ func (s *saveSession) save(outStream io.Writer) error { parentID, _ := s.is.GetParent(id) parentLinks = append(parentLinks, parentLink{id, parentID}) + s.tarexporter.loggerImgEvent.LogImageEvent(id.String(), id.String(), "save") } for i, p := range validatedParentLinks(parentLinks) { diff --git a/image/tarexport/tarexport.go b/image/tarexport/tarexport.go index 5e20877779..b1aa5b6599 100644 --- a/image/tarexport/tarexport.go +++ b/image/tarexport/tarexport.go @@ -22,16 +22,24 @@ type manifestItem struct { } type tarexporter struct { - is image.Store - ls layer.Store - rs reference.Store + is image.Store + ls layer.Store + rs reference.Store + loggerImgEvent LogImageEvent +} + +// LogImageEvent defines interface for event generation related to image tar(load and save) operations +type LogImageEvent interface { + //LogImageEvent generates an event related to an image operation + LogImageEvent(imageID, refName, action string) } // NewTarExporter returns new ImageExporter for tar packages -func NewTarExporter(is image.Store, ls layer.Store, rs reference.Store) image.Exporter { +func NewTarExporter(is image.Store, ls layer.Store, rs reference.Store, loggerImgEvent LogImageEvent) image.Exporter { return &tarexporter{ - is: is, - ls: ls, - rs: rs, + is: is, + ls: ls, + rs: rs, + loggerImgEvent: loggerImgEvent, } } diff --git a/integration-cli/docker_cli_events_test.go b/integration-cli/docker_cli_events_test.go index 8a287141d6..cb3f77804c 100644 --- a/integration-cli/docker_cli_events_test.go +++ b/integration-cli/docker_cli_events_test.go @@ -258,6 +258,45 @@ func (s *DockerSuite) TestEventsImageImport(c *check.C) { c.Assert(matches["action"], checker.Equals, "import", check.Commentf("matches: %v\nout:\n%s\n", matches, out)) } +func (s *DockerSuite) TestEventsImageLoad(c *check.C) { + testRequires(c, DaemonIsLinux) + myImageName := "footest:v1" + dockerCmd(c, "tag", "busybox", myImageName) + since := daemonUnixTime(c) + + out, _ := dockerCmd(c, "images", "-q", "--no-trunc", myImageName) + longImageID := strings.TrimSpace(out) + c.Assert(longImageID, checker.Not(check.Equals), "", check.Commentf("Id should not be empty")) + + dockerCmd(c, "save", "-o", "saveimg.tar", myImageName) + dockerCmd(c, "rmi", myImageName) + out, _ = dockerCmd(c, "images", "-q", myImageName) + noImageID := strings.TrimSpace(out) + c.Assert(noImageID, checker.Equals, "", check.Commentf("Should not have any image")) + dockerCmd(c, "load", "-i", "saveimg.tar") + + cmd := exec.Command("rm", "-rf", "saveimg.tar") + runCommand(cmd) + + out, _ = dockerCmd(c, "images", "-q", "--no-trunc", myImageName) + imageID := strings.TrimSpace(out) + c.Assert(imageID, checker.Equals, longImageID, check.Commentf("Should have same image id as before")) + + out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=load") + events := strings.Split(strings.TrimSpace(out), "\n") + c.Assert(events, checker.HasLen, 1) + matches := eventstestutils.ScanMap(events[0]) + c.Assert(matches["id"], checker.Equals, imageID, check.Commentf("matches: %v\nout:\n%s\n", matches, out)) + c.Assert(matches["action"], checker.Equals, "load", check.Commentf("matches: %v\nout:\n%s\n", matches, out)) + + out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=save") + events = strings.Split(strings.TrimSpace(out), "\n") + c.Assert(events, checker.HasLen, 1) + matches = eventstestutils.ScanMap(events[0]) + c.Assert(matches["id"], checker.Equals, imageID, check.Commentf("matches: %v\nout:\n%s\n", matches, out)) + c.Assert(matches["action"], checker.Equals, "save", check.Commentf("matches: %v\nout:\n%s\n", matches, out)) +} + func (s *DockerSuite) TestEventsFilters(c *check.C) { since := daemonUnixTime(c) dockerCmd(c, "run", "--rm", "busybox", "true") diff --git a/man/docker-events.1.md b/man/docker-events.1.md index 4d0bff25c5..6a1a3649ff 100644 --- a/man/docker-events.1.md +++ b/man/docker-events.1.md @@ -18,11 +18,19 @@ information and real-time information. Docker containers will report the following events: - attach, commit, copy, create, destroy, die, exec_create, exec_start, export, kill, oom, pause, rename, resize, restart, start, stop, top, unpause + attach, commit, copy, create, destroy, die, exec_create, exec_start, export, kill, oom, pause, rename, resize, restart, start, stop, top, unpause, update -and Docker images will report: +Docker images report the following events: - delete, import, pull, push, tag, untag + delete, import, load, pull, push, save, tag, untag + +Docker volumes report the following events: + + create, mount, unmount, destroy + +Docker networks report the following events: + + create, connect, disconnect, destroy # OPTIONS **--help**