containerd/cmd/ctr/events.go
Stephen J Day c05be46348
events: move types into service package
When using events, it was found to be fairly unwieldy with a number of
extra packages. For the most part, when interacting with the events
service, we want types of the same version of the service. This has been
accomplished by moving all events types into the events package.

In addition, several fixes to the way events are marshaled have been
included. Specifically, we defer to the protobuf type registration
system to assemble events and type urls, with a little bit sheen on top
of add a containerd.io oriented namespace.

This has resulted in much cleaner event consumption and has removed the
reliance on error prone type urls, in favor of concrete types.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2017-06-22 19:12:25 -07:00

111 lines
2.9 KiB
Go

package main
import (
"fmt"
"os"
"strings"
"text/tabwriter"
eventsapi "github.com/containerd/containerd/api/services/events/v1"
"github.com/containerd/containerd/events"
"github.com/urfave/cli"
)
var eventsCommand = cli.Command{
Name: "events",
Usage: "display containerd events",
Action: func(context *cli.Context) error {
eventsClient, err := getEventsService(context)
if err != nil {
return err
}
ctx, cancel := appContext(context)
defer cancel()
events, err := eventsClient.Stream(ctx, &eventsapi.StreamEventsRequest{})
if err != nil {
return err
}
w := tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0)
for {
e, err := events.Recv()
if err != nil {
return err
}
out, err := getEventOutput(e)
if err != nil {
return err
}
if _, err := fmt.Fprintf(w,
"%s\t%s",
e.Timestamp,
e.Topic,
); err != nil {
return err
}
if _, err := fmt.Fprintf(w, "\t%s\n", out); err != nil {
return err
}
if err := w.Flush(); err != nil {
return err
}
}
},
}
func getEventOutput(env *eventsapi.Envelope) (string, error) {
out := ""
var de events.DynamicEvent
if err := events.UnmarshalEvent(env.Event, &de); err != nil {
return "", err
}
switch e := de.Event.(type) {
case *eventsapi.ContainerCreate:
out = fmt.Sprintf("id=%s image=%s runtime=%s", e.ContainerID, e.Image, e.Runtime)
case *eventsapi.TaskCreate:
out = "id=" + e.ContainerID
case *eventsapi.TaskStart:
out = "id=" + e.ContainerID
case *eventsapi.TaskDelete:
out = fmt.Sprintf("id=%s pid=%d status=%d", e.ContainerID, e.Pid, e.ExitStatus)
case *eventsapi.ContainerUpdate:
out = "id=" + e.ContainerID
case *eventsapi.ContainerDelete:
out = "id=" + e.ContainerID
case *eventsapi.SnapshotPrepare:
out = fmt.Sprintf("key=%s parent=%s", e.Key, e.Parent)
case *eventsapi.SnapshotCommit:
out = fmt.Sprintf("key=%s name=%s", e.Key, e.Name)
case *eventsapi.SnapshotRemove:
out = "key=" + e.Key
case *eventsapi.ImageUpdate:
out = fmt.Sprintf("name=%s labels=%s", e.Name, e.Labels)
case *eventsapi.ImageDelete:
out = "name=" + e.Name
case *eventsapi.NamespaceCreate:
out = fmt.Sprintf("name=%s labels=%s", e.Name, e.Labels)
case *eventsapi.NamespaceUpdate:
out = fmt.Sprintf("name=%s labels=%s", e.Name, e.Labels)
case *eventsapi.NamespaceDelete:
out = "name=" + e.Name
case *eventsapi.RuntimeCreate:
mounts := []string{}
for _, m := range e.RootFS {
mounts = append(mounts, fmt.Sprintf("type=%s:src=%s", m.Type, m.Source))
}
out = fmt.Sprintf("id=%s bundle=%s rootfs=%s checkpoint=%s", e.ID, e.Bundle, strings.Join(mounts, ","), e.Checkpoint)
case *eventsapi.RuntimeEvent:
out = fmt.Sprintf("id=%s type=%s pid=%d status=%d exited=%s", e.ID, e.Type, e.Pid, e.ExitStatus, e.ExitedAt)
case *eventsapi.RuntimeDelete:
out = fmt.Sprintf("id=%s runtime=%s status=%d exited=%s", e.ID, e.Runtime, e.ExitStatus, e.ExitedAt)
default:
out = env.Event.TypeUrl
}
return out, nil
}