Browse Source

introduce « exec_die » event

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
Nicolas De Loof 7 years ago
parent
commit
aa6bb5cb69
6 changed files with 98 additions and 5 deletions
  1. 1 1
      api/swagger.yaml
  2. 12 3
      daemon/exec.go
  3. 4 1
      daemon/health.go
  4. 5 0
      daemon/monitor.go
  5. 2 0
      docs/api/version-history.md
  6. 74 0
      integration/system/event_test.go

+ 1 - 1
api/swagger.yaml

@@ -6925,7 +6925,7 @@ paths:
 
         Various objects within Docker report events when something happens to them.
 
-        Containers report these events: `attach`, `commit`, `copy`, `create`, `destroy`, `detach`, `die`, `exec_create`, `exec_detach`, `exec_start`, `export`, `health_status`, `kill`, `oom`, `pause`, `rename`, `resize`, `restart`, `start`, `stop`, `top`, `unpause`, and `update`
+        Containers report these events: `attach`, `commit`, `copy`, `create`, `destroy`, `detach`, `die`, `exec_create`, `exec_detach`, `exec_start`, `exec_die`, `export`, `health_status`, `kill`, `oom`, `pause`, `rename`, `resize`, `restart`, `start`, `stop`, `top`, `unpause`, and `update`
 
         Images report these events: `delete`, `import`, `load`, `pull`, `push`, `save`, `tag`, and `untag`
 

+ 12 - 3
daemon/exec.go

@@ -138,7 +138,10 @@ func (d *Daemon) ContainerExecCreate(name string, config *types.ExecConfig) (str
 
 	d.registerExecCommand(cntr, execConfig)
 
-	d.LogContainerEvent(cntr, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " "))
+	attributes := map[string]string{
+		"execID": execConfig.ID,
+	}
+	d.LogContainerEventWithAttributes(cntr, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " "), attributes)
 
 	return execConfig.ID, nil
 }
@@ -173,7 +176,10 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R
 
 	c := d.containers.Get(ec.ContainerID)
 	logrus.Debugf("starting exec command %s in container %s", ec.ID, c.ID)
-	d.LogContainerEvent(c, "exec_start: "+ec.Entrypoint+" "+strings.Join(ec.Args, " "))
+	attributes := map[string]string{
+		"execID": ec.ID,
+	}
+	d.LogContainerEventWithAttributes(c, "exec_start: "+ec.Entrypoint+" "+strings.Join(ec.Args, " "), attributes)
 
 	defer func() {
 		if err != nil {
@@ -269,7 +275,10 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R
 			if _, ok := err.(term.EscapeError); !ok {
 				return errors.Wrap(systemError{err}, "exec attach failed")
 			}
-			d.LogContainerEvent(c, "exec_detach")
+			attributes := map[string]string{
+				"execID": ec.ID,
+			}
+			d.LogContainerEventWithAttributes(c, "exec_detach", attributes)
 		}
 	}
 	return nil

+ 4 - 1
daemon/health.go

@@ -89,7 +89,10 @@ func (p *cmdProbe) run(ctx context.Context, d *Daemon, cntr *container.Container
 	execConfig.Env = container.ReplaceOrAppendEnvValues(cntr.CreateDaemonEnvironment(execConfig.Tty, linkedEnv), execConfig.Env)
 
 	d.registerExecCommand(cntr, execConfig)
-	d.LogContainerEvent(cntr, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " "))
+	attributes := map[string]string{
+		"execID": execConfig.ID,
+	}
+	d.LogContainerEventWithAttributes(cntr, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " "), attributes)
 
 	output := &limitedBuffer{}
 	err = d.ContainerExecStart(ctx, execConfig.ID, nil, output, output)

+ 5 - 0
daemon/monitor.go

@@ -128,6 +128,11 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc
 			// remove the exec command from the container's store only and not the
 			// daemon's store so that the exec command can be inspected.
 			c.ExecCommands.Delete(execConfig.ID, execConfig.Pid)
+			attributes := map[string]string{
+				"execID":   execConfig.ID,
+				"exitCode": strconv.Itoa(ec),
+			}
+			daemon.LogContainerEventWithAttributes(c, "exec_die", attributes)
 		} else {
 			logrus.WithFields(logrus.Fields{
 				"container": c.ID,

+ 2 - 0
docs/api/version-history.md

@@ -17,6 +17,8 @@ keywords: "API, Docker, rcli, REST, documentation"
 
 [Docker Engine API v1.36](https://docs.docker.com/engine/api/v1.36/) documentation
 
+* `Get /events` now return `exec_die` event when an exec process terminates.  
+
 
 ## v1.35 API changes
 

+ 74 - 0
integration/system/event_test.go

@@ -0,0 +1,74 @@
+package system
+
+import (
+	"context"
+	"testing"
+
+	"time"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/container"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/api/types/network"
+	"github.com/docker/docker/api/types/strslice"
+	"github.com/docker/docker/integration/util/request"
+	"github.com/stretchr/testify/require"
+)
+
+func TestEvents(t *testing.T) {
+	defer setupTest(t)()
+	ctx := context.Background()
+	client := request.NewAPIClient(t)
+
+	container, err := client.ContainerCreate(ctx,
+		&container.Config{
+			Image:      "busybox",
+			Tty:        true,
+			WorkingDir: "/root",
+			Cmd:        strslice.StrSlice([]string{"top"}),
+		},
+		&container.HostConfig{},
+		&network.NetworkingConfig{},
+		"foo",
+	)
+	require.NoError(t, err)
+	err = client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{})
+	require.NoError(t, err)
+
+	id, err := client.ContainerExecCreate(ctx, container.ID,
+		types.ExecConfig{
+			Cmd: strslice.StrSlice([]string{"echo", "hello"}),
+		},
+	)
+	require.NoError(t, err)
+
+	filters := filters.NewArgs(
+		filters.Arg("container", container.ID),
+		filters.Arg("event", "exec_die"),
+	)
+	msg, errors := client.Events(ctx, types.EventsOptions{
+		Filters: filters,
+	})
+
+	err = client.ContainerExecStart(ctx, id.ID,
+		types.ExecStartCheck{
+			Detach: true,
+			Tty:    false,
+		},
+	)
+	require.NoError(t, err)
+
+	select {
+	case m := <-msg:
+		require.Equal(t, m.Type, "container")
+		require.Equal(t, m.Actor.ID, container.ID)
+		require.Equal(t, m.Action, "exec_die")
+		require.Equal(t, m.Actor.Attributes["execID"], id.ID)
+		require.Equal(t, m.Actor.Attributes["exitCode"], "0")
+	case err = <-errors:
+		t.Fatal(err)
+	case <-time.After(time.Second * 3):
+		t.Fatal("timeout hit")
+	}
+
+}