Integrate NATS with event subsystem

Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
Kenfe-Mickael Laventure 2016-12-12 14:26:51 -08:00
parent 934940a96c
commit aa5ff88bbc
10 changed files with 165 additions and 68 deletions

View file

@ -1,8 +1,11 @@
package execution
import "time"
type ContainerEvent struct {
ID string
Action string
Timestamp time.Time
ID string
Action string
}
type ContainerExitEvent struct {
@ -16,6 +19,6 @@ const (
)
const (
containerEventsSubjectFormat = "containerd.execution.container.%s"
containerProcessEventsSubjectFormat = "containerd.execution.container.%s.%s"
containerEventsTopicFormat = "container.%s"
containerProcessEventsTopicFormat = "container.%s.%s"
)

View file

@ -12,7 +12,9 @@ import (
"github.com/docker/containerd/execution"
)
var ErrRootEmpty = errors.New("oci: runtime root cannot be an empty string")
var (
ErrRootEmpty = errors.New("oci: runtime root cannot be an empty string")
)
func New(root string) (*OCIRuntime, error) {
err := SetSubreaper(1)

19
execution/log.go Normal file
View file

@ -0,0 +1,19 @@
package execution
import (
"context"
"github.com/docker/containerd/log"
"github.com/sirupsen/logrus"
)
var ctx context.Context
func GetLogger(module string) *logrus.Entry {
if ctx == nil {
ctx = log.WithModule(context.Background(), "execution")
}
subCtx := log.WithModule(ctx, module)
return log.GetLogger(subCtx)
}

View file

@ -3,10 +3,11 @@ package execution
import (
"fmt"
"syscall"
"time"
api "github.com/docker/containerd/api/execution"
"github.com/docker/containerd/events"
google_protobuf "github.com/golang/protobuf/ptypes/empty"
"github.com/nats-io/go-nats"
"github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/net/context"
)
@ -16,17 +17,15 @@ var (
ErrProcessNotFound = fmt.Errorf("Process not found")
)
func New(executor Executor, nec *nats.EncodedConn) (*Service, error) {
func New(executor Executor) (*Service, error) {
return &Service{
executor: executor,
nec: nec,
}, nil
}
type Service struct {
executor Executor
supervisor *Supervisor
nec *nats.EncodedConn
}
func (s *Service) Create(ctx context.Context, r *api.CreateContainerRequest) (*api.CreateContainerResponse, error) {
@ -46,7 +45,7 @@ func (s *Service) Create(ctx context.Context, r *api.CreateContainerRequest) (*a
procs := container.Processes()
initProcess := procs[0]
s.monitorProcess(container, initProcess)
s.monitorProcess(ctx, container, initProcess)
return &api.CreateContainerResponse{
Container: toGRPCContainer(container),
@ -145,7 +144,7 @@ func (s *Service) StartProcess(ctx context.Context, r *api.StartProcessRequest)
return nil, err
}
s.monitorProcess(container, process)
s.monitorProcess(ctx, container, process)
return &api.StartProcessResponse{
Process: toGRPCProcess(process),
@ -205,27 +204,21 @@ var (
_ = (api.ExecutionServiceServer)(&Service{})
)
func (s *Service) publishEvent(name string, v interface{}) {
if s.nec == nil {
return
}
err := s.nec.Publish(name, v)
if err != nil {
// TODO: Use logrus?
fmt.Println("Failed to publish '%s:%#v': %v", name, v, err)
}
func (s *Service) publishEvent(ctx context.Context, topic string, v interface{}) {
ctx = events.WithTopic(ctx, topic)
events.GetPoster(ctx).Post(ctx, v)
}
func (s *Service) monitorProcess(container *Container, process Process) {
func (s *Service) monitorProcess(ctx context.Context, container *Container, process Process) {
go func() {
status, err := process.Wait()
if err == nil {
subject := GetContainerProcessEventSubject(container.ID(), process.ID())
s.publishEvent(subject, &ContainerExitEvent{
topic := GetContainerProcessEventTopic(container.ID(), process.ID())
s.publishEvent(ctx, topic, &ContainerExitEvent{
ContainerEvent: ContainerEvent{
ID: container.ID(),
Action: "exit",
Timestamp: time.Now(),
ID: container.ID(),
Action: "exit",
},
PID: process.ID(),
StatusCode: status,
@ -234,12 +227,12 @@ func (s *Service) monitorProcess(container *Container, process Process) {
}()
}
func GetContainerEventSubject(id string) string {
return fmt.Sprintf(containerEventsSubjectFormat, id)
func GetContainerEventTopic(id string) string {
return fmt.Sprintf(containerEventsTopicFormat, id)
}
func GetContainerProcessEventSubject(containerID, processID string) string {
return fmt.Sprintf(containerProcessEventsSubjectFormat, containerID, processID)
func GetContainerProcessEventTopic(containerID, processID string) string {
return fmt.Sprintf(containerProcessEventsTopicFormat, containerID, processID)
}
func toGRPCContainer(container *Container) *api.Container {