Add the possibility to log event with specific attributes

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
Vincent Demeester 2016-01-07 23:14:05 +01:00
parent 82401a4b13
commit 1d8ccc6ae7
7 changed files with 108 additions and 20 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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")
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}
}()