From 1d8ccc6ae7dafde55cf4458e3119f61c83ccbc4a Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Thu, 7 Jan 2016 23:14:05 +0100 Subject: [PATCH] Add the possibility to log event with specific attributes Signed-off-by: Vincent Demeester --- daemon/commit.go | 5 +++- daemon/events.go | 25 ++++++++++------ daemon/events_test.go | 66 ++++++++++++++++++++++++++++++++++++++++--- daemon/kill.go | 5 +++- daemon/rename.go | 9 ++++-- daemon/resize.go | 12 ++++++-- daemon/start.go | 6 +++- 7 files changed, 108 insertions(+), 20 deletions(-) diff --git a/daemon/commit.go b/daemon/commit.go index d0c4924e8e..6f2b38d52d 100644 --- a/daemon/commit.go +++ b/daemon/commit.go @@ -204,7 +204,10 @@ func (daemon *Daemon) Commit(name string, c *types.ContainerCommitConfig) (strin } } - daemon.LogContainerEvent(container, "commit") + attributes := map[string]string{ + "comment": c.Comment, + } + daemon.LogContainerEventWithAttributes(container, "commit", attributes) return id.String(), nil } diff --git a/daemon/events.go b/daemon/events.go index 825ce8a0d1..0ce0eaf0d9 100644 --- a/daemon/events.go +++ b/daemon/events.go @@ -8,9 +8,14 @@ import ( "github.com/docker/libnetwork" ) -// LogContainerEvent generates an event related to a container. +// LogContainerEvent generates an event related to a container with only the default attributes. func (daemon *Daemon) LogContainerEvent(container *container.Container, action string) { - attributes := copyAttributes(container.Config.Labels) + daemon.LogContainerEventWithAttributes(container, action, map[string]string{}) +} + +// LogContainerEventWithAttributes generates an event related to a container with specific given attributes. +func (daemon *Daemon) LogContainerEventWithAttributes(container *container.Container, action string, attributes map[string]string) { + copyAttributes(attributes, container.Config.Labels) if container.Config.Image != "" { attributes["image"] = container.Config.Image } @@ -23,14 +28,18 @@ func (daemon *Daemon) LogContainerEvent(container *container.Container, action s daemon.EventsService.Log(action, events.ContainerEventType, actor) } -// LogImageEvent generates an event related to a container. +// LogImageEvent generates an event related to a container with only the default attributes. func (daemon *Daemon) LogImageEvent(imageID, refName, action string) { - attributes := map[string]string{} + daemon.LogImageEventWithAttributes(imageID, refName, action, map[string]string{}) +} + +// LogImageEventWithAttributes generates an event related to a container with specific given attributes. +func (daemon *Daemon) LogImageEventWithAttributes(imageID, refName, action string, attributes map[string]string) { img, err := daemon.GetImage(imageID) if err == nil && img.Config != nil { // image has not been removed yet. // it could be missing if the event is `delete`. - attributes = copyAttributes(img.Config.Labels) + copyAttributes(attributes, img.Config.Labels) } if refName != "" { attributes["name"] = refName @@ -69,13 +78,11 @@ func (daemon *Daemon) LogNetworkEventWithAttributes(nw libnetwork.Network, actio } // copyAttributes guarantees that labels are not mutated by event triggers. -func copyAttributes(labels map[string]string) map[string]string { - attributes := map[string]string{} +func copyAttributes(attributes, labels map[string]string) { if labels == nil { - return attributes + return } for k, v := range labels { attributes[k] = v } - return attributes } diff --git a/daemon/events_test.go b/daemon/events_test.go index acc285ed60..8ee14a3144 100644 --- a/daemon/events_test.go +++ b/daemon/events_test.go @@ -2,13 +2,48 @@ package daemon import ( "testing" + "time" "github.com/docker/docker/container" "github.com/docker/docker/daemon/events" containertypes "github.com/docker/engine-api/types/container" + eventtypes "github.com/docker/engine-api/types/events" ) -func TestLogContainerCopyLabels(t *testing.T) { +func TestLogContainerEventCopyLabels(t *testing.T) { + e := events.New() + _, l, _ := e.Subscribe() + defer e.Evict(l) + + container := &container.Container{ + CommonContainer: container.CommonContainer{ + ID: "container_id", + Name: "container_name", + Config: &containertypes.Config{ + Image: "image_name", + Labels: map[string]string{ + "node": "1", + "os": "alpine", + }, + }, + }, + } + daemon := &Daemon{ + EventsService: e, + } + daemon.LogContainerEvent(container, "create") + + if _, mutated := container.Config.Labels["image"]; mutated { + t.Fatalf("Expected to not mutate the container labels, got %q", container.Config.Labels) + } + + validateTestAttributes(t, l, map[string]string{ + "node": "1", + "os": "alpine", + }) +} + +func TestLogContainerEventWithAttributes(t *testing.T) { e := events.New() _, l, _ := e.Subscribe() defer e.Evict(l) @@ -28,9 +63,32 @@ func TestLogContainerCopyLabels(t *testing.T) { daemon := &Daemon{ EventsService: e, } - daemon.LogContainerEvent(container, "create") + attributes := map[string]string{ + "node": "2", + "foo": "bar", + } + daemon.LogContainerEventWithAttributes(container, "create", attributes) - if _, mutated := container.Config.Labels["image"]; mutated { - t.Fatalf("Expected to not mutate the container labels, got %q", container.Config.Labels) + validateTestAttributes(t, l, map[string]string{ + "node": "1", + "foo": "bar", + }) +} + +func validateTestAttributes(t *testing.T, l chan interface{}, expectedAttributesToTest map[string]string) { + select { + case ev := <-l: + event, ok := ev.(eventtypes.Message) + if !ok { + t.Fatalf("Unexpected event message: %q", ev) + } + for key, expected := range expectedAttributesToTest { + actual, ok := event.Actor.Attributes[key] + if !ok || actual != expected { + t.Fatalf("Expected value for key %s to be %s, but was %s (event:%v)", key, expected, actual, event) + } + } + case <-time.After(10 * time.Second): + t.Fatalf("LogEvent test timed out") } } diff --git a/daemon/kill.go b/daemon/kill.go index 0f962223c6..642d488246 100644 --- a/daemon/kill.go +++ b/daemon/kill.go @@ -65,7 +65,10 @@ func (daemon *Daemon) killWithSignal(container *container.Container, sig int) er return err } - daemon.LogContainerEvent(container, "kill") + attributes := map[string]string{ + "signal": fmt.Sprintf("%d", sig), + } + daemon.LogContainerEventWithAttributes(container, "kill", attributes) return nil } diff --git a/daemon/rename.go b/daemon/rename.go index eaed577ad6..023fb7c230 100644 --- a/daemon/rename.go +++ b/daemon/rename.go @@ -49,8 +49,12 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) error { return err } + attributes := map[string]string{ + "oldName": oldName, + } + if !container.Running { - daemon.LogContainerEvent(container, "rename") + daemon.LogContainerEventWithAttributes(container, "rename", attributes) return nil } @@ -73,6 +77,7 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) error { if err != nil { return err } - daemon.LogContainerEvent(container, "rename") + + daemon.LogContainerEventWithAttributes(container, "rename", attributes) return nil } diff --git a/daemon/resize.go b/daemon/resize.go index f443af0339..c326248c92 100644 --- a/daemon/resize.go +++ b/daemon/resize.go @@ -1,6 +1,10 @@ package daemon -import derr "github.com/docker/docker/errors" +import ( + "fmt" + + derr "github.com/docker/docker/errors" +) // ContainerResize changes the size of the TTY of the process running // in the container with the given name to the given height and width. @@ -15,7 +19,11 @@ func (daemon *Daemon) ContainerResize(name string, height, width int) error { } if err = container.Resize(height, width); err == nil { - daemon.LogContainerEvent(container, "resize") + attributes := map[string]string{ + "height": fmt.Sprintf("%d", height), + "width": fmt.Sprintf("%d", width), + } + daemon.LogContainerEventWithAttributes(container, "resize", attributes) } return err } diff --git a/daemon/start.go b/daemon/start.go index 418dace609..883e9d06d9 100644 --- a/daemon/start.go +++ b/daemon/start.go @@ -1,6 +1,7 @@ package daemon import ( + "fmt" "runtime" "github.com/Sirupsen/logrus" @@ -101,7 +102,10 @@ func (daemon *Daemon) containerStart(container *container.Container) (err error) } container.ToDisk() daemon.Cleanup(container) - daemon.LogContainerEvent(container, "die") + attributes := map[string]string{ + "exitCode": fmt.Sprintf("%d", container.ExitCode), + } + daemon.LogContainerEventWithAttributes(container, "die", attributes) } }()