Remove bundles from API

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2017-02-13 10:23:28 -08:00
parent 1dc5d652ac
commit ab8586b7c5
48 changed files with 3287 additions and 5946 deletions

File diff suppressed because it is too large Load diff

View file

@ -3,116 +3,54 @@ syntax = "proto3";
package containerd.v1.services;
import "google/protobuf/empty.proto";
import "google/protobuf/any.proto";
import "gogoproto/gogo.proto";
import "github.com/docker/containerd/api/types/mount/mount.proto";
import "github.com/docker/containerd/api/types/container/container.proto";
import "github.com/docker/containerd/api/types/process/process.proto";
service ExecutionService {
rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse);
rpc StartContainer(StartContainerRequest) returns (google.protobuf.Empty);
rpc UpdateContainer(UpdateContainerRequest) returns (google.protobuf.Empty);
rpc PauseContainer(PauseContainerRequest) returns (google.protobuf.Empty);
rpc ResumeContainer(ResumeContainerRequest) returns (google.protobuf.Empty);
rpc DeleteContainer(DeleteContainerRequest) returns (google.protobuf.Empty);
rpc GetContainer(GetContainerRequest) returns (GetContainerResponse);
rpc ListContainers(ListContainersRequest) returns (ListContainersResponse);
rpc StartProcess(StartProcessRequest) returns (StartProcessResponse);
rpc GetProcess(GetProcessRequest) returns (GetProcessResponse);
rpc SignalProcess(SignalProcessRequest) returns (google.protobuf.Empty);
rpc DeleteProcess(DeleteProcessRequest) returns (google.protobuf.Empty);
rpc ListProcesses(ListProcessesRequest) returns (ListProcessesResponse);
service ContainerService {
rpc Create(CreateRequest) returns (CreateResponse);
rpc Start(StartRequest) returns (google.protobuf.Empty);
rpc Delete(DeleteRequest) returns (google.protobuf.Empty);
rpc List(ListRequest) returns (ListResponse);
rpc Events(EventsRequest) returns (stream containerd.v1.types.Event);
}
message StartContainerRequest {
message CreateRequest {
string id = 1 [(gogoproto.customname) = "ID"];
google.protobuf.Any spec = 2;
repeated containerd.v1.types.Mount rootfs = 3;
string runtime = 4;
string stdin = 5;
string stdout = 6;
string stderr = 7;
bool terminal = 8;
}
message CreateContainerRequest {
message CreateResponse {
string id = 1 [(gogoproto.customname) = "ID"];
string bundle_path = 2;
bool console = 3;
string stdin = 4;
string stdout = 5;
string stderr = 6;
}
message CreateContainerResponse {
types.Container container = 1;
types.Process initProcess = 2;
}
message DeleteContainerRequest {
string id = 1 [(gogoproto.customname) = "ID"];
}
message ListContainersRequest {
repeated string owner = 1;
}
message ListContainersResponse {
repeated types.Container containers = 1;
}
message StartProcessRequest {
string container_id = 1 [(gogoproto.customname) = "ContainerID"];
types.Process process = 2;
bool console = 3;
string stdin = 4;
string stdout = 5;
string stderr = 6;
}
message StartProcessResponse {
types.Process process = 1;
}
message GetContainerRequest {
string id = 1 [(gogoproto.customname) = "ID"];
}
message GetContainerResponse {
types.Container container = 1;
}
message UpdateContainerRequest {
string container_id = 1 [(gogoproto.customname) = "ContainerID"];
string bundle_path = 2;
}
message PauseContainerRequest {
string id = 1 [(gogoproto.customname) = "ID"];
}
message ResumeContainerRequest {
string id = 1 [(gogoproto.customname) = "ID"];
}
message GetProcessRequest {
string container_id = 1 [(gogoproto.customname) = "ContainerID"];
uint32 pid = 2;
}
message GetProcessResponse {
types.Process process = 1;
message StartRequest {
string id = 1 [(gogoproto.customname) = "ID"];
}
message SignalProcessRequest {
string container_id = 1 [(gogoproto.customname) = "ContainerID"];
uint32 pid = 2;
uint32 signal = 3;
message DeleteRequest {
string id = 1 [(gogoproto.customname) = "ID"];
}
message DeleteProcessRequest {
string container_id = 1 [(gogoproto.customname) = "ContainerID"];
uint32 pid = 2;
message DeleteResponse {
string id = 1 [(gogoproto.customname) = "ID"];
uint32 exit_status = 2;
}
message ListProcessesRequest {
string container_id = 1 [(gogoproto.customname) = "ContainerID"];
message ListRequest {
}
message ListProcessesResponse {
repeated types.Process processes = 1;
message ListResponse {
repeated containerd.v1.types.Container containers = 1;
}
message EventsRequest {
}

View file

@ -19,11 +19,11 @@
ExecResponse
PtyRequest
EventsRequest
Event
StateRequest
StateResponse
PauseRequest
ResumeRequest
ExitRequest
*/
package shim
@ -32,8 +32,8 @@ import fmt "fmt"
import math "math"
import google_protobuf "github.com/golang/protobuf/ptypes/empty"
import _ "github.com/gogo/protobuf/gogoproto"
import containerd_v1_types2 "github.com/docker/containerd/api/types/process"
import containerd_v1_types "github.com/docker/containerd/api/types/user"
import containerd_v1_types "github.com/docker/containerd/api/types/mount"
import containerd_v1_types1 "github.com/docker/containerd/api/types/container"
import (
context "golang.org/x/net/context"
@ -56,36 +56,6 @@ var _ = math.Inf
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type EventType int32
const (
EventType_EXIT EventType = 0
EventType_OOM EventType = 1
EventType_CREATE EventType = 2
EventType_START EventType = 3
EventType_EXEC_ADDED EventType = 4
)
var EventType_name = map[int32]string{
0: "EXIT",
1: "OOM",
2: "CREATE",
3: "START",
4: "EXEC_ADDED",
}
var EventType_value = map[string]int32{
"EXIT": 0,
"OOM": 1,
"CREATE": 2,
"START": 3,
"EXEC_ADDED": 4,
}
func (x EventType) String() string {
return proto.EnumName(EventType_name, int32(x))
}
func (EventType) EnumDescriptor() ([]byte, []int) { return fileDescriptorShim, []int{0} }
type CreateRequest struct {
ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Bundle string `protobuf:"bytes,2,opt,name=bundle,proto3" json:"bundle,omitempty"`
@ -95,6 +65,7 @@ type CreateRequest struct {
Stdin string `protobuf:"bytes,6,opt,name=stdin,proto3" json:"stdin,omitempty"`
Stdout string `protobuf:"bytes,7,opt,name=stdout,proto3" json:"stdout,omitempty"`
Stderr string `protobuf:"bytes,8,opt,name=stderr,proto3" json:"stderr,omitempty"`
Rootfs []*containerd_v1_types.Mount `protobuf:"bytes,9,rep,name=rootfs" json:"rootfs,omitempty"`
}
func (m *CreateRequest) Reset() { *m = CreateRequest{} }
@ -138,7 +109,7 @@ type ExecRequest struct {
Stdout string `protobuf:"bytes,3,opt,name=stdout,proto3" json:"stdout,omitempty"`
Stderr string `protobuf:"bytes,4,opt,name=stderr,proto3" json:"stderr,omitempty"`
SelinuxLabel string `protobuf:"bytes,5,opt,name=selinux_label,json=selinuxLabel,proto3" json:"selinux_label,omitempty"`
User *containerd_v1_types.User `protobuf:"bytes,6,opt,name=user" json:"user,omitempty"`
User *containerd_v1_types1.User `protobuf:"bytes,6,opt,name=user" json:"user,omitempty"`
Args []string `protobuf:"bytes,7,rep,name=args" json:"args,omitempty"`
Env []string `protobuf:"bytes,8,rep,name=env" json:"env,omitempty"`
Cwd string `protobuf:"bytes,9,opt,name=cwd,proto3" json:"cwd,omitempty"`
@ -187,49 +158,44 @@ func (m *EventsRequest) Reset() { *m = EventsRequest{} }
func (*EventsRequest) ProtoMessage() {}
func (*EventsRequest) Descriptor() ([]byte, []int) { return fileDescriptorShim, []int{9} }
// should be moved to api/types/event maybe
type Event struct {
ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Type EventType `protobuf:"varint,2,opt,name=type,proto3,enum=containerd.v1.services.EventType" json:"type,omitempty"`
Pid uint32 `protobuf:"varint,3,opt,name=pid,proto3" json:"pid,omitempty"`
ExitStatus uint32 `protobuf:"varint,4,opt,name=exit_status,json=exitStatus,proto3" json:"exit_status,omitempty"`
}
func (m *Event) Reset() { *m = Event{} }
func (*Event) ProtoMessage() {}
func (*Event) Descriptor() ([]byte, []int) { return fileDescriptorShim, []int{10} }
type StateRequest struct {
}
func (m *StateRequest) Reset() { *m = StateRequest{} }
func (*StateRequest) ProtoMessage() {}
func (*StateRequest) Descriptor() ([]byte, []int) { return fileDescriptorShim, []int{11} }
func (*StateRequest) Descriptor() ([]byte, []int) { return fileDescriptorShim, []int{10} }
type StateResponse struct {
ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Bundle string `protobuf:"bytes,2,opt,name=bundle,proto3" json:"bundle,omitempty"`
InitPid uint32 `protobuf:"varint,3,opt,name=initPid,proto3" json:"initPid,omitempty"`
Processes []*containerd_v1_types2.Process `protobuf:"bytes,4,rep,name=processes" json:"processes,omitempty"`
Pid uint32 `protobuf:"varint,3,opt,name=pid,proto3" json:"pid,omitempty"`
Processes []*containerd_v1_types1.Process `protobuf:"bytes,4,rep,name=processes" json:"processes,omitempty"`
}
func (m *StateResponse) Reset() { *m = StateResponse{} }
func (*StateResponse) ProtoMessage() {}
func (*StateResponse) Descriptor() ([]byte, []int) { return fileDescriptorShim, []int{12} }
func (*StateResponse) Descriptor() ([]byte, []int) { return fileDescriptorShim, []int{11} }
type PauseRequest struct {
}
func (m *PauseRequest) Reset() { *m = PauseRequest{} }
func (*PauseRequest) ProtoMessage() {}
func (*PauseRequest) Descriptor() ([]byte, []int) { return fileDescriptorShim, []int{13} }
func (*PauseRequest) Descriptor() ([]byte, []int) { return fileDescriptorShim, []int{12} }
type ResumeRequest struct {
}
func (m *ResumeRequest) Reset() { *m = ResumeRequest{} }
func (*ResumeRequest) ProtoMessage() {}
func (*ResumeRequest) Descriptor() ([]byte, []int) { return fileDescriptorShim, []int{14} }
func (*ResumeRequest) Descriptor() ([]byte, []int) { return fileDescriptorShim, []int{13} }
type ExitRequest struct {
}
func (m *ExitRequest) Reset() { *m = ExitRequest{} }
func (*ExitRequest) ProtoMessage() {}
func (*ExitRequest) Descriptor() ([]byte, []int) { return fileDescriptorShim, []int{14} }
func init() {
proto.RegisterType((*CreateRequest)(nil), "containerd.v1.services.CreateRequest")
@ -242,12 +208,11 @@ func init() {
proto.RegisterType((*ExecResponse)(nil), "containerd.v1.services.ExecResponse")
proto.RegisterType((*PtyRequest)(nil), "containerd.v1.services.PtyRequest")
proto.RegisterType((*EventsRequest)(nil), "containerd.v1.services.EventsRequest")
proto.RegisterType((*Event)(nil), "containerd.v1.services.Event")
proto.RegisterType((*StateRequest)(nil), "containerd.v1.services.StateRequest")
proto.RegisterType((*StateResponse)(nil), "containerd.v1.services.StateResponse")
proto.RegisterType((*PauseRequest)(nil), "containerd.v1.services.PauseRequest")
proto.RegisterType((*ResumeRequest)(nil), "containerd.v1.services.ResumeRequest")
proto.RegisterEnum("containerd.v1.services.EventType", EventType_name, EventType_value)
proto.RegisterType((*ExitRequest)(nil), "containerd.v1.services.ExitRequest")
}
// Reference imports to suppress errors if they are not otherwise used.
@ -270,6 +235,7 @@ type ShimClient interface {
State(ctx context.Context, in *StateRequest, opts ...grpc.CallOption) (*StateResponse, error)
Pause(ctx context.Context, in *PauseRequest, opts ...grpc.CallOption) (*google_protobuf.Empty, error)
Resume(ctx context.Context, in *ResumeRequest, opts ...grpc.CallOption) (*google_protobuf.Empty, error)
Exit(ctx context.Context, in *ExitRequest, opts ...grpc.CallOption) (*google_protobuf.Empty, error)
}
type shimClient struct {
@ -341,7 +307,7 @@ func (c *shimClient) Events(ctx context.Context, in *EventsRequest, opts ...grpc
}
type Shim_EventsClient interface {
Recv() (*Event, error)
Recv() (*containerd_v1_types1.Event, error)
grpc.ClientStream
}
@ -349,8 +315,8 @@ type shimEventsClient struct {
grpc.ClientStream
}
func (x *shimEventsClient) Recv() (*Event, error) {
m := new(Event)
func (x *shimEventsClient) Recv() (*containerd_v1_types1.Event, error) {
m := new(containerd_v1_types1.Event)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
@ -384,6 +350,15 @@ func (c *shimClient) Resume(ctx context.Context, in *ResumeRequest, opts ...grpc
return out, nil
}
func (c *shimClient) Exit(ctx context.Context, in *ExitRequest, opts ...grpc.CallOption) (*google_protobuf.Empty, error) {
out := new(google_protobuf.Empty)
err := grpc.Invoke(ctx, "/containerd.v1.services.Shim/Exit", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for Shim service
type ShimServer interface {
@ -396,6 +371,7 @@ type ShimServer interface {
State(context.Context, *StateRequest) (*StateResponse, error)
Pause(context.Context, *PauseRequest) (*google_protobuf.Empty, error)
Resume(context.Context, *ResumeRequest) (*google_protobuf.Empty, error)
Exit(context.Context, *ExitRequest) (*google_protobuf.Empty, error)
}
func RegisterShimServer(s *grpc.Server, srv ShimServer) {
@ -501,7 +477,7 @@ func _Shim_Events_Handler(srv interface{}, stream grpc.ServerStream) error {
}
type Shim_EventsServer interface {
Send(*Event) error
Send(*containerd_v1_types1.Event) error
grpc.ServerStream
}
@ -509,7 +485,7 @@ type shimEventsServer struct {
grpc.ServerStream
}
func (x *shimEventsServer) Send(m *Event) error {
func (x *shimEventsServer) Send(m *containerd_v1_types1.Event) error {
return x.ServerStream.SendMsg(m)
}
@ -567,6 +543,24 @@ func _Shim_Resume_Handler(srv interface{}, ctx context.Context, dec func(interfa
return interceptor(ctx, in, info, handler)
}
func _Shim_Exit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ExitRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ShimServer).Exit(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/containerd.v1.services.Shim/Exit",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ShimServer).Exit(ctx, req.(*ExitRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Shim_serviceDesc = grpc.ServiceDesc{
ServiceName: "containerd.v1.services.Shim",
HandlerType: (*ShimServer)(nil),
@ -603,6 +597,10 @@ var _Shim_serviceDesc = grpc.ServiceDesc{
MethodName: "Resume",
Handler: _Shim_Resume_Handler,
},
{
MethodName: "Exit",
Handler: _Shim_Exit_Handler,
},
},
Streams: []grpc.StreamDesc{
{
@ -685,6 +683,18 @@ func (m *CreateRequest) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintShim(dAtA, i, uint64(len(m.Stderr)))
i += copy(dAtA[i:], m.Stderr)
}
if len(m.Rootfs) > 0 {
for _, msg := range m.Rootfs {
dAtA[i] = 0x4a
i++
i = encodeVarintShim(dAtA, i, uint64(msg.Size()))
n, err := msg.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n
}
}
return i, nil
}
@ -1024,45 +1034,6 @@ func (m *EventsRequest) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func (m *Event) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Event) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.ID) > 0 {
dAtA[i] = 0xa
i++
i = encodeVarintShim(dAtA, i, uint64(len(m.ID)))
i += copy(dAtA[i:], m.ID)
}
if m.Type != 0 {
dAtA[i] = 0x10
i++
i = encodeVarintShim(dAtA, i, uint64(m.Type))
}
if m.Pid != 0 {
dAtA[i] = 0x18
i++
i = encodeVarintShim(dAtA, i, uint64(m.Pid))
}
if m.ExitStatus != 0 {
dAtA[i] = 0x20
i++
i = encodeVarintShim(dAtA, i, uint64(m.ExitStatus))
}
return i, nil
}
func (m *StateRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -1108,10 +1079,10 @@ func (m *StateResponse) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintShim(dAtA, i, uint64(len(m.Bundle)))
i += copy(dAtA[i:], m.Bundle)
}
if m.InitPid != 0 {
if m.Pid != 0 {
dAtA[i] = 0x18
i++
i = encodeVarintShim(dAtA, i, uint64(m.InitPid))
i = encodeVarintShim(dAtA, i, uint64(m.Pid))
}
if len(m.Processes) > 0 {
for _, msg := range m.Processes {
@ -1164,6 +1135,24 @@ func (m *ResumeRequest) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func (m *ExitRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ExitRequest) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
return i, nil
}
func encodeFixed64Shim(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
@ -1224,6 +1213,12 @@ func (m *CreateRequest) Size() (n int) {
if l > 0 {
n += 1 + l + sovShim(uint64(l))
}
if len(m.Rootfs) > 0 {
for _, e := range m.Rootfs {
l = e.Size()
n += 1 + l + sovShim(uint64(l))
}
}
return n
}
@ -1370,25 +1365,6 @@ func (m *EventsRequest) Size() (n int) {
return n
}
func (m *Event) Size() (n int) {
var l int
_ = l
l = len(m.ID)
if l > 0 {
n += 1 + l + sovShim(uint64(l))
}
if m.Type != 0 {
n += 1 + sovShim(uint64(m.Type))
}
if m.Pid != 0 {
n += 1 + sovShim(uint64(m.Pid))
}
if m.ExitStatus != 0 {
n += 1 + sovShim(uint64(m.ExitStatus))
}
return n
}
func (m *StateRequest) Size() (n int) {
var l int
_ = l
@ -1406,8 +1382,8 @@ func (m *StateResponse) Size() (n int) {
if l > 0 {
n += 1 + l + sovShim(uint64(l))
}
if m.InitPid != 0 {
n += 1 + sovShim(uint64(m.InitPid))
if m.Pid != 0 {
n += 1 + sovShim(uint64(m.Pid))
}
if len(m.Processes) > 0 {
for _, e := range m.Processes {
@ -1430,6 +1406,12 @@ func (m *ResumeRequest) Size() (n int) {
return n
}
func (m *ExitRequest) Size() (n int) {
var l int
_ = l
return n
}
func sovShim(x uint64) (n int) {
for {
n++
@ -1456,6 +1438,7 @@ func (this *CreateRequest) String() string {
`Stdin:` + fmt.Sprintf("%v", this.Stdin) + `,`,
`Stdout:` + fmt.Sprintf("%v", this.Stdout) + `,`,
`Stderr:` + fmt.Sprintf("%v", this.Stderr) + `,`,
`Rootfs:` + strings.Replace(fmt.Sprintf("%v", this.Rootfs), "Mount", "containerd_v1_types.Mount", 1) + `,`,
`}`,
}, "")
return s
@ -1509,7 +1492,7 @@ func (this *ExecRequest) String() string {
`Stdout:` + fmt.Sprintf("%v", this.Stdout) + `,`,
`Stderr:` + fmt.Sprintf("%v", this.Stderr) + `,`,
`SelinuxLabel:` + fmt.Sprintf("%v", this.SelinuxLabel) + `,`,
`User:` + strings.Replace(fmt.Sprintf("%v", this.User), "User", "containerd_v1_types.User", 1) + `,`,
`User:` + strings.Replace(fmt.Sprintf("%v", this.User), "User", "containerd_v1_types1.User", 1) + `,`,
`Args:` + fmt.Sprintf("%v", this.Args) + `,`,
`Env:` + fmt.Sprintf("%v", this.Env) + `,`,
`Cwd:` + fmt.Sprintf("%v", this.Cwd) + `,`,
@ -1564,19 +1547,6 @@ func (this *EventsRequest) String() string {
}, "")
return s
}
func (this *Event) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&Event{`,
`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
`Type:` + fmt.Sprintf("%v", this.Type) + `,`,
`Pid:` + fmt.Sprintf("%v", this.Pid) + `,`,
`ExitStatus:` + fmt.Sprintf("%v", this.ExitStatus) + `,`,
`}`,
}, "")
return s
}
func (this *StateRequest) String() string {
if this == nil {
return "nil"
@ -1593,8 +1563,8 @@ func (this *StateResponse) String() string {
s := strings.Join([]string{`&StateResponse{`,
`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
`Bundle:` + fmt.Sprintf("%v", this.Bundle) + `,`,
`InitPid:` + fmt.Sprintf("%v", this.InitPid) + `,`,
`Processes:` + strings.Replace(fmt.Sprintf("%v", this.Processes), "Process", "containerd_v1_types2.Process", 1) + `,`,
`Pid:` + fmt.Sprintf("%v", this.Pid) + `,`,
`Processes:` + strings.Replace(fmt.Sprintf("%v", this.Processes), "Process", "containerd_v1_types1.Process", 1) + `,`,
`}`,
}, "")
return s
@ -1617,6 +1587,15 @@ func (this *ResumeRequest) String() string {
}, "")
return s
}
func (this *ExitRequest) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&ExitRequest{`,
`}`,
}, "")
return s
}
func valueToStringShim(v interface{}) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
@ -1868,6 +1847,37 @@ func (m *CreateRequest) Unmarshal(dAtA []byte) error {
}
m.Stderr = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 9:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Rootfs", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowShim
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthShim
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Rootfs = append(m.Rootfs, &containerd_v1_types.Mount{})
if err := m.Rootfs[len(m.Rootfs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipShim(dAtA[iNdEx:])
@ -2338,7 +2348,7 @@ func (m *ExecRequest) Unmarshal(dAtA []byte) error {
return io.ErrUnexpectedEOF
}
if m.User == nil {
m.User = &containerd_v1_types.User{}
m.User = &containerd_v1_types1.User{}
}
if err := m.User.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
@ -2904,142 +2914,6 @@ func (m *EventsRequest) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *Event) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowShim
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Event: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Event: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowShim
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthShim
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
}
m.Type = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowShim
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Type |= (EventType(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Pid", wireType)
}
m.Pid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowShim
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Pid |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ExitStatus", wireType)
}
m.ExitStatus = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowShim
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.ExitStatus |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipShim(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthShim
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *StateRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
@ -3179,9 +3053,9 @@ func (m *StateResponse) Unmarshal(dAtA []byte) error {
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field InitPid", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Pid", wireType)
}
m.InitPid = 0
m.Pid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowShim
@ -3191,7 +3065,7 @@ func (m *StateResponse) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
m.InitPid |= (uint32(b) & 0x7F) << shift
m.Pid |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
@ -3222,7 +3096,7 @@ func (m *StateResponse) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Processes = append(m.Processes, &containerd_v1_types2.Process{})
m.Processes = append(m.Processes, &containerd_v1_types1.Process{})
if err := m.Processes[len(m.Processes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
@ -3348,6 +3222,56 @@ func (m *ResumeRequest) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *ExitRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowShim
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ExitRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ExitRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
default:
iNdEx = preIndex
skippy, err := skipShim(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthShim
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipShim(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
@ -3458,66 +3382,63 @@ func init() {
}
var fileDescriptorShim = []byte{
// 976 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x55, 0x4f, 0x6f, 0xe3, 0x44,
0x14, 0xaf, 0x13, 0xe7, 0xdf, 0x6b, 0xdd, 0x86, 0xd1, 0xaa, 0xf2, 0x06, 0xc8, 0x76, 0xbd, 0xbb,
0xa8, 0xac, 0x84, 0xc3, 0x16, 0x81, 0x00, 0x71, 0xe9, 0x36, 0x16, 0x5a, 0x69, 0x61, 0x83, 0x1b,
0xc4, 0xde, 0x22, 0x27, 0x7e, 0x4d, 0x46, 0x38, 0xb6, 0x99, 0x19, 0xa7, 0xed, 0x8d, 0x2b, 0x1f,
0x80, 0xef, 0xc1, 0xc7, 0xd8, 0x0b, 0x12, 0x27, 0xc4, 0x09, 0xb1, 0xf9, 0x24, 0x68, 0x66, 0xec,
0xa4, 0xd9, 0xad, 0x5b, 0xc4, 0x25, 0x79, 0xef, 0xe7, 0xdf, 0xbc, 0x79, 0xff, 0x07, 0xbe, 0x98,
0x52, 0x31, 0xcb, 0xc6, 0xee, 0x24, 0x99, 0xf7, 0xc2, 0x64, 0xf2, 0x23, 0xb2, 0xde, 0x24, 0x89,
0x45, 0x40, 0x63, 0x64, 0x61, 0x2f, 0x48, 0x69, 0x8f, 0x23, 0x5b, 0xd0, 0x09, 0xf2, 0x1e, 0x9f,
0xd1, 0xb9, 0xfa, 0x71, 0x53, 0x96, 0x88, 0x84, 0xec, 0xaf, 0x89, 0xee, 0xe2, 0x89, 0x5b, 0xf0,
0x3a, 0xef, 0x4e, 0x93, 0x64, 0x1a, 0x61, 0x4f, 0xb1, 0xc6, 0xd9, 0x59, 0x0f, 0xe7, 0xa9, 0xb8,
0xd4, 0x87, 0x3a, 0x77, 0xa6, 0xc9, 0x34, 0x51, 0x62, 0x4f, 0x4a, 0x39, 0xfa, 0xd5, 0xad, 0x5e,
0x88, 0xcb, 0x14, 0xb9, 0x34, 0x39, 0x41, 0xbe, 0xfa, 0xcf, 0x4f, 0x7f, 0xf6, 0x1f, 0x4f, 0x67,
0x1c, 0x99, 0xfa, 0xd1, 0xe7, 0x9c, 0x3f, 0x0d, 0xb0, 0x4e, 0x18, 0x06, 0x02, 0x7d, 0xfc, 0x29,
0x43, 0x2e, 0xc8, 0x3e, 0x54, 0x68, 0x68, 0x1b, 0x07, 0xc6, 0x61, 0xeb, 0x69, 0x7d, 0xf9, 0xf7,
0xbd, 0xca, 0xb3, 0xbe, 0x5f, 0xa1, 0x21, 0xd9, 0x87, 0xfa, 0x38, 0x8b, 0xc3, 0x08, 0xed, 0x8a,
0xfc, 0xe6, 0xe7, 0x1a, 0xb1, 0xa1, 0xc1, 0xb2, 0x58, 0xd0, 0x39, 0xda, 0x55, 0xf5, 0xa1, 0x50,
0xc9, 0x5d, 0x68, 0xc6, 0xc9, 0x28, 0xa5, 0x8b, 0x44, 0xd8, 0xe6, 0x81, 0x71, 0xd8, 0xf4, 0x1b,
0x71, 0x32, 0x90, 0x2a, 0xe9, 0x40, 0x53, 0x20, 0x9b, 0xd3, 0x38, 0x88, 0xec, 0x9a, 0xfa, 0xb4,
0xd2, 0xc9, 0x1d, 0xa8, 0x71, 0x11, 0xd2, 0xd8, 0xae, 0x2b, 0x73, 0x5a, 0x91, 0xd7, 0x73, 0x11,
0x26, 0x99, 0xb0, 0x1b, 0xfa, 0x7a, 0xad, 0xe5, 0x38, 0x32, 0x66, 0x37, 0x57, 0x38, 0x32, 0xe6,
0x38, 0xb0, 0x5b, 0xc4, 0xc5, 0xd3, 0x24, 0xe6, 0x48, 0xda, 0x50, 0x4d, 0xf3, 0xc8, 0x2c, 0x5f,
0x8a, 0xce, 0x2e, 0xec, 0x9c, 0x8a, 0x80, 0x89, 0x3c, 0x74, 0xe7, 0x3e, 0x58, 0x7d, 0x8c, 0x70,
0x9d, 0x8b, 0xb7, 0x8f, 0x3c, 0x81, 0xdd, 0x82, 0x92, 0x9b, 0xbd, 0x07, 0xdb, 0x78, 0x41, 0xc5,
0x88, 0x8b, 0x40, 0x64, 0x3c, 0xe7, 0x82, 0x84, 0x4e, 0x15, 0xe2, 0xfc, 0x56, 0x85, 0x6d, 0xef,
0x02, 0x27, 0x85, 0xd1, 0xab, 0xb1, 0x1b, 0x65, 0xb1, 0x57, 0xae, 0x8f, 0xbd, 0x5a, 0x12, 0xbb,
0x79, 0x35, 0x76, 0xf2, 0x00, 0x2c, 0x8e, 0x11, 0x8d, 0xb3, 0x8b, 0x51, 0x14, 0x8c, 0x51, 0xa7,
0xb8, 0xe5, 0xef, 0xe4, 0xe0, 0x73, 0x89, 0x91, 0x8f, 0xc0, 0x94, 0x7d, 0xa0, 0xb2, 0xbc, 0x7d,
0x74, 0xd7, 0xdd, 0xec, 0x64, 0xd5, 0x2d, 0xee, 0xf7, 0x1c, 0x99, 0xaf, 0x68, 0x84, 0x80, 0x19,
0xb0, 0x29, 0xb7, 0x1b, 0x07, 0xd5, 0xc3, 0x96, 0xaf, 0x64, 0x99, 0x1e, 0x8c, 0x17, 0x76, 0x53,
0x41, 0x52, 0x94, 0xc8, 0xe4, 0x3c, 0xb4, 0x5b, 0xea, 0x3e, 0x29, 0x12, 0x07, 0x76, 0x26, 0x41,
0x1a, 0x8c, 0x69, 0x44, 0x05, 0x45, 0x6e, 0x83, 0x22, 0x6f, 0x60, 0xe4, 0x73, 0x68, 0xb0, 0x88,
0xce, 0xa9, 0xe0, 0xf6, 0xf6, 0x41, 0xf5, 0x70, 0xfb, 0xa8, 0xeb, 0x5e, 0x3f, 0x57, 0xae, 0xaf,
0x68, 0x7e, 0x41, 0x27, 0x8f, 0xe1, 0x9d, 0x38, 0x19, 0xc5, 0x78, 0x3e, 0x4a, 0x19, 0x5d, 0xd0,
0x08, 0xa7, 0xc8, 0xed, 0x1d, 0x95, 0xd4, 0xbd, 0x38, 0xf9, 0x16, 0xcf, 0x07, 0x2b, 0x98, 0x7c,
0x08, 0xed, 0x20, 0x4d, 0x03, 0x36, 0x4f, 0xd8, 0x28, 0x65, 0xc9, 0x19, 0x8d, 0xd0, 0xb6, 0x94,
0xa3, 0x7b, 0x05, 0x3e, 0xd0, 0xb0, 0xd3, 0x87, 0xba, 0xbe, 0x49, 0x86, 0x2d, 0x53, 0xa1, 0xe7,
0xc1, 0x57, 0xb2, 0xc4, 0x66, 0x01, 0x0b, 0x55, 0x8d, 0x4c, 0x5f, 0xc9, 0x12, 0xe3, 0xc9, 0x99,
0x2e, 0x90, 0xe9, 0x2b, 0xd9, 0x39, 0x80, 0x1d, 0x5d, 0xf7, 0xd2, 0x06, 0x7c, 0x0e, 0x30, 0x10,
0x97, 0xa5, 0xdd, 0x26, 0xdb, 0xe1, 0x9c, 0x86, 0x62, 0xa6, 0xae, 0xb2, 0x7c, 0xad, 0xc8, 0xb2,
0xcf, 0x90, 0x4e, 0x67, 0xfa, 0x36, 0xcb, 0xcf, 0x35, 0x67, 0x0f, 0x2c, 0x6f, 0x81, 0xb1, 0xe0,
0x45, 0x3f, 0xff, 0x62, 0x40, 0x4d, 0x21, 0xa5, 0x43, 0xfd, 0x69, 0x1e, 0x9e, 0xb4, 0xbf, 0x7b,
0x74, 0xbf, 0x2c, 0xed, 0xca, 0xc8, 0xf0, 0x32, 0xc5, 0x3c, 0x03, 0xb9, 0xa7, 0xd5, 0xb5, 0xa7,
0x6f, 0x4c, 0x81, 0xf9, 0xd6, 0x14, 0xe8, 0x59, 0x5b, 0x8d, 0x96, 0xf3, 0xab, 0x01, 0x56, 0x0e,
0xe4, 0xe9, 0xf9, 0x1f, 0x8b, 0x87, 0xc6, 0x54, 0x0c, 0x56, 0x8e, 0x14, 0x2a, 0xf9, 0x12, 0x5a,
0xf9, 0x76, 0x44, 0xe9, 0x8a, 0xec, 0xa8, 0xf7, 0xae, 0xed, 0xef, 0x81, 0x66, 0xf9, 0x6b, 0xba,
0xf4, 0x73, 0x10, 0x64, 0x7c, 0xe5, 0xe7, 0x1e, 0x58, 0x3e, 0xf2, 0x6c, 0x5e, 0x00, 0x8f, 0x3d,
0x68, 0xad, 0xd2, 0x41, 0x9a, 0x60, 0x7a, 0x2f, 0x9f, 0x0d, 0xdb, 0x5b, 0xa4, 0x01, 0xd5, 0x17,
0x2f, 0xbe, 0x69, 0x1b, 0x04, 0xa0, 0x7e, 0xe2, 0x7b, 0xc7, 0x43, 0xaf, 0x5d, 0x21, 0x2d, 0xa8,
0x9d, 0x0e, 0x8f, 0xfd, 0x61, 0xbb, 0x4a, 0x76, 0x01, 0xbc, 0x97, 0xde, 0xc9, 0xe8, 0xb8, 0xdf,
0xf7, 0xfa, 0x6d, 0xf3, 0xe8, 0xf7, 0x1a, 0x98, 0xa7, 0x33, 0x3a, 0x27, 0x3f, 0x40, 0x5d, 0x2f,
0x2a, 0xf2, 0xa8, 0x2c, 0xfd, 0x1b, 0x0b, 0xba, 0xf3, 0xc1, 0x6d, 0xb4, 0x3c, 0x9f, 0x1e, 0xd4,
0xd4, 0x76, 0x23, 0x0f, 0xcb, 0x0e, 0x5c, 0x5d, 0x7e, 0x9d, 0x7d, 0x57, 0xbf, 0x59, 0x6e, 0xf1,
0x66, 0xb9, 0x9e, 0x7c, 0xb3, 0xa4, 0x7f, 0x7a, 0xe3, 0x95, 0xfb, 0xb7, 0xb1, 0x34, 0xcb, 0xfd,
0x7b, 0x63, 0x71, 0x7e, 0x07, 0xa6, 0x1c, 0x0f, 0xf2, 0xa0, 0xb4, 0xeb, 0xd6, 0x4b, 0xb3, 0xf3,
0xf0, 0x66, 0x52, 0x6e, 0xf2, 0x18, 0xaa, 0x03, 0x71, 0x49, 0x9c, 0x32, 0xf2, 0x7a, 0xd8, 0x4a,
0xc3, 0x1d, 0x40, 0x5d, 0x0f, 0x51, 0x79, 0xb8, 0x1b, 0x43, 0xd6, 0x79, 0xff, 0x46, 0xda, 0xc7,
0x06, 0x19, 0xaa, 0x3a, 0x08, 0xbc, 0xb1, 0x0e, 0xeb, 0xf4, 0x3d, 0xba, 0x85, 0xb5, 0xae, 0xae,
0xea, 0xd3, 0x72, 0xab, 0x57, 0xdb, 0xb8, 0x34, 0xdc, 0xaf, 0xa1, 0xae, 0xdb, 0xbb, 0x3c, 0xdc,
0x8d, 0xf6, 0x2f, 0x33, 0xf4, 0xd4, 0x7e, 0xf5, 0xba, 0xbb, 0xf5, 0xd7, 0xeb, 0xee, 0xd6, 0xcf,
0xcb, 0xae, 0xf1, 0x6a, 0xd9, 0x35, 0xfe, 0x58, 0x76, 0x8d, 0x7f, 0x96, 0x5d, 0x63, 0x5c, 0x57,
0xcc, 0x4f, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x7d, 0x28, 0xed, 0x88, 0x67, 0x09, 0x00, 0x00,
// 918 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x55, 0xc1, 0x6f, 0xe3, 0xc4,
0x17, 0x5e, 0x27, 0xa9, 0x9b, 0xbc, 0xc4, 0xed, 0xfe, 0x46, 0xab, 0x6a, 0x36, 0x3f, 0x94, 0x0d,
0xde, 0x5d, 0x54, 0x90, 0x70, 0xd8, 0x72, 0x59, 0x38, 0xc1, 0x6e, 0x2b, 0x84, 0xb4, 0x8b, 0x82,
0x0b, 0xe2, 0x18, 0x39, 0xf1, 0x6b, 0x32, 0xc2, 0xf6, 0x98, 0x99, 0x71, 0xda, 0xde, 0x38, 0x23,
0x21, 0xfe, 0x15, 0xfe, 0x8c, 0x3d, 0x72, 0xe4, 0x84, 0xd8, 0xfc, 0x25, 0x68, 0x66, 0xec, 0xa4,
0x81, 0xb8, 0x85, 0x4b, 0xf4, 0xde, 0x97, 0x6f, 0x66, 0xde, 0x7c, 0xef, 0x9b, 0x67, 0xf8, 0x64,
0xce, 0xd4, 0xa2, 0x98, 0x06, 0x33, 0x9e, 0x8e, 0x62, 0x3e, 0xfb, 0x1e, 0xc5, 0x68, 0xc6, 0x33,
0x15, 0xb1, 0x0c, 0x45, 0x3c, 0x8a, 0x72, 0x36, 0x92, 0x28, 0x96, 0x6c, 0x86, 0x72, 0x24, 0x17,
0x2c, 0x35, 0x3f, 0x41, 0x2e, 0xb8, 0xe2, 0xe4, 0x68, 0x43, 0x0c, 0x96, 0xcf, 0x82, 0x8a, 0xd7,
0xff, 0xff, 0x9c, 0xf3, 0x79, 0x82, 0x23, 0xc3, 0x9a, 0x16, 0x17, 0x23, 0x4c, 0x73, 0x75, 0x6d,
0x17, 0xf5, 0x1f, 0xcc, 0xf9, 0x9c, 0x9b, 0x70, 0xa4, 0xa3, 0x12, 0x7d, 0x7e, 0x67, 0x15, 0xea,
0x3a, 0x47, 0x39, 0x4a, 0x79, 0x91, 0x29, 0xfb, 0x5b, 0xae, 0xfc, 0xec, 0x5f, 0xae, 0x5c, 0x83,
0x9b, 0xc8, 0xee, 0xe0, 0xff, 0xd4, 0x00, 0xef, 0xa5, 0xc0, 0x48, 0x61, 0x88, 0x3f, 0x14, 0x28,
0x15, 0x39, 0x82, 0x06, 0x8b, 0xa9, 0x33, 0x74, 0x8e, 0x3b, 0x2f, 0xdc, 0xd5, 0x1f, 0x8f, 0x1a,
0x5f, 0x9e, 0x86, 0x0d, 0x16, 0x93, 0x23, 0x70, 0xa7, 0x45, 0x16, 0x27, 0x48, 0x1b, 0xfa, 0xbf,
0xb0, 0xcc, 0x08, 0x85, 0x7d, 0x51, 0x64, 0x8a, 0xa5, 0x48, 0x9b, 0xe6, 0x8f, 0x2a, 0x25, 0x0f,
0xa1, 0x9d, 0xf1, 0x49, 0xce, 0x96, 0x5c, 0xd1, 0xd6, 0xd0, 0x39, 0x6e, 0x87, 0xfb, 0x19, 0x1f,
0xeb, 0x94, 0xf4, 0xa1, 0xad, 0x50, 0xa4, 0x2c, 0x8b, 0x12, 0xba, 0x67, 0xfe, 0x5a, 0xe7, 0xe4,
0x01, 0xec, 0x49, 0x15, 0xb3, 0x8c, 0xba, 0x66, 0x3b, 0x9b, 0xe8, 0xe3, 0xa5, 0x8a, 0x79, 0xa1,
0xe8, 0xbe, 0x3d, 0xde, 0x66, 0x25, 0x8e, 0x42, 0xd0, 0xf6, 0x1a, 0x47, 0x21, 0xc8, 0x09, 0xb8,
0x82, 0x73, 0x75, 0x21, 0x69, 0x67, 0xd8, 0x3c, 0xee, 0x9e, 0xf4, 0x83, 0xed, 0x86, 0x19, 0x61,
0x82, 0xd7, 0x5a, 0xcc, 0xb0, 0x64, 0xfa, 0x3e, 0x1c, 0x54, 0x5a, 0xc8, 0x9c, 0x67, 0x12, 0xc9,
0x7d, 0x68, 0xe6, 0xa5, 0x1a, 0x5e, 0xa8, 0x43, 0xff, 0x00, 0x7a, 0xe7, 0x2a, 0x12, 0xaa, 0x94,
0xcb, 0x7f, 0x17, 0xbc, 0x53, 0x4c, 0x70, 0xa3, 0xdf, 0x3f, 0x97, 0x3c, 0x83, 0x83, 0x8a, 0x52,
0x6e, 0xfb, 0x08, 0xba, 0x78, 0xc5, 0xd4, 0x44, 0xaa, 0x48, 0x15, 0xb2, 0xe4, 0x82, 0x86, 0xce,
0x0d, 0xe2, 0xff, 0xda, 0x84, 0xee, 0xd9, 0x15, 0xce, 0xaa, 0x4d, 0x6f, 0xea, 0xe5, 0xd4, 0xe9,
0xd5, 0xd8, 0xad, 0x57, 0xb3, 0x46, 0xaf, 0xd6, 0x96, 0x5e, 0x8f, 0xc1, 0x93, 0x98, 0xb0, 0xac,
0xb8, 0x9a, 0x24, 0xd1, 0x14, 0x6d, 0x5b, 0x3a, 0x61, 0xaf, 0x04, 0x5f, 0x69, 0x8c, 0x7c, 0x08,
0xad, 0x42, 0xa2, 0x30, 0x9d, 0xe9, 0x9e, 0x3c, 0xdc, 0x29, 0xe9, 0xb7, 0x12, 0x45, 0x68, 0x68,
0x84, 0x40, 0x2b, 0x12, 0x73, 0x49, 0xf7, 0x87, 0xcd, 0xe3, 0x4e, 0x68, 0x62, 0x2d, 0x0f, 0x66,
0x4b, 0xda, 0x36, 0x90, 0x0e, 0x35, 0x32, 0xbb, 0x8c, 0x69, 0xc7, 0x9c, 0xa7, 0x43, 0xe2, 0x43,
0x6f, 0x16, 0xe5, 0xd1, 0x94, 0x25, 0x4c, 0x31, 0x94, 0x14, 0x0c, 0x79, 0x0b, 0x23, 0xcf, 0x61,
0x5f, 0x24, 0x2c, 0x65, 0x4a, 0xd2, 0xae, 0x69, 0xf0, 0x20, 0xd8, 0xfd, 0x22, 0x83, 0xd0, 0xd0,
0xc2, 0x8a, 0x4e, 0x3e, 0x80, 0xff, 0x65, 0x7c, 0x92, 0xe1, 0xe5, 0x24, 0x17, 0x6c, 0xc9, 0x12,
0x9c, 0xa3, 0xa4, 0x3d, 0x23, 0xea, 0x61, 0xc6, 0xbf, 0xc2, 0xcb, 0xf1, 0x1a, 0x26, 0xef, 0xc3,
0xfd, 0x28, 0xcf, 0x23, 0x91, 0x72, 0x31, 0xc9, 0x05, 0xbf, 0x60, 0x09, 0x52, 0xcf, 0x14, 0x7a,
0x58, 0xe1, 0x63, 0x0b, 0xfb, 0xa7, 0xe0, 0xda, 0x93, 0xf4, 0xb5, 0xb5, 0x14, 0xf6, 0x0d, 0x85,
0x26, 0xd6, 0xd8, 0x22, 0x12, 0xb1, 0xe9, 0x51, 0x2b, 0x34, 0xb1, 0xc6, 0x24, 0xbf, 0xb0, 0x0d,
0x6a, 0x85, 0x26, 0xf6, 0x87, 0xd0, 0xb3, 0x7d, 0xaf, 0x35, 0xe0, 0x2b, 0x80, 0xb1, 0xba, 0xae,
0x75, 0x9b, 0xb6, 0xc3, 0x25, 0x8b, 0xd5, 0xc2, 0x1c, 0xe5, 0x85, 0x36, 0xd1, 0x6d, 0x5f, 0x20,
0x9b, 0x2f, 0xec, 0x69, 0x5e, 0x58, 0x66, 0xfe, 0x21, 0x78, 0x67, 0x4b, 0xcc, 0x94, 0xac, 0xfc,
0x6c, 0xfd, 0xbd, 0xb6, 0xb3, 0xff, 0xb3, 0x03, 0x5e, 0x09, 0x94, 0x25, 0xfd, 0xd7, 0x01, 0x51,
0x96, 0xd8, 0xdc, 0x94, 0xf8, 0x29, 0x74, 0x72, 0xc1, 0x67, 0x28, 0x25, 0x4a, 0xda, 0x32, 0xdd,
0x7b, 0x67, 0xa7, 0x97, 0xc6, 0x96, 0x15, 0x6e, 0xe8, 0xba, 0xbe, 0x71, 0x54, 0xc8, 0x75, 0x7d,
0x87, 0xe0, 0x85, 0x28, 0x8b, 0x74, 0x0d, 0x78, 0xfa, 0xe5, 0xb0, 0xea, 0x7d, 0x9e, 0xfc, 0xe2,
0x42, 0xeb, 0x7c, 0xc1, 0x52, 0xf2, 0x1d, 0xb8, 0xf6, 0x71, 0x93, 0xa7, 0x75, 0x4e, 0xd9, 0x1a,
0x84, 0xfd, 0xf7, 0xee, 0xa2, 0x95, 0x7a, 0x9c, 0xc1, 0x9e, 0x99, 0x08, 0xe4, 0x49, 0xdd, 0x82,
0x9b, 0x03, 0xa3, 0x7f, 0x14, 0xd8, 0x2f, 0x44, 0x50, 0x7d, 0x21, 0x82, 0x33, 0xfd, 0x85, 0xd0,
0xf5, 0xd9, 0x29, 0x51, 0x5f, 0xdf, 0xd6, 0xa0, 0xa9, 0xaf, 0xef, 0x6f, 0xc3, 0xe6, 0x6b, 0x68,
0x69, 0x4b, 0x91, 0xc7, 0x75, 0xfc, 0x1b, 0x83, 0xa6, 0xff, 0xe4, 0x76, 0x52, 0xb9, 0xe5, 0xe7,
0xd0, 0x1c, 0xab, 0x6b, 0xe2, 0xd7, 0x91, 0x37, 0x06, 0xad, 0xbd, 0xee, 0x6b, 0x70, 0xad, 0xf1,
0xea, 0xaf, 0xbb, 0x65, 0xcc, 0xfe, 0xee, 0x01, 0x6e, 0x38, 0x1f, 0x39, 0xe4, 0x1b, 0xd3, 0x04,
0x85, 0xb7, 0x36, 0x61, 0xa3, 0xdd, 0xd3, 0x3b, 0x58, 0x9b, 0xd6, 0x1a, 0xb3, 0xd5, 0xef, 0x7a,
0xd3, 0x8b, 0xb5, 0x77, 0xfd, 0x02, 0x5c, 0xeb, 0xd1, 0xfa, 0xbb, 0x6e, 0x79, 0xb8, 0x76, 0xa3,
0x97, 0xba, 0x95, 0x4c, 0xdd, 0xd6, 0x4a, 0x76, 0x97, 0xd1, 0x5e, 0xd0, 0x37, 0x6f, 0x07, 0xf7,
0x7e, 0x7f, 0x3b, 0xb8, 0xf7, 0xe3, 0x6a, 0xe0, 0xbc, 0x59, 0x0d, 0x9c, 0xdf, 0x56, 0x03, 0xe7,
0xcf, 0xd5, 0xc0, 0x99, 0xba, 0x86, 0xf9, 0xf1, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb2, 0x82,
0x40, 0x80, 0x17, 0x09, 0x00, 0x00,
}

View file

@ -4,8 +4,8 @@ package containerd.v1.services;
import "google/protobuf/empty.proto";
import "gogoproto/gogo.proto";
import "github.com/docker/containerd/api/types/process/process.proto";
import "github.com/docker/containerd/api/types/user/user.proto";
import "github.com/docker/containerd/api/types/mount/mount.proto";
import "github.com/docker/containerd/api/types/container/container.proto";
service Shim {
rpc Create(CreateRequest) returns (CreateResponse);
@ -13,10 +13,11 @@ service Shim {
rpc Delete(DeleteRequest) returns (DeleteResponse);
rpc Exec(ExecRequest) returns (ExecResponse);
rpc Pty(PtyRequest) returns (google.protobuf.Empty);
rpc Events(EventsRequest) returns (stream Event);
rpc Events(EventsRequest) returns (stream containerd.v1.types.Event);
rpc State(StateRequest) returns (StateResponse);
rpc Pause(PauseRequest) returns (google.protobuf.Empty);
rpc Resume(ResumeRequest) returns (google.protobuf.Empty);
rpc Exit(ExitRequest) returns (google.protobuf.Empty);
}
message CreateRequest {
@ -28,6 +29,7 @@ message CreateRequest {
string stdin = 6;
string stdout = 7;
string stderr = 8;
repeated containerd.v1.types.Mount rootfs = 9;
}
message CreateResponse {
@ -51,7 +53,7 @@ message ExecRequest {
string stdout = 3;
string stderr = 4;
string selinux_label = 5;
types.User user = 6;
containerd.v1.types.User user = 6;
repeated string args = 7;
repeated string env = 8;
string cwd = 9;
@ -80,34 +82,22 @@ message PtyRequest {
message EventsRequest {
}
enum EventType {
EXIT = 0;
OOM = 1;
CREATE = 2;
START = 3;
EXEC_ADDED = 4;
}
// should be moved to api/types/event maybe
message Event {
string id = 1 [(gogoproto.customname) = "ID"];
EventType type = 2;
uint32 pid = 3;
uint32 exit_status = 4;
}
message StateRequest {
}
message StateResponse {
string id = 1 [(gogoproto.customname) = "ID"];
string bundle = 2;
uint32 initPid = 3;
repeated types.Process processes = 4;
uint32 pid = 3;
repeated containerd.v1.types.Process processes = 4;
}
message PauseRequest {
}
message ResumeRequest {
}
message ExitRequest {
}

File diff suppressed because it is too large Load diff

View file

@ -3,10 +3,50 @@ syntax = "proto3";
package containerd.v1.types;
import "gogoproto/gogo.proto";
import "github.com/docker/containerd/api/types/state/state.proto";
enum Status {
CREATED = 0;
RUNNING = 1;
STOPPED = 2;
PAUSED = 3;
}
message Container {
string id = 1 [(gogoproto.customname) = "ID"];
string bundle = 2;
State state = 4;
uint32 pid = 2;
Status status = 3;
}
message Process {
uint32 pid = 1;
repeated string args = 2;
repeated string env = 3;
User user = 4;
string cwd = 5;
bool terminal = 6;
uint32 exit_status = 7;
Status status = 8;
}
message User {
uint32 uid = 1;
uint32 gid = 2;
repeated uint32 additional_gids = 3;
}
message Event {
string id = 1 [(gogoproto.customname) = "ID"];
enum EventType {
EXIT = 0;
OOM = 1;
CREATE = 2;
START = 3;
EXEC_ADDED = 4;
PAUSED = 5;
}
EventType type = 2;
uint32 pid = 3;
uint32 exit_status = 4;
}

View file

@ -472,19 +472,18 @@ func init() {
}
var fileDescriptorMount = []byte{
// 212 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x4c, 0x8e, 0xb1, 0x4a, 0x43, 0x31,
0x14, 0x86, 0x1b, 0x5b, 0x2b, 0xcd, 0x18, 0x41, 0x82, 0x43, 0x28, 0x4e, 0x5d, 0x4c, 0x10, 0x17,
0x67, 0x77, 0x97, 0xbe, 0xc1, 0xbd, 0x69, 0x8c, 0x41, 0x9a, 0x13, 0x72, 0x4f, 0x04, 0x37, 0x1f,
0xef, 0x8e, 0x8e, 0x8e, 0xde, 0x3c, 0x89, 0xdc, 0x13, 0xc5, 0x2e, 0x87, 0xff, 0xfb, 0xf9, 0xf9,
0x38, 0xfc, 0xc1, 0x07, 0x7c, 0x29, 0xbd, 0xb6, 0x70, 0x34, 0x07, 0xb0, 0xaf, 0x2e, 0x1b, 0x0b,
0x11, 0xbb, 0x10, 0x5d, 0x3e, 0x98, 0x2e, 0x05, 0x83, 0xef, 0xc9, 0x0d, 0xe6, 0x08, 0x25, 0x62,
0xbb, 0x3a, 0x65, 0x40, 0x10, 0x97, 0xff, 0x3b, 0xfd, 0x76, 0xa7, 0x69, 0x76, 0x7d, 0x7b, 0xa2,
0xf3, 0xe0, 0xc1, 0xd0, 0xb6, 0x2f, 0xcf, 0x44, 0x04, 0x94, 0x9a, 0xe3, 0xc6, 0xf1, 0xf3, 0xa7,
0x59, 0x29, 0x04, 0x5f, 0xcd, 0x02, 0xc9, 0xb6, 0x6c, 0xb7, 0xd9, 0x53, 0x16, 0x57, 0x7c, 0x3d,
0x40, 0xc9, 0xd6, 0xc9, 0x33, 0x6a, 0x7f, 0x69, 0xee, 0xb1, 0xcb, 0xde, 0xa1, 0x5c, 0xb6, 0xbe,
0x91, 0x90, 0xfc, 0x02, 0x12, 0x06, 0x88, 0x83, 0x5c, 0x6d, 0x97, 0xbb, 0xcd, 0xfe, 0x0f, 0x1f,
0xe5, 0x38, 0xa9, 0xc5, 0xd7, 0xa4, 0x16, 0x1f, 0x55, 0xb1, 0xb1, 0x2a, 0xf6, 0x59, 0x15, 0xfb,
0xae, 0x8a, 0xf5, 0x6b, 0xfa, 0xe3, 0xfe, 0x27, 0x00, 0x00, 0xff, 0xff, 0x0f, 0xcf, 0x31, 0x1e,
0x07, 0x01, 0x00, 0x00,
// 204 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x48, 0xcf, 0x2c, 0xc9,
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xc9, 0x4f, 0xce, 0x4e, 0x2d, 0xd2, 0x4f, 0xce,
0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0x4a, 0xd1, 0x4f, 0x2c, 0xc8, 0xd4, 0x2f, 0xa9, 0x2c,
0x48, 0x2d, 0xd6, 0xcf, 0xcd, 0x2f, 0xcd, 0x2b, 0x81, 0x90, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9,
0x42, 0xc2, 0x08, 0x75, 0x7a, 0x65, 0x86, 0x7a, 0x60, 0x65, 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9,
0x60, 0x79, 0x7d, 0x10, 0x0b, 0xa2, 0x54, 0x29, 0x95, 0x8b, 0xd5, 0x17, 0xa4, 0x53, 0x48, 0x88,
0x8b, 0x05, 0xa4, 0x4e, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x08, 0xcc, 0x16, 0x12, 0xe3, 0x62,
0x2b, 0xce, 0x2f, 0x2d, 0x4a, 0x4e, 0x95, 0x60, 0x02, 0x8b, 0x42, 0x79, 0x20, 0xf1, 0x92, 0xc4,
0xa2, 0xf4, 0xd4, 0x12, 0x09, 0x66, 0x88, 0x38, 0x84, 0x27, 0x24, 0xc1, 0xc5, 0x9e, 0x5f, 0x50,
0x92, 0x99, 0x9f, 0x57, 0x2c, 0xc1, 0xa2, 0xc0, 0xac, 0xc1, 0x19, 0x04, 0xe3, 0x3a, 0x49, 0x9c,
0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0x43, 0xc3, 0x23, 0x39, 0xc6, 0x13, 0x8f, 0xe4, 0x18,
0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x31, 0x89, 0x0d, 0xec, 0x0e, 0x63, 0x40, 0x00,
0x00, 0x00, 0xff, 0xff, 0xf3, 0x5c, 0x4b, 0x3a, 0xee, 0x00, 0x00, 0x00,
}

View file

@ -2,7 +2,7 @@ syntax = "proto3";
package containerd.v1.types;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
import "gogoproto/gogo.proto";
// Mount describes mounts for a container.
//

View file

@ -1,625 +0,0 @@
// Code generated by protoc-gen-gogo.
// source: github.com/docker/containerd/api/types/process/process.proto
// DO NOT EDIT!
/*
Package process is a generated protocol buffer package.
It is generated from these files:
github.com/docker/containerd/api/types/process/process.proto
It has these top-level messages:
Process
*/
package process
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import containerd_v1_types "github.com/docker/containerd/api/types/user"
import containerd_v1_types1 "github.com/docker/containerd/api/types/state"
import strings "strings"
import reflect "reflect"
import io "io"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type Process struct {
Pid uint32 `protobuf:"varint,1,opt,name=pid,proto3" json:"pid,omitempty"`
Args []string `protobuf:"bytes,2,rep,name=args" json:"args,omitempty"`
Env []string `protobuf:"bytes,3,rep,name=env" json:"env,omitempty"`
User *containerd_v1_types.User `protobuf:"bytes,4,opt,name=user" json:"user,omitempty"`
Cwd string `protobuf:"bytes,5,opt,name=cwd,proto3" json:"cwd,omitempty"`
Terminal bool `protobuf:"varint,6,opt,name=terminal,proto3" json:"terminal,omitempty"`
State containerd_v1_types1.State `protobuf:"varint,7,opt,name=state,proto3,enum=containerd.v1.types.State" json:"state,omitempty"`
ExitStatus uint32 `protobuf:"varint,8,opt,name=exit_status,json=exitStatus,proto3" json:"exit_status,omitempty"`
}
func (m *Process) Reset() { *m = Process{} }
func (*Process) ProtoMessage() {}
func (*Process) Descriptor() ([]byte, []int) { return fileDescriptorProcess, []int{0} }
func init() {
proto.RegisterType((*Process)(nil), "containerd.v1.types.Process")
}
func (m *Process) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Process) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Pid != 0 {
dAtA[i] = 0x8
i++
i = encodeVarintProcess(dAtA, i, uint64(m.Pid))
}
if len(m.Args) > 0 {
for _, s := range m.Args {
dAtA[i] = 0x12
i++
l = len(s)
for l >= 1<<7 {
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
}
dAtA[i] = uint8(l)
i++
i += copy(dAtA[i:], s)
}
}
if len(m.Env) > 0 {
for _, s := range m.Env {
dAtA[i] = 0x1a
i++
l = len(s)
for l >= 1<<7 {
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
}
dAtA[i] = uint8(l)
i++
i += copy(dAtA[i:], s)
}
}
if m.User != nil {
dAtA[i] = 0x22
i++
i = encodeVarintProcess(dAtA, i, uint64(m.User.Size()))
n1, err := m.User.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n1
}
if len(m.Cwd) > 0 {
dAtA[i] = 0x2a
i++
i = encodeVarintProcess(dAtA, i, uint64(len(m.Cwd)))
i += copy(dAtA[i:], m.Cwd)
}
if m.Terminal {
dAtA[i] = 0x30
i++
if m.Terminal {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if m.State != 0 {
dAtA[i] = 0x38
i++
i = encodeVarintProcess(dAtA, i, uint64(m.State))
}
if m.ExitStatus != 0 {
dAtA[i] = 0x40
i++
i = encodeVarintProcess(dAtA, i, uint64(m.ExitStatus))
}
return i, nil
}
func encodeFixed64Process(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
dAtA[offset+4] = uint8(v >> 32)
dAtA[offset+5] = uint8(v >> 40)
dAtA[offset+6] = uint8(v >> 48)
dAtA[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Process(dAtA []byte, offset int, v uint32) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintProcess(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
}
func (m *Process) Size() (n int) {
var l int
_ = l
if m.Pid != 0 {
n += 1 + sovProcess(uint64(m.Pid))
}
if len(m.Args) > 0 {
for _, s := range m.Args {
l = len(s)
n += 1 + l + sovProcess(uint64(l))
}
}
if len(m.Env) > 0 {
for _, s := range m.Env {
l = len(s)
n += 1 + l + sovProcess(uint64(l))
}
}
if m.User != nil {
l = m.User.Size()
n += 1 + l + sovProcess(uint64(l))
}
l = len(m.Cwd)
if l > 0 {
n += 1 + l + sovProcess(uint64(l))
}
if m.Terminal {
n += 2
}
if m.State != 0 {
n += 1 + sovProcess(uint64(m.State))
}
if m.ExitStatus != 0 {
n += 1 + sovProcess(uint64(m.ExitStatus))
}
return n
}
func sovProcess(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozProcess(x uint64) (n int) {
return sovProcess(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (this *Process) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&Process{`,
`Pid:` + fmt.Sprintf("%v", this.Pid) + `,`,
`Args:` + fmt.Sprintf("%v", this.Args) + `,`,
`Env:` + fmt.Sprintf("%v", this.Env) + `,`,
`User:` + strings.Replace(fmt.Sprintf("%v", this.User), "User", "containerd_v1_types.User", 1) + `,`,
`Cwd:` + fmt.Sprintf("%v", this.Cwd) + `,`,
`Terminal:` + fmt.Sprintf("%v", this.Terminal) + `,`,
`State:` + fmt.Sprintf("%v", this.State) + `,`,
`ExitStatus:` + fmt.Sprintf("%v", this.ExitStatus) + `,`,
`}`,
}, "")
return s
}
func valueToStringProcess(v interface{}) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("*%v", pv)
}
func (m *Process) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowProcess
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Process: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Process: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Pid", wireType)
}
m.Pid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowProcess
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Pid |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Args", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowProcess
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthProcess
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Args = append(m.Args, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Env", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowProcess
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthProcess
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Env = append(m.Env, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field User", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowProcess
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthProcess
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.User == nil {
m.User = &containerd_v1_types.User{}
}
if err := m.User.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Cwd", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowProcess
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthProcess
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Cwd = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 6:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Terminal", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowProcess
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Terminal = bool(v != 0)
case 7:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field State", wireType)
}
m.State = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowProcess
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.State |= (containerd_v1_types1.State(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 8:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ExitStatus", wireType)
}
m.ExitStatus = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowProcess
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.ExitStatus |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipProcess(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthProcess
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipProcess(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowProcess
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowProcess
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowProcess
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
iNdEx += length
if length < 0 {
return 0, ErrInvalidLengthProcess
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowProcess
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipProcess(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthProcess = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowProcess = fmt.Errorf("proto: integer overflow")
)
func init() {
proto.RegisterFile("github.com/docker/containerd/api/types/process/process.proto", fileDescriptorProcess)
}
var fileDescriptorProcess = []byte{
// 297 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x90, 0xb1, 0x4e, 0xc3, 0x30,
0x10, 0x86, 0x7b, 0x34, 0x6d, 0x83, 0x2b, 0x10, 0x32, 0x8b, 0xc9, 0x60, 0x2c, 0xa6, 0x2c, 0x38,
0x50, 0x24, 0xc4, 0xc0, 0xc4, 0x13, 0xa0, 0x54, 0xcc, 0x28, 0x75, 0xac, 0x62, 0x41, 0xe3, 0xc8,
0x76, 0x5a, 0xd8, 0x78, 0xbc, 0x8e, 0x8c, 0x8c, 0x34, 0x6f, 0xc0, 0x1b, 0x20, 0x3b, 0x52, 0x59,
0x3a, 0x74, 0x39, 0xdf, 0xfd, 0xfa, 0xee, 0xd7, 0x7f, 0x46, 0xf7, 0x73, 0xe5, 0x5e, 0x9a, 0x19,
0x17, 0x7a, 0x91, 0x95, 0x5a, 0xbc, 0x4a, 0x93, 0x09, 0x5d, 0xb9, 0x42, 0x55, 0xd2, 0x94, 0x59,
0x51, 0xab, 0xcc, 0x7d, 0xd4, 0xd2, 0x66, 0xb5, 0xd1, 0x42, 0xda, 0xed, 0xcb, 0x6b, 0xa3, 0x9d,
0xc6, 0xa7, 0xff, 0x2c, 0x5f, 0x5e, 0xf3, 0x80, 0x26, 0xb7, 0x7b, 0x5a, 0x36, 0x56, 0x9a, 0x50,
0x3a, 0xb3, 0xe4, 0x6e, 0xcf, 0x3d, 0xeb, 0x0a, 0x27, 0xbb, 0xda, 0x6d, 0x5e, 0xfc, 0x02, 0x1a,
0x3d, 0x76, 0xc1, 0xf0, 0x09, 0xea, 0xd7, 0xaa, 0x24, 0xc0, 0x20, 0x3d, 0xca, 0x7d, 0x8b, 0x31,
0x8a, 0x0a, 0x33, 0xb7, 0xe4, 0x80, 0xf5, 0xd3, 0xc3, 0x3c, 0xf4, 0x9e, 0x92, 0xd5, 0x92, 0xf4,
0x83, 0xe4, 0x5b, 0x7c, 0x89, 0x22, 0x9f, 0x85, 0x44, 0x0c, 0xd2, 0xf1, 0xe4, 0x8c, 0xef, 0xb8,
0x8c, 0x3f, 0x59, 0x69, 0xf2, 0x80, 0x79, 0x03, 0xb1, 0x2a, 0xc9, 0x80, 0x81, 0x37, 0x10, 0xab,
0x12, 0x27, 0x28, 0x76, 0xd2, 0x2c, 0x54, 0x55, 0xbc, 0x91, 0x21, 0x83, 0x34, 0xce, 0xb7, 0x33,
0xbe, 0x42, 0x83, 0x90, 0x97, 0x8c, 0x18, 0xa4, 0xc7, 0x93, 0x64, 0xa7, 0xfb, 0xd4, 0x13, 0x79,
0x07, 0xe2, 0x73, 0x34, 0x96, 0xef, 0xca, 0x3d, 0xfb, 0xa9, 0xb1, 0x24, 0x0e, 0xe7, 0x20, 0x2f,
0x4d, 0x83, 0xf2, 0x40, 0xd6, 0x1b, 0xda, 0xfb, 0xde, 0xd0, 0xde, 0x67, 0x4b, 0x61, 0xdd, 0x52,
0xf8, 0x6a, 0x29, 0xfc, 0xb4, 0x14, 0x66, 0xc3, 0xf0, 0x29, 0x37, 0x7f, 0x01, 0x00, 0x00, 0xff,
0xff, 0x19, 0xf5, 0x94, 0x44, 0xdb, 0x01, 0x00, 0x00,
}

View file

@ -1,17 +0,0 @@
syntax = "proto3";
package containerd.v1.types;
import "github.com/docker/containerd/api/types/user/user.proto";
import "github.com/docker/containerd/api/types/state/state.proto";
message Process {
uint32 pid = 1;
repeated string args = 2;
repeated string env = 3;
User user = 4;
string cwd = 5;
bool terminal = 6;
State state = 7; // only used by shim at the moment
uint32 exit_status = 8;
}

View file

@ -1,83 +0,0 @@
// Code generated by protoc-gen-gogo.
// source: github.com/docker/containerd/api/types/state/state.proto
// DO NOT EDIT!
/*
Package state is a generated protocol buffer package.
It is generated from these files:
github.com/docker/containerd/api/types/state/state.proto
It has these top-level messages:
*/
package state
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// At the moment we have same State type for Container and Process
type State int32
const (
State_UNKNOWN State = 0
State_CREATED State = 1
State_RUNNING State = 2
State_STOPPED State = 3
State_PAUSED State = 4
)
var State_name = map[int32]string{
0: "UNKNOWN",
1: "CREATED",
2: "RUNNING",
3: "STOPPED",
4: "PAUSED",
}
var State_value = map[string]int32{
"UNKNOWN": 0,
"CREATED": 1,
"RUNNING": 2,
"STOPPED": 3,
"PAUSED": 4,
}
func (x State) String() string {
return proto.EnumName(State_name, int32(x))
}
func (State) EnumDescriptor() ([]byte, []int) { return fileDescriptorState, []int{0} }
func init() {
proto.RegisterEnum("containerd.v1.types.State", State_name, State_value)
}
func init() {
proto.RegisterFile("github.com/docker/containerd/api/types/state/state.proto", fileDescriptorState)
}
var fileDescriptorState = []byte{
// 184 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xb2, 0x48, 0xcf, 0x2c, 0xc9,
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xc9, 0x4f, 0xce, 0x4e, 0x2d, 0xd2, 0x4f, 0xce,
0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0x4a, 0xd1, 0x4f, 0x2c, 0xc8, 0xd4, 0x2f, 0xa9, 0x2c,
0x48, 0x2d, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x49, 0x85, 0x90, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9,
0x42, 0xc2, 0x08, 0x75, 0x7a, 0x65, 0x86, 0x7a, 0x60, 0x65, 0x5a, 0xee, 0x5c, 0xac, 0xc1, 0x20,
0x35, 0x42, 0xdc, 0x5c, 0xec, 0xa1, 0x7e, 0xde, 0x7e, 0xfe, 0xe1, 0x7e, 0x02, 0x0c, 0x20, 0x8e,
0x73, 0x90, 0xab, 0x63, 0x88, 0xab, 0x8b, 0x00, 0x23, 0x88, 0x13, 0x14, 0xea, 0xe7, 0xe7, 0xe9,
0xe7, 0x2e, 0xc0, 0x04, 0xe2, 0x04, 0x87, 0xf8, 0x07, 0x04, 0xb8, 0xba, 0x08, 0x30, 0x0b, 0x71,
0x71, 0xb1, 0x05, 0x38, 0x86, 0x06, 0xbb, 0xba, 0x08, 0xb0, 0x38, 0x49, 0x9c, 0x78, 0x28, 0xc7,
0x70, 0xe3, 0xa1, 0x1c, 0x43, 0xc3, 0x23, 0x39, 0xc6, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92,
0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x31, 0x89, 0x0d, 0x6c, 0xbd, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff,
0xcd, 0xc9, 0x58, 0x29, 0xba, 0x00, 0x00, 0x00,
}

View file

@ -1,12 +0,0 @@
syntax = "proto3";
package containerd.v1.types;
// At the moment we have same State type for Container and Process
enum State {
UNKNOWN = 0;
CREATED = 1;
RUNNING = 2;
STOPPED = 3;
PAUSED = 4;
}

View file

@ -1,446 +0,0 @@
// Code generated by protoc-gen-gogo.
// source: github.com/docker/containerd/api/types/user/user.proto
// DO NOT EDIT!
/*
Package user is a generated protocol buffer package.
It is generated from these files:
github.com/docker/containerd/api/types/user/user.proto
It has these top-level messages:
User
*/
package user
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import strings "strings"
import reflect "reflect"
import io "io"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type User struct {
Uid uint32 `protobuf:"varint,1,opt,name=uid,proto3" json:"uid,omitempty"`
Gid uint32 `protobuf:"varint,2,opt,name=gid,proto3" json:"gid,omitempty"`
AdditionalGids []uint32 `protobuf:"varint,3,rep,packed,name=additional_gids,json=additionalGids" json:"additional_gids,omitempty"`
}
func (m *User) Reset() { *m = User{} }
func (*User) ProtoMessage() {}
func (*User) Descriptor() ([]byte, []int) { return fileDescriptorUser, []int{0} }
func init() {
proto.RegisterType((*User)(nil), "containerd.v1.types.User")
}
func (m *User) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *User) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Uid != 0 {
dAtA[i] = 0x8
i++
i = encodeVarintUser(dAtA, i, uint64(m.Uid))
}
if m.Gid != 0 {
dAtA[i] = 0x10
i++
i = encodeVarintUser(dAtA, i, uint64(m.Gid))
}
if len(m.AdditionalGids) > 0 {
dAtA2 := make([]byte, len(m.AdditionalGids)*10)
var j1 int
for _, num := range m.AdditionalGids {
for num >= 1<<7 {
dAtA2[j1] = uint8(uint64(num)&0x7f | 0x80)
num >>= 7
j1++
}
dAtA2[j1] = uint8(num)
j1++
}
dAtA[i] = 0x1a
i++
i = encodeVarintUser(dAtA, i, uint64(j1))
i += copy(dAtA[i:], dAtA2[:j1])
}
return i, nil
}
func encodeFixed64User(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
dAtA[offset+4] = uint8(v >> 32)
dAtA[offset+5] = uint8(v >> 40)
dAtA[offset+6] = uint8(v >> 48)
dAtA[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32User(dAtA []byte, offset int, v uint32) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintUser(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
}
func (m *User) Size() (n int) {
var l int
_ = l
if m.Uid != 0 {
n += 1 + sovUser(uint64(m.Uid))
}
if m.Gid != 0 {
n += 1 + sovUser(uint64(m.Gid))
}
if len(m.AdditionalGids) > 0 {
l = 0
for _, e := range m.AdditionalGids {
l += sovUser(uint64(e))
}
n += 1 + sovUser(uint64(l)) + l
}
return n
}
func sovUser(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozUser(x uint64) (n int) {
return sovUser(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (this *User) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&User{`,
`Uid:` + fmt.Sprintf("%v", this.Uid) + `,`,
`Gid:` + fmt.Sprintf("%v", this.Gid) + `,`,
`AdditionalGids:` + fmt.Sprintf("%v", this.AdditionalGids) + `,`,
`}`,
}, "")
return s
}
func valueToStringUser(v interface{}) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("*%v", pv)
}
func (m *User) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: User: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: User: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Uid", wireType)
}
m.Uid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Uid |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Gid", wireType)
}
m.Gid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Gid |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType == 2 {
var packedLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
packedLen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if packedLen < 0 {
return ErrInvalidLengthUser
}
postIndex := iNdEx + packedLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
for iNdEx < postIndex {
var v uint32
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.AdditionalGids = append(m.AdditionalGids, v)
}
} else if wireType == 0 {
var v uint32
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowUser
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.AdditionalGids = append(m.AdditionalGids, v)
} else {
return fmt.Errorf("proto: wrong wireType = %d for field AdditionalGids", wireType)
}
default:
iNdEx = preIndex
skippy, err := skipUser(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthUser
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipUser(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowUser
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowUser
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowUser
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
iNdEx += length
if length < 0 {
return 0, ErrInvalidLengthUser
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowUser
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipUser(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthUser = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowUser = fmt.Errorf("proto: integer overflow")
)
func init() {
proto.RegisterFile("github.com/docker/containerd/api/types/user/user.proto", fileDescriptorUser)
}
var fileDescriptorUser = []byte{
// 188 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x32, 0x4b, 0xcf, 0x2c, 0xc9,
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xc9, 0x4f, 0xce, 0x4e, 0x2d, 0xd2, 0x4f, 0xce,
0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0x4a, 0xd1, 0x4f, 0x2c, 0xc8, 0xd4, 0x2f, 0xa9, 0x2c,
0x48, 0x2d, 0xd6, 0x2f, 0x2d, 0x4e, 0x2d, 0x02, 0x13, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42,
0xc2, 0x08, 0x55, 0x7a, 0x65, 0x86, 0x7a, 0x60, 0x45, 0x4a, 0xc1, 0x5c, 0x2c, 0xa1, 0xc5, 0xa9,
0x45, 0x42, 0x02, 0x5c, 0xcc, 0xa5, 0x99, 0x29, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xbc, 0x41, 0x20,
0x26, 0x48, 0x24, 0x3d, 0x33, 0x45, 0x82, 0x09, 0x22, 0x92, 0x9e, 0x99, 0x22, 0xa4, 0xce, 0xc5,
0x9f, 0x98, 0x92, 0x92, 0x59, 0x92, 0x99, 0x9f, 0x97, 0x98, 0x13, 0x9f, 0x9e, 0x99, 0x52, 0x2c,
0xc1, 0xac, 0xc0, 0xac, 0xc1, 0x1b, 0xc4, 0x87, 0x10, 0x76, 0xcf, 0x4c, 0x29, 0x76, 0x92, 0x38,
0xf1, 0x50, 0x8e, 0xe1, 0xc6, 0x43, 0x39, 0x86, 0x86, 0x47, 0x72, 0x8c, 0x27, 0x1e, 0xc9, 0x31,
0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0x63, 0x12, 0x1b, 0xd8, 0x29, 0xc6, 0x80, 0x00,
0x00, 0x00, 0xff, 0xff, 0x39, 0x97, 0xe1, 0xe0, 0xc4, 0x00, 0x00, 0x00,
}

View file

@ -1,9 +0,0 @@
syntax = "proto3";
package containerd.v1.types;
message User {
uint32 uid = 1;
uint32 gid = 2;
repeated uint32 additional_gids = 3;
}

View file

@ -1,70 +0,0 @@
package bundle
import (
"encoding/json"
"os"
"path/filepath"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
const configName = "config.json"
func New(path string, s *specs.Spec) (*Bundle, error) {
if err := os.Mkdir(path, 0700); err != nil {
return nil, err
}
b := &Bundle{
Path: path,
}
if err := os.Mkdir(filepath.Join(path, "rootfs"), 0700); err != nil {
b.Delete()
return nil, err
}
f, err := os.Create(filepath.Join(path, configName))
if err != nil {
b.Delete()
return nil, err
}
err = json.NewEncoder(f).Encode(s)
f.Close()
if err != nil {
b.Delete()
return nil, err
}
return b, nil
}
func Load(path string) (*Bundle, error) {
fi, err := os.Stat(path)
if err != nil {
return nil, errors.Wrapf(err, "failed to access %q", path)
}
if !fi.IsDir() {
return nil, errors.Errorf("%q is not a directory", path)
}
return &Bundle{
Path: path,
}, nil
}
type Bundle struct {
Path string
}
func (b *Bundle) Config() (*specs.Spec, error) {
var s specs.Spec
f, err := os.Open(filepath.Join(b.Path, configName))
if err != nil {
return nil, err
}
err = json.NewDecoder(f).Decode(&s)
f.Close()
return &s, err
}
func (b *Bundle) Delete() error {
return os.RemoveAll(b.Path)
}

View file

@ -2,6 +2,7 @@ package main
import (
"fmt"
"net"
"os"
"os/signal"
"strings"
@ -52,6 +53,9 @@ func main() {
if err != nil {
return err
}
if err := setupRoot(); err != nil {
return err
}
var (
server = grpc.NewServer()
sv = shim.New()
@ -84,7 +88,7 @@ func setupSignals() (chan os.Signal, error) {
// serve serves the grpc API over a unix socket at the provided path
// this function does not block
func serve(server *grpc.Server, path string) error {
l, err := utils.CreateUnixSocket(path)
l, err := net.FileListener(os.NewFile(3, "socket"))
if err != nil {
return err
}
@ -126,3 +130,8 @@ func handleSignals(signals chan os.Signal, server *grpc.Server, service *shim.Se
}
return nil
}
// setupRoot sets up the root as the shim is started in its own mount namespace
func setupRoot() error {
return syscall.Mount("", "/", "", syscall.MS_SLAVE|syscall.MS_REC, "")
}

View file

@ -3,16 +3,12 @@ package main
import (
_ "expvar"
"fmt"
"net"
"net/http"
_ "net/http/pprof"
"net/url"
"os"
"os/signal"
"runtime"
"strconv"
"strings"
"syscall"
"time"
gocontext "golang.org/x/net/context"
"google.golang.org/grpc"
@ -20,17 +16,13 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/containerd"
api "github.com/docker/containerd/api/services/execution"
"github.com/docker/containerd/events"
_ "github.com/docker/containerd/linux"
"github.com/docker/containerd/log"
"github.com/docker/containerd/supervisor"
"github.com/docker/containerd/services/execution"
"github.com/docker/containerd/utils"
metrics "github.com/docker/go-metrics"
"github.com/pkg/errors"
"github.com/urfave/cli"
natsd "github.com/nats-io/gnatsd/server"
"github.com/nats-io/go-nats"
stand "github.com/nats-io/nats-streaming-server/server"
)
const usage = `
@ -43,10 +35,7 @@ const usage = `
high performance container runtime
`
const (
StanClusterID = "containerd"
stanClientID = "containerd"
)
var global = log.WithModule(gocontext.Background(), "containerd")
func main() {
app := cli.NewApp()
@ -83,59 +72,120 @@ func main() {
Usage: "tcp address to serve metrics on",
Value: "127.0.0.1:7897",
},
cli.StringFlag{
Name: "events-address, e",
Usage: "nats address to serve events on",
Value: nats.DefaultURL,
},
}
app.Before = func(context *cli.Context) error {
app.Before = before
app.Action = func(context *cli.Context) error {
start := time.Now()
// start the signal handler as soon as we can to make sure that
// we don't miss any signals during boot
signals := make(chan os.Signal, 2048)
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT, syscall.SIGUSR1)
log.G(global).Info("starting containerd boot...")
runtimes, err := loadRuntimes(context)
if err != nil {
return err
}
supervisor, err := containerd.NewSupervisor(log.WithModule(global, "execution"), runtimes)
if err != nil {
return err
}
// start debug and metrics APIs
if err := serveDebugAPI(context); err != nil {
return err
}
serveMetricsAPI(context)
// start the GRPC api with the execution service registered
server := newGRPCServer(execution.New(supervisor))
if err := serveGRPC(context, server); err != nil {
return err
}
log.G(global).Infof("containerd successfully booted in %fs", time.Now().Sub(start).Seconds())
return handleSignals(signals, server)
}
if err := app.Run(os.Args); err != nil {
fmt.Fprintf(os.Stderr, "containerd: %s\n", err)
os.Exit(1)
}
}
func before(context *cli.Context) error {
if context.GlobalBool("debug") {
logrus.SetLevel(logrus.DebugLevel)
}
if logLevel := context.GlobalString("log-level"); logLevel != "" {
lvl, err := logrus.ParseLevel(logLevel)
if l := context.GlobalString("log-level"); l != "" {
lvl, err := logrus.ParseLevel(l)
if err != nil {
lvl = logrus.InfoLevel
fmt.Fprintf(os.Stderr, "Unable to parse logging level: %s\n, and being defaulted to info", logLevel)
fmt.Fprintf(os.Stderr, "Unable to parse logging level: %s\n, and being defaulted to info", l)
}
logrus.SetLevel(lvl)
}
return nil
}
app.Action = func(context *cli.Context) error {
signals := make(chan os.Signal, 2048)
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT, syscall.SIGUSR1)
ctx := log.WithModule(gocontext.Background(), "containerd")
if address := context.GlobalString("metrics-address"); address != "" {
log.G(ctx).WithField("metrics-address", address).Info("listening and serving metrics")
go serveMetrics(ctx, address)
func serveMetricsAPI(context *cli.Context) {
if addr := context.GlobalString("metrics-address"); addr != "" {
log.G(global).WithField("metrics", addr).Info("starting metrics API...")
h := newMetricsHandler()
go func() {
if err := http.ListenAndServe(addr, h); err != nil {
log.G(global).WithError(err).Fatal("serve metrics API")
}
}()
}
}
ea := context.GlobalString("events-address")
log.G(ctx).WithField("events-address", ea).Info("starting nats-streaming-server")
s, err := startNATSServer(ea)
if err != nil {
return nil
func newMetricsHandler() http.Handler {
m := http.NewServeMux()
m.Handle("/metrics", metrics.Handler())
return m
}
defer s.Shutdown()
debugPath := context.GlobalString("debug-socket")
if debugPath == "" {
func serveDebugAPI(context *cli.Context) error {
path := context.GlobalString("debug-socket")
if path == "" {
return errors.New("--debug-socket path cannot be empty")
}
d, err := utils.CreateUnixSocket(debugPath)
l, err := utils.CreateUnixSocket(path)
if err != nil {
return err
}
log.G(global).WithField("debug", path).Info("starting debug API...")
go func() {
defer l.Close()
// pprof and expvars are imported and automatically register their endpoints
// under /debug
if err := http.Serve(l, nil); err != nil {
log.G(global).WithError(err).Fatal("serve debug API")
}
}()
return nil
}
//publish profiling and debug socket.
log.G(ctx).WithField("socket", debugPath).Info("starting profiler handlers")
log.G(ctx).WithFields(logrus.Fields{"expvars": "/debug/vars", "socket": debugPath}).Debug("serving expvars requests")
log.G(ctx).WithFields(logrus.Fields{"pprof": "/debug/pprof", "socket": debugPath}).Debug("serving pprof requests")
go serveProfiler(ctx, d)
func loadRuntimes(context *cli.Context) (map[string]containerd.Runtime, error) {
var (
root = context.GlobalString("root")
o = make(map[string]containerd.Runtime)
)
for _, name := range containerd.Runtimes() {
r, err := containerd.NewRuntime(name, root)
if err != nil {
return nil, err
}
o[name] = r
log.G(global).WithField("runtime", name).Info("load runtime")
}
return o, nil
}
func newGRPCServer(service api.ContainerServiceServer) *grpc.Server {
s := grpc.NewServer(grpc.UnaryInterceptor(interceptor))
api.RegisterContainerServiceServer(s, service)
return s
}
func serveGRPC(context *cli.Context, server *grpc.Server) error {
path := context.GlobalString("socket")
if path == "" {
return errors.New("--socket path cannot be empty")
@ -144,129 +194,38 @@ func main() {
if err != nil {
return err
}
// Get events publisher
natsPoster, err := events.NewNATSPoster(StanClusterID, stanClientID)
if err != nil {
return err
go func() {
defer l.Close()
if err := server.Serve(l); err != nil {
log.G(global).WithError(err).Fatal("serve GRPC")
}
execCtx := log.WithModule(ctx, "execution")
execCtx = events.WithPoster(execCtx, natsPoster)
execService, err := supervisor.New(execCtx, context.GlobalString("root"))
if err != nil {
return err
}()
return nil
}
// Intercept the GRPC call in order to populate the correct module path
interceptor := func(ctx gocontext.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
func interceptor(ctx gocontext.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (interface{}, error) {
ctx = log.WithModule(ctx, "containerd")
switch info.Server.(type) {
case api.ExecutionServiceServer:
ctx = log.WithModule(ctx, "execution")
ctx = events.WithPoster(ctx, natsPoster)
case api.ContainerServiceServer:
ctx = log.WithModule(global, "execution")
default:
fmt.Printf("Unknown type: %#v\n", info.Server)
fmt.Printf("unknown GRPC server type: %#v\n", info.Server)
}
return handler(ctx, req)
return handler(global, req)
}
server := grpc.NewServer(grpc.UnaryInterceptor(interceptor))
api.RegisterExecutionServiceServer(server, execService)
log.G(ctx).WithField("socket", l.Addr()).Info("start serving GRPC API")
go serveGRPC(ctx, server, l)
func handleSignals(signals chan os.Signal, server *grpc.Server) error {
for s := range signals {
log.G(global).WithField("signal", s).Debug("received signal")
switch s {
case syscall.SIGUSR1:
dumpStacks(ctx)
default:
log.G(ctx).WithField("signal", s).Info("stopping GRPC server")
server.Stop()
return nil
}
}
return nil
}
if err := app.Run(os.Args); err != nil {
fmt.Fprintf(os.Stderr, "containerd: %s\n", err)
os.Exit(1)
}
}
func serveMetrics(ctx gocontext.Context, address string) {
m := http.NewServeMux()
m.Handle("/metrics", metrics.Handler())
if err := http.ListenAndServe(address, m); err != nil {
log.G(ctx).WithError(err).Fatal("metrics server failure")
}
}
func serveGRPC(ctx gocontext.Context, server *grpc.Server, l net.Listener) {
defer l.Close()
if err := server.Serve(l); err != nil {
log.G(ctx).WithError(err).Fatal("GRPC server failure")
}
}
func serveProfiler(ctx gocontext.Context, l net.Listener) {
defer l.Close()
if err := http.Serve(l, nil); err != nil {
log.G(ctx).WithError(err).Fatal("profiler server failure")
}
}
// DumpStacks dumps the runtime stack.
func dumpStacks(ctx gocontext.Context) {
var (
buf []byte
stackSize int
)
bufferLen := 16384
for stackSize == len(buf) {
buf = make([]byte, bufferLen)
stackSize = runtime.Stack(buf, true)
bufferLen *= 2
}
buf = buf[:stackSize]
log.G(ctx).Infof("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf)
}
func startNATSServer(address string) (s *stand.StanServer, err error) {
defer func() {
if r := recover(); r != nil {
s = nil
if _, ok := r.(error); !ok {
err = fmt.Errorf("failed to start NATS server: %v", r)
} else {
err = r.(error)
}
}
}()
so, no, err := getServerOptions(address)
if err != nil {
return nil, err
}
s = stand.RunServerWithOpts(so, no)
return s, err
}
func getServerOptions(address string) (*stand.Options, *natsd.Options, error) {
url, err := url.Parse(address)
if err != nil {
return nil, nil, errors.Wrapf(err, "failed to parse address url %q", address)
}
no := stand.DefaultNatsServerOptions
parts := strings.Split(url.Host, ":")
if len(parts) == 2 {
no.Port, err = strconv.Atoi(parts[1])
} else {
no.Port = nats.DefaultPort
}
no.Host = parts[0]
so := stand.GetDefaultOptions()
so.ID = StanClusterID
return so, &no, nil
}

View file

@ -10,43 +10,20 @@ import (
var deleteCommand = cli.Command{
Name: "delete",
Usage: "delete a process from containerd store",
Usage: "delete an existing container",
ArgsUsage: "CONTAINER",
Flags: []cli.Flag{
cli.StringFlag{
Name: "pid, p",
Usage: "process id to be deleted",
},
},
Action: func(context *cli.Context) error {
executionService, err := getExecutionService(context)
containers, err := getExecutionService(context)
if err != nil {
return err
}
id := context.Args().First()
if id == "" {
return errors.New("container id must be provided")
return errors.New(" id must be provided")
}
pid := uint32(context.Int64("pid"))
if pid != 0 {
_, err = executionService.DeleteProcess(gocontext.Background(), &execution.DeleteProcessRequest{
ContainerID: id,
Pid: pid,
})
if err != nil {
return err
}
return nil
}
if _, err := executionService.DeleteContainer(gocontext.Background(), &execution.DeleteContainerRequest{
_, err = containers.Delete(gocontext.Background(), &execution.DeleteRequest{
ID: id,
}); err != nil {
})
return err
}
return nil
},
}

View file

@ -1,61 +1,47 @@
package main
import (
"bytes"
"encoding/json"
gocontext "context"
"fmt"
"os"
"text/tabwriter"
"github.com/nats-io/go-nats"
"github.com/docker/containerd/api/services/execution"
"github.com/urfave/cli"
)
var eventsCommand = cli.Command{
Name: "events",
Usage: "display containerd events",
Flags: []cli.Flag{
cli.StringFlag{
Name: "subject, s",
Usage: "subjects filter",
Value: "containerd.>",
},
},
Action: func(context *cli.Context) error {
nc, err := nats.Connect(nats.DefaultURL)
containers, err := getExecutionService(context)
if err != nil {
return err
}
nec, err := nats.NewEncodedConn(nc, nats.JSON_ENCODER)
if err != nil {
nc.Close()
return err
}
defer nec.Close()
evCh := make(chan *nats.Msg, 64)
sub, err := nec.Subscribe(context.String("subject"), func(e *nats.Msg) {
evCh <- e
})
events, err := containers.Events(gocontext.Background(), &execution.EventsRequest{})
if err != nil {
return err
}
defer sub.Unsubscribe()
w := tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0)
fmt.Fprintln(w, "TYPE\tID\tPID\tEXIT_STATUS")
for {
e, more := <-evCh
if !more {
break
}
var prettyJSON bytes.Buffer
err := json.Indent(&prettyJSON, e.Data, "", "\t")
e, err := events.Recv()
if err != nil {
fmt.Println(string(e.Data))
} else {
fmt.Println(prettyJSON.String())
return err
}
if _, err := fmt.Fprintf(w,
"%s\t%s\t%d\t%d\n",
e.Type.String(),
e.ID,
e.Pid,
e.ExitStatus,
); err != nil {
return err
}
if err := w.Flush(); err != nil {
return err
}
}
return nil
},
}

View file

@ -1,87 +0,0 @@
package main
import (
"os"
"path/filepath"
"time"
gocontext "context"
"github.com/docker/containerd/api/services/execution"
"github.com/docker/containerd/api/types/process"
"github.com/urfave/cli"
)
var execCommand = cli.Command{
Name: "exec",
Usage: "exec a new process in a running container",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id, i",
Usage: "target container id",
},
cli.StringFlag{
Name: "cwd, c",
Usage: "current working directory for the process",
},
cli.BoolFlag{
Name: "tty, t",
Usage: "create a terminal for the process",
},
cli.StringSliceFlag{
Name: "env, e",
Value: &cli.StringSlice{},
Usage: "environment variables for the process",
},
},
Action: func(context *cli.Context) error {
executionService, err := getExecutionService(context)
if err != nil {
return err
}
tmpDir, err := getTempDir(time.Now().Format("2006-02-01_15:04:05"))
if err != nil {
return err
}
defer os.RemoveAll(tmpDir)
id := context.String("id")
sOpts := &execution.StartProcessRequest{
ContainerID: id,
Process: &process.Process{
Cwd: context.String("cwd"),
Terminal: context.Bool("tty"),
Args: context.Args(),
Env: context.StringSlice("env"),
},
Stdin: filepath.Join(tmpDir, "stdin"),
Stdout: filepath.Join(tmpDir, "stdout"),
Stderr: filepath.Join(tmpDir, "stderr"),
Console: context.Bool("tty"),
}
fwg, err := prepareStdio(sOpts.Stdin, sOpts.Stdout, sOpts.Stderr, sOpts.Console)
if err != nil {
return err
}
sr, err := executionService.StartProcess(gocontext.Background(), sOpts)
if err != nil {
return err
}
_, err = executionService.DeleteProcess(gocontext.Background(), &execution.DeleteProcessRequest{
ContainerID: id,
Pid: sr.Process.Pid,
})
if err != nil {
return err
}
// Ensure we read all io
fwg.Wait()
return nil
},
}

View file

@ -1,42 +0,0 @@
package main
import (
gocontext "context"
"errors"
"github.com/davecgh/go-spew/spew"
"github.com/docker/containerd/api/services/execution"
"github.com/urfave/cli"
)
var inspectCommand = cli.Command{
Name: "inspect",
Usage: "inspect a container",
ArgsUsage: "CONTAINER",
Action: func(context *cli.Context) error {
executionService, err := getExecutionService(context)
if err != nil {
return err
}
id := context.Args().First()
if id == "" {
return errors.New("container id must be provided")
}
getResponse, err := executionService.GetContainer(gocontext.Background(),
&execution.GetContainerRequest{ID: id})
if err != nil {
return err
}
listProcResponse, err := executionService.ListProcesses(gocontext.Background(),
&execution.ListProcessesRequest{ContainerID: id})
if err != nil {
return err
}
dumper := spew.NewDefaultConfig()
dumper.Indent = "\t"
dumper.DisableMethods = true
dumper.DisablePointerAddresses = true
dumper.Dump(getResponse, listProcResponse)
return nil
},
}

View file

@ -3,6 +3,8 @@ package main
import (
gocontext "context"
"fmt"
"os"
"text/tabwriter"
"github.com/docker/containerd/api/services/execution"
"github.com/urfave/cli"
@ -12,29 +14,27 @@ var listCommand = cli.Command{
Name: "list",
Usage: "list containers",
Action: func(context *cli.Context) error {
executionService, err := getExecutionService(context)
containers, err := getExecutionService(context)
if err != nil {
return err
}
listResponse, err := executionService.ListContainers(gocontext.Background(), &execution.ListContainersRequest{
Owner: []string{},
})
response, err := containers.List(gocontext.Background(), &execution.ListRequest{})
if err != nil {
return err
}
fmt.Println("ID\tSTATUS\tPROCS\tBUNDLE")
for _, c := range listResponse.Containers {
listProcResponse, err := executionService.ListProcesses(gocontext.Background(),
&execution.ListProcessesRequest{ContainerID: c.ID})
if err != nil {
return err
}
fmt.Printf("%s\t%s\t%d\t%s\n",
w := tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0)
fmt.Fprintln(w, "ID\tPID\tSTATUS")
for _, c := range response.Containers {
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n",
c.ID,
c.State,
len(listProcResponse.Processes),
c.Bundle,
)
c.Pid,
c.Status.String(),
); err != nil {
return err
}
if err := w.Flush(); err != nil {
return err
}
}
return nil
},

View file

@ -35,11 +35,9 @@ containerd client
}
app.Commands = []cli.Command{
runCommand,
execCommand,
eventsCommand,
deleteCommand,
listCommand,
inspectCommand,
shimCommand,
pprofCommand,
}

View file

@ -3,148 +3,232 @@ package main
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"time"
gocontext "context"
"runtime"
"github.com/crosbymichael/console"
"github.com/docker/containerd/api/services/execution"
execEvents "github.com/docker/containerd/execution"
"github.com/nats-io/go-nats"
"github.com/nats-io/go-nats-streaming"
"github.com/pkg/errors"
"github.com/docker/containerd/api/types/mount"
protobuf "github.com/gogo/protobuf/types"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/urfave/cli"
)
var rwm = "rwm"
func spec(id string, args []string, tty bool) *specs.Spec {
return &specs.Spec{
Version: specs.Version,
Platform: specs.Platform{
OS: runtime.GOOS,
Arch: runtime.GOARCH,
},
Root: specs.Root{
Path: "rootfs",
Readonly: true,
},
Process: specs.Process{
Args: args,
Env: []string{
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
},
Terminal: tty,
Cwd: "/",
NoNewPrivileges: true,
},
Mounts: []specs.Mount{
{
Destination: "/proc",
Type: "proc",
Source: "proc",
},
{
Destination: "/dev",
Type: "tmpfs",
Source: "tmpfs",
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
},
{
Destination: "/dev/pts",
Type: "devpts",
Source: "devpts",
Options: []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
},
{
Destination: "/dev/shm",
Type: "tmpfs",
Source: "shm",
Options: []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"},
},
{
Destination: "/dev/mqueue",
Type: "mqueue",
Source: "mqueue",
Options: []string{"nosuid", "noexec", "nodev"},
},
{
Destination: "/sys",
Type: "sysfs",
Source: "sysfs",
Options: []string{"nosuid", "noexec", "nodev"},
},
{
Destination: "/run",
Type: "tmpfs",
Source: "tmpfs",
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
},
{
Destination: "/etc/resolv.conf",
Type: "bind",
Source: "/etc/resolv.conf",
Options: []string{"rbind", "ro"},
},
{
Destination: "/etc/hosts",
Type: "bind",
Source: "/etc/hosts",
Options: []string{"rbind", "ro"},
},
{
Destination: "/etc/localtime",
Type: "bind",
Source: "/etc/localtime",
Options: []string{"rbind", "ro"},
},
},
Hostname: id,
Linux: &specs.Linux{
Resources: &specs.LinuxResources{
Devices: []specs.LinuxDeviceCgroup{
{
Allow: false,
Access: &rwm,
},
},
},
Namespaces: []specs.LinuxNamespace{
{
Type: "pid",
},
{
Type: "ipc",
},
{
Type: "uts",
},
{
Type: "mount",
},
{
Type: "network",
},
},
},
}
}
var runCommand = cli.Command{
Name: "run",
Usage: "run a container",
Flags: []cli.Flag{
cli.StringFlag{
Name: "bundle, b",
Usage: "path to the container's bundle",
Name: "id",
Usage: "id of the container",
},
cli.BoolFlag{
Name: "tty,t",
Usage: "allocate a TTY for the container",
},
cli.StringFlag{
Name: "rootfs,r",
Usage: "path to the container's root filesystem",
},
},
Action: func(context *cli.Context) error {
id := context.Args().First()
id := context.String("id")
if id == "" {
return fmt.Errorf("container id must be provided")
}
executionService, err := getExecutionService(context)
containers, err := getExecutionService(context)
if err != nil {
return err
}
// setup our event subscriber
sc, err := stan.Connect("containerd", "ctr", stan.ConnectWait(5*time.Second))
if err != nil {
return err
}
defer sc.Close()
evCh := make(chan *execEvents.ContainerEvent, 64)
sub, err := sc.Subscribe(fmt.Sprintf("containers.%s", id), func(m *stan.Msg) {
var e execEvents.ContainerEvent
err := json.Unmarshal(m.Data, &e)
if err != nil {
fmt.Printf("failed to unmarshal event: %v", err)
return
}
evCh <- &e
})
if err != nil {
return err
}
defer sub.Unsubscribe()
tmpDir, err := getTempDir(id)
if err != nil {
return err
}
defer os.RemoveAll(tmpDir)
bundle, err := filepath.Abs(context.String("bundle"))
events, err := containers.Events(gocontext.Background(), &execution.EventsRequest{})
if err != nil {
return err
}
crOpts := &execution.CreateContainerRequest{
// for ctr right now just do a bind mount
rootfs := []*mount.Mount{
{
Type: "bind",
Source: context.String("rootfs"),
Options: []string{
"rw",
"rbind",
},
},
}
s := spec(id, []string(context.Args()), context.Bool("tty"))
data, err := json.Marshal(s)
if err != nil {
return err
}
create := &execution.CreateRequest{
ID: id,
BundlePath: bundle,
Console: context.Bool("tty"),
Spec: &protobuf.Any{
TypeUrl: specs.Version,
Value: data,
},
Rootfs: rootfs,
Runtime: "linux",
Terminal: context.Bool("tty"),
Stdin: filepath.Join(tmpDir, "stdin"),
Stdout: filepath.Join(tmpDir, "stdout"),
Stderr: filepath.Join(tmpDir, "stderr"),
}
if crOpts.Console {
if create.Terminal {
con := console.Current()
defer con.Reset()
if err := con.SetRaw(); err != nil {
return err
}
}
fwg, err := prepareStdio(crOpts.Stdin, crOpts.Stdout, crOpts.Stderr, crOpts.Console)
fwg, err := prepareStdio(create.Stdin, create.Stdout, create.Stderr, create.Terminal)
if err != nil {
return err
}
cr, err := executionService.CreateContainer(gocontext.Background(), crOpts)
response, err := containers.Create(gocontext.Background(), create)
if err != nil {
return errors.Wrap(err, "CreateContainer RPC failed")
return err
}
if _, err := executionService.StartContainer(gocontext.Background(), &execution.StartContainerRequest{
ID: cr.Container.ID,
if _, err := containers.Start(gocontext.Background(), &execution.StartRequest{
ID: response.ID,
}); err != nil {
return errors.Wrap(err, "StartContainer RPC failed")
return err
}
var ec uint32
eventLoop:
for {
select {
case e, more := <-evCh:
if !more {
break eventLoop
status, err := waitContainer(events, response)
if err != nil {
return err
}
if e.Type != "exit" {
continue
}
if e.ID == cr.Container.ID && e.Pid == cr.InitProcess.Pid {
ec = e.ExitStatus
break eventLoop
}
case <-time.After(1 * time.Second):
if sc.NatsConn().Status() != nats.CONNECTED {
break eventLoop
}
}
}
if _, err := executionService.DeleteContainer(gocontext.Background(), &execution.DeleteContainerRequest{
ID: cr.Container.ID,
if _, err := containers.Delete(gocontext.Background(), &execution.DeleteRequest{
ID: response.ID,
}); err != nil {
return errors.Wrap(err, "DeleteContainer RPC failed")
return err
}
// Ensure we read all io
fwg.Wait()
if ec != 0 {
return cli.NewExitError("", int(ec))
if status != 0 {
return cli.NewExitError("", int(status))
}
return nil
},
}

View file

@ -15,6 +15,7 @@ import (
gocontext "context"
"github.com/docker/containerd/api/services/execution"
"github.com/docker/containerd/api/types/container"
"github.com/pkg/errors"
"github.com/tonistiigi/fifo"
"github.com/urfave/cli"
@ -103,12 +104,12 @@ func getGRPCConnection(context *cli.Context) (*grpc.ClientConn, error) {
return grpcConn, nil
}
func getExecutionService(context *cli.Context) (execution.ExecutionServiceClient, error) {
func getExecutionService(context *cli.Context) (execution.ContainerServiceClient, error) {
conn, err := getGRPCConnection(context)
if err != nil {
return nil, err
}
return execution.NewExecutionServiceClient(conn), nil
return execution.NewContainerServiceClient(conn), nil
}
func getTempDir(id string) (string, error) {
@ -122,3 +123,19 @@ func getTempDir(id string) (string, error) {
}
return tmpDir, nil
}
func waitContainer(events execution.ContainerService_EventsClient, respose *execution.CreateResponse) (uint32, error) {
for {
e, err := events.Recv()
if err != nil {
return 255, err
}
if e.Type != container.Event_EXIT {
continue
}
if e.ID == respose.ID &&
e.Pid == respose.Pid {
return e.ExitStatus, nil
}
}
}

View file

@ -42,6 +42,7 @@ var (
// becomes the M declarations at the end of the declaration.
packageMap = map[string]string{
"google/protobuf/timestamp.proto": "github.com/gogo/protobuf/types",
"google/protobuf/any.proto": "github.com/gogo/protobuf/types",
"google/protobuf/descriptor.proto": "github.com/gogo/protobuf/protoc-gen-gogo/descriptor",
"gogoproto/gogo.proto": "github.com/gogo/protobuf/gogoproto",
}
@ -148,8 +149,9 @@ func main() {
// pass to sh -c so we don't need to re-split here.
args := []string{"-c", arg}
cmd := exec.Command("sh", args...)
if err := cmd.Run(); err != nil {
log.Fatalln(err)
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("%s %s\n", out, err)
}
}
}

94
collector.go Normal file
View file

@ -0,0 +1,94 @@
package containerd
import (
"sync"
"golang.org/x/net/context"
)
func newCollector(ctx context.Context, runtimes map[string]Runtime) (*collector, error) {
c := &collector{
context: ctx,
ch: make(chan *Event, 2048),
eventClients: make(map[*eventClient]struct{}),
}
for _, r := range runtimes {
if err := c.collect(r); err != nil {
return nil, err
}
}
// run the publisher
go c.publisher()
// run a goroutine that waits for the context to be done
// and closes the channel after all writes have finished
go c.waitDone()
return c, nil
}
type eventClient struct {
eCh chan error
w EventWriter
}
type collector struct {
mu sync.Mutex
wg sync.WaitGroup
context context.Context
ch chan *Event
eventClients map[*eventClient]struct{}
}
// collect collects events from the provided runtime
func (c *collector) collect(r Runtime) error {
c.wg.Add(1)
go func() {
defer c.wg.Done()
for e := range r.Events(c.context) {
c.ch <- e
}
}()
return nil
}
// Forward forwards all events from the collector to the EventWriters
//
// It forwards events until the channels are closed or the EventWriter
// returns an error
// This is a blocking call
func (c *collector) forward(w EventWriter) (err error) {
client := &eventClient{
w: w,
eCh: make(chan error, 1),
}
c.mu.Lock()
c.eventClients[client] = struct{}{}
c.mu.Unlock()
if serr := <-client.eCh; serr != nil {
err = serr
}
c.mu.Lock()
delete(c.eventClients, client)
c.mu.Unlock()
return err
}
func (c *collector) publisher() {
for e := range c.ch {
c.mu.Lock()
for client := range c.eventClients {
if err := client.w.Write(e); err != nil {
client.eCh <- err
}
}
c.mu.Unlock()
}
}
// waitDone waits for the context to finish, waits for all the goroutines to finish
// collecting grpc events from the shim, and closes the output channel
func (c *collector) waitDone() {
<-c.context.Done()
c.wg.Wait()
close(c.ch)
}

31
container.go Normal file
View file

@ -0,0 +1,31 @@
package containerd
import "golang.org/x/net/context"
type Container interface {
// ID of the container
ID() string
// Runtime returns the runtime name that the container was created with
Runtime() string
// Start the container's user defined process
Start(context.Context) error
// State returns the container's state
State(context.Context) (State, error)
}
type ContainerStatus int
const (
CreatedStatus ContainerStatus = iota + 1
RunningStatus
StoppedStatus
DeletedStatus
PausedStatus
)
type State interface {
// Status is the current status of the container
Status() ContainerStatus
// Pid is the main process id for the container
Pid() uint32
}

10
errors.go Normal file
View file

@ -0,0 +1,10 @@
package containerd
import "errors"
var (
ErrUnknownRuntime = errors.New("unknown runtime")
ErrContainerExists = errors.New("container with id already exists")
ErrContainerNotExist = errors.New("container does not exist")
ErrRuntimeNotExist = errors.New("runtime does not exist")
)

70
event.go Normal file
View file

@ -0,0 +1,70 @@
package containerd
import "time"
type EventType int
func (t EventType) String() string {
switch t {
case ExitEvent:
return "exit"
case PausedEvent:
return "paused"
case CreateEvent:
return "create"
case StartEvent:
return "start"
case OOMEvent:
return "oom"
case ExecAddEvent:
return "execAdd"
}
return "unknown"
}
const (
ExitEvent EventType = iota + 1
PausedEvent
CreateEvent
StartEvent
OOMEvent
ExecAddEvent
)
type Event struct {
Timestamp time.Time
Type EventType
Runtime string
ID string
Pid uint32
ExitStatus uint32
}
type EventWriter interface {
Write(*Event) error
}
type EventFilter func(*Event) bool
// NewFilterEventWriter returns an EventWriter that runs the provided filters on the events.
// If all the filters pass then the event is written to the wrapped EventWriter
func NewFilterEventWriter(w EventWriter, filters ...EventFilter) EventWriter {
return &filteredEventWriter{
w: w,
filters: filters,
}
}
type filteredEventWriter struct {
w EventWriter
filters []EventFilter
}
func (f *filteredEventWriter) Write(e *Event) error {
for _, filter := range f.filters {
if !filter(e) {
return nil
}
}
return f.w.Write(e)
}

View file

@ -1,179 +0,0 @@
package execution
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"sync"
"github.com/docker/containerd/log"
"github.com/pkg/errors"
)
const (
InitProcessID = "init"
processesDirName = "processes"
bundleFileName = "bundle"
)
func LoadContainer(ctx context.Context, stateDir, id string) (c *Container, err error) {
c = &Container{
id: id,
stateDir: stateDir,
processes: make(map[string]Process, 1),
ctx: ctx,
status: Unknown,
}
data, err := ioutil.ReadFile(filepath.Join(stateDir, bundleFileName))
if err != nil {
err = errors.Wrapf(err, "failed to read bundle path")
return
}
c.bundle = string(data)
return
}
func NewContainer(ctx context.Context, stateDir, id, bundle string) (c *Container, err error) {
c = &Container{
id: id,
stateDir: stateDir,
bundle: bundle,
processes: make(map[string]Process, 1),
status: Created,
ctx: ctx,
}
defer func() {
if err != nil {
c.Cleanup()
c = nil
}
}()
if err = os.Mkdir(stateDir, 0700); err != nil {
err = errors.Wrap(err, "failed to create container state dir")
return
}
bundleFile := filepath.Join(stateDir, bundleFileName)
if err = ioutil.WriteFile(bundleFile, []byte(bundle), 0600); err != nil {
err = errors.Wrap(err, "failed to store bundle path")
return
}
processesDir := filepath.Join(stateDir, processesDirName)
if err = os.Mkdir(processesDir, 0700); err != nil {
err = errors.Wrap(err, "failed to create processes statedir")
return
}
return
}
type Container struct {
id string
stateDir string
bundle string
processes map[string]Process
status Status
ctx context.Context
mu sync.Mutex
}
func (c *Container) ID() string {
return c.id
}
func (c *Container) Bundle() string {
return c.bundle
}
func (c *Container) Wait() (uint32, error) {
initProcess := c.GetProcess(InitProcessID)
return initProcess.Wait()
}
func (c *Container) Status() Status {
initProcess := c.GetProcess(InitProcessID)
return initProcess.Status()
}
func (c *Container) AddProcess(p Process) {
c.mu.Lock()
c.processes[p.ID()] = p
c.mu.Unlock()
}
func (c *Container) RemoveProcess(id string) error {
if _, ok := c.processes[id]; !ok {
return errors.Errorf("no such process %s", id)
}
c.mu.Lock()
delete(c.processes, id)
c.mu.Unlock()
processStateDir := filepath.Join(c.stateDir, processesDirName, id)
err := os.RemoveAll(processStateDir)
if err != nil {
return errors.Wrap(err, "failed to remove process state dir")
}
return nil
}
func (c *Container) GetProcess(id string) Process {
c.mu.Lock()
defer c.mu.Unlock()
return c.processes[id]
}
func (c *Container) Processes() []Process {
var procs []Process
c.mu.Lock()
for _, p := range c.processes {
procs = append(procs, p)
}
c.mu.Unlock()
return procs
}
// ProcessStateDir returns the path of the state dir for a given
// process id. The process doesn't have to exist for this to succeed.
func (c *Container) ProcessStateDir(id string) string {
return filepath.Join(c.stateDir, processesDirName, id)
}
// ProcessesStateDir returns a map matching process ids to their state
// directory
func (c *Container) ProcessesStateDir() (map[string]string, error) {
root := filepath.Join(c.stateDir, processesDirName)
dirs, err := ioutil.ReadDir(root)
if err != nil {
return nil, errors.Wrapf(err, "failed to list processes state dirs")
}
procs := make(map[string]string, 1)
for _, d := range dirs {
if d.IsDir() {
procs[d.Name()] = filepath.Join(root, d.Name())
}
}
return procs, nil
}
func (c *Container) Cleanup() {
if err := os.RemoveAll(c.stateDir); err != nil {
log.G(c.ctx).Warnf("failed to remove container state dir: %v", err)
}
}
func (c *Container) Context() context.Context {
return c.ctx
}

View file

@ -1,10 +0,0 @@
package execution
import "fmt"
var (
ErrProcessNotFound = fmt.Errorf("process not found")
ErrProcessNotExited = fmt.Errorf("process has not exited")
ErrContainerNotFound = fmt.Errorf("container not found")
ErrContainerExists = fmt.Errorf("container already exists")
)

View file

@ -1,28 +0,0 @@
package execution
import "time"
const (
ExitEvent = "exit"
OOMEvent = "oom"
CreateEvent = "create"
StartEvent = "start"
ExecEvent = "exec-added9"
)
type ContainerEvent struct {
Timestamp time.Time
ID string
Type string
Pid uint32
ExitStatus uint32
}
const (
ContainersEventsSubjectSubscriber = "containerd.execution.container.>"
)
const (
containerEventsTopicFormat = "container.%s"
containerProcessEventsTopicFormat = "container.%s.%s"
)

View file

@ -1,39 +0,0 @@
package execution
import (
"context"
"os"
"github.com/opencontainers/runtime-spec/specs-go"
)
type CreateOpts struct {
Bundle string
Console bool
Stdin string
Stdout string
Stderr string
}
type StartProcessOpts struct {
ID string
Spec specs.Process
Console bool
Stdin string
Stdout string
Stderr string
}
type Executor interface {
Create(ctx context.Context, id string, o CreateOpts) (*Container, error)
Pause(context.Context, *Container) error
Resume(context.Context, *Container) error
List(context.Context) ([]*Container, error)
Load(ctx context.Context, id string) (*Container, error)
Delete(context.Context, *Container) error
Start(context.Context, *Container) error
StartProcess(context.Context, *Container, StartProcessOpts) (Process, error)
SignalProcess(ctx context.Context, c *Container, id string, sig os.Signal) error
DeleteProcess(ctx context.Context, c *Container, id string) error
}

View file

@ -1,12 +0,0 @@
package execution
import "os"
type Process interface {
ID() string
Pid() int64
//Spec() *specs.Process
Wait() (uint32, error)
Signal(os.Signal) error
Status() Status
}

View file

@ -1,15 +0,0 @@
package execution
type Status string
const (
Created Status = "created"
Paused Status = "paused"
Pausing Status = "pausing"
Running Status = "running"
Stopped Status = "stopped"
Deleted Status = "deleted"
Unknown Status = "unknown"
UnknownStatusCode = 255
)

49
linux/container.go Normal file
View file

@ -0,0 +1,49 @@
package linux
import (
"github.com/docker/containerd"
"github.com/docker/containerd/api/services/shim"
"golang.org/x/net/context"
)
type State struct {
pid uint32
status containerd.ContainerStatus
}
func (s State) Pid() uint32 {
return s.pid
}
func (s State) Status() containerd.ContainerStatus {
return s.status
}
type Container struct {
id string
shim shim.ShimClient
}
func (c *Container) ID() string {
return c.id
}
func (Container) Runtime() string {
return runtimeName
}
func (c *Container) Start(ctx context.Context) error {
_, err := c.shim.Start(ctx, &shim.StartRequest{})
return err
}
func (c *Container) State(ctx context.Context) (containerd.State, error) {
response, err := c.shim.State(ctx, &shim.StateRequest{})
if err != nil {
return nil, err
}
return &State{
pid: response.Pid,
}, nil
}

197
linux/runtime.go Normal file
View file

@ -0,0 +1,197 @@
package linux
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"time"
"github.com/docker/containerd"
"github.com/docker/containerd/api/services/shim"
"github.com/docker/containerd/api/types/container"
"github.com/docker/containerd/api/types/mount"
"github.com/docker/swarmkit/log"
"golang.org/x/net/context"
)
const (
runtimeName = "linux"
configFilename = "config.json"
)
func init() {
containerd.RegisterRuntime(runtimeName, New)
}
func New(root string) (containerd.Runtime, error) {
if err := os.MkdirAll(root, 0700); err != nil {
return nil, err
}
c, cancel := context.WithCancel(context.Background())
return &Runtime{
root: root,
events: make(chan *containerd.Event, 2048),
eventsContext: c,
eventsCancel: cancel,
}, nil
}
type Runtime struct {
root string
events chan *containerd.Event
eventsContext context.Context
eventsCancel func()
}
func (r *Runtime) Create(ctx context.Context, id string, opts containerd.CreateOpts) (containerd.Container, error) {
path, err := r.newBundle(id, opts.Spec)
if err != nil {
os.RemoveAll(path)
return nil, err
}
s, err := newShim(path)
if err != nil {
os.RemoveAll(path)
return nil, err
}
if err := r.handleEvents(s); err != nil {
os.RemoveAll(path)
return nil, err
}
sopts := &shim.CreateRequest{
ID: id,
Bundle: path,
Runtime: "runc",
Stdin: opts.IO.Stdin,
Stdout: opts.IO.Stdout,
Stderr: opts.IO.Stderr,
Terminal: opts.IO.Terminal,
}
for _, m := range opts.Rootfs {
sopts.Rootfs = append(sopts.Rootfs, &mount.Mount{
Type: m.Type,
Source: m.Source,
Options: m.Options,
})
}
if _, err := s.Create(ctx, sopts); err != nil {
os.RemoveAll(path)
return nil, err
}
return &Container{
id: id,
shim: s,
}, nil
}
func (r *Runtime) Delete(ctx context.Context, c containerd.Container) error {
lc, ok := c.(*Container)
if !ok {
return fmt.Errorf("container cannot be cast as *linux.Container")
}
if _, err := lc.shim.Delete(ctx, &shim.DeleteRequest{}); err != nil {
return err
}
lc.shim.Exit(ctx, &shim.ExitRequest{})
return r.deleteBundle(lc.id)
}
func (r *Runtime) Containers() ([]containerd.Container, error) {
dir, err := ioutil.ReadDir(r.root)
if err != nil {
return nil, err
}
var o []containerd.Container
for _, fi := range dir {
if !fi.IsDir() {
continue
}
c, err := r.loadContainer(fi.Name())
if err != nil {
return nil, err
}
o = append(o, c)
}
return o, nil
}
func (r *Runtime) Events(ctx context.Context) <-chan *containerd.Event {
return r.events
}
func (r *Runtime) handleEvents(s shim.ShimClient) error {
events, err := s.Events(r.eventsContext, &shim.EventsRequest{})
if err != nil {
return err
}
go r.forward(events)
return nil
}
func (r *Runtime) forward(events shim.Shim_EventsClient) {
for {
e, err := events.Recv()
if err != nil {
log.G(r.eventsContext).WithError(err).Error("get event from shim")
return
}
var et containerd.EventType
switch e.Type {
case container.Event_CREATE:
et = containerd.CreateEvent
case container.Event_EXEC_ADDED:
et = containerd.ExecAddEvent
case container.Event_EXIT:
et = containerd.ExitEvent
case container.Event_OOM:
et = containerd.OOMEvent
case container.Event_START:
et = containerd.StartEvent
}
r.events <- &containerd.Event{
Timestamp: time.Now(),
Runtime: runtimeName,
Type: et,
Pid: e.Pid,
ID: e.ID,
ExitStatus: e.ExitStatus,
}
}
}
func (r *Runtime) newBundle(id string, spec []byte) (string, error) {
path := filepath.Join(r.root, id)
if err := os.Mkdir(path, 0700); err != nil {
return "", err
}
if err := os.Mkdir(filepath.Join(path, "rootfs"), 0700); err != nil {
return "", err
}
f, err := os.Create(filepath.Join(path, configFilename))
if err != nil {
return "", err
}
_, err = io.Copy(f, bytes.NewReader(spec))
return path, err
}
func (r *Runtime) deleteBundle(id string) error {
return os.RemoveAll(filepath.Join(r.root, id))
}
func (r *Runtime) loadContainer(path string) (*Container, error) {
id := filepath.Base(path)
s, err := loadShim(path)
if err != nil {
return nil, err
}
return &Container{
id: id,
shim: s,
}, nil
}

76
linux/shim.go Normal file
View file

@ -0,0 +1,76 @@
package linux
import (
"fmt"
"io/ioutil"
"log"
"net"
"os/exec"
"path/filepath"
"syscall"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
"github.com/docker/containerd/api/services/shim"
"github.com/docker/containerd/utils"
"github.com/pkg/errors"
)
func newShim(path string) (shim.ShimClient, error) {
socket := filepath.Join(path, "shim.sock")
l, err := utils.CreateUnixSocket(socket)
if err != nil {
return nil, err
}
cmd := exec.Command("containerd-shim")
cmd.Dir = path
f, err := l.(*net.UnixListener).File()
if err != nil {
return nil, err
}
cmd.ExtraFiles = append(cmd.ExtraFiles, f)
// make sure the shim can be re-parented to system init
// and is cloned in a new mount namespace because the overlay/filesystems
// will be mounted by the shim
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWNS,
Setpgid: true,
}
if err := cmd.Start(); err != nil {
return nil, errors.Wrapf(err, "failed to start shim")
}
// close our side of the socket, do not close the listener as it will
// remove the socket from disk
f.Close()
// since we are currently the parent go ahead and make sure we wait on the shim
go cmd.Wait()
return connectShim(socket)
}
func loadShim(path string) (shim.ShimClient, error) {
socket := filepath.Join(path, "shim.sock")
return connectShim(socket)
// TODO: failed to connect to the shim, check if it's alive
// - if it is kill it
// - in both case call runc killall and runc delete on the id
}
func connectShim(socket string) (shim.ShimClient, error) {
// reset the logger for grpc to log to dev/null so that it does not mess with our stdio
grpclog.SetLogger(log.New(ioutil.Discard, "", log.LstdFlags))
dialOpts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithTimeout(100 * time.Second)}
dialOpts = append(dialOpts,
grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout("unix", socket, timeout)
}),
grpc.WithBlock(),
grpc.WithTimeout(2*time.Second),
)
conn, err := grpc.Dial(fmt.Sprintf("unix://%s", socket), dialOpts...)
if err != nil {
return nil, errors.Wrapf(err, "failed to connect to shim via \"%s\"", fmt.Sprintf("unix://%s", socket))
}
return shim.NewShimClient(conn), nil
}

View file

@ -3,9 +3,6 @@ package containerd
import (
"strings"
"syscall"
"github.com/Sirupsen/logrus"
"github.com/docker/containerd/log"
)
// Mount is the lingua franca of containerd. A mount represents a
@ -23,13 +20,6 @@ type Mount struct {
func (m *Mount) Mount(target string) error {
flags, data := parseMountOptions(m.Options)
lfields := logrus.Fields{"target": target, "source": m.Source}
if data != "" {
lfields["data"] = data
}
log.L.WithFields(lfields).Debug("syscall.Mount")
return syscall.Mount(m.Source, target, m.Type, uintptr(flags), data)
}

79
runtime.go Normal file
View file

@ -0,0 +1,79 @@
package containerd
import (
"fmt"
"sync"
"golang.org/x/net/context"
)
// NewRuntimeFunc is the runtime's constructor
type NewRuntimeFunc func(root string) (Runtime, error)
var runtimeRegistration = struct {
mu sync.Mutex
runtimes map[string]NewRuntimeFunc
}{
runtimes: make(map[string]NewRuntimeFunc),
}
// RegisterRuntime is not external packages registers Runtimes for use with containerd
func RegisterRuntime(name string, f NewRuntimeFunc) {
runtimeRegistration.mu.Lock()
defer runtimeRegistration.mu.Unlock()
if _, ok := runtimeRegistration.runtimes[name]; ok {
panic(fmt.Errorf("runtime already registered as %q", name))
}
runtimeRegistration.runtimes[name] = f
}
// Runtimes returns a slice of all registered runtime names for containerd
func Runtimes() (o []string) {
runtimeRegistration.mu.Lock()
defer runtimeRegistration.mu.Unlock()
for k := range runtimeRegistration.runtimes {
o = append(o, k)
}
return o
}
// NewRuntime calls the runtime's constructor with the provided root
func NewRuntime(name, root string) (Runtime, error) {
runtimeRegistration.mu.Lock()
defer runtimeRegistration.mu.Unlock()
f, ok := runtimeRegistration.runtimes[name]
if !ok {
return nil, ErrRuntimeNotExist
}
return f(root)
}
type IO struct {
Stdin string
Stdout string
Stderr string
Terminal bool
}
type CreateOpts struct {
// Spec is the OCI runtime spec
Spec []byte
// Rootfs mounts to perform to gain access to the container's filesystem
Rootfs []Mount
// IO for the container's main process
IO IO
}
// Runtime is responsible for the creation of containers for a certain platform,
// arch, or custom usage.
type Runtime interface {
// Create creates a container with the provided id and options
Create(ctx context.Context, id string, opts CreateOpts) (Container, error)
// Containers returns all the current containers for the runtime
Containers() ([]Container, error)
// Delete returns the container in the runtime
Delete(ctx context.Context, c Container) error
// Events returns events for the runtime and all containers created by the runtime
Events(context.Context) <-chan *Event
}

View file

@ -0,0 +1,136 @@
package execution
import (
"github.com/docker/containerd"
api "github.com/docker/containerd/api/services/execution"
"github.com/docker/containerd/api/types/container"
google_protobuf "github.com/golang/protobuf/ptypes/empty"
"golang.org/x/net/context"
)
var (
_ = (api.ContainerServiceServer)(&Service{})
empty = &google_protobuf.Empty{}
)
// New creates a new GRPC service for the ContainerService
func New(s *containerd.Supervisor) *Service {
return &Service{
s: s,
}
}
type Service struct {
s *containerd.Supervisor
}
func (s *Service) Create(ctx context.Context, r *api.CreateRequest) (*api.CreateResponse, error) {
opts := containerd.CreateOpts{
Spec: r.Spec.Value,
IO: containerd.IO{
Stdin: r.Stdin,
Stdout: r.Stdout,
Stderr: r.Stderr,
Terminal: r.Terminal,
},
}
for _, m := range r.Rootfs {
opts.Rootfs = append(opts.Rootfs, containerd.Mount{
Type: m.Type,
Source: m.Source,
Options: m.Options,
})
}
c, err := s.s.Create(ctx, r.ID, r.Runtime, opts)
if err != nil {
return nil, err
}
state, err := c.State(ctx)
if err != nil {
return nil, err
}
return &api.CreateResponse{
ID: r.ID,
Pid: state.Pid(),
}, nil
}
func (s *Service) Start(ctx context.Context, r *api.StartRequest) (*google_protobuf.Empty, error) {
c, err := s.s.Get(r.ID)
if err != nil {
return nil, err
}
if err := c.Start(ctx); err != nil {
return nil, err
}
return empty, nil
}
func (s *Service) Delete(ctx context.Context, r *api.DeleteRequest) (*google_protobuf.Empty, error) {
if err := s.s.Delete(ctx, r.ID); err != nil {
return nil, err
}
return empty, nil
}
func (s *Service) List(ctx context.Context, r *api.ListRequest) (*api.ListResponse, error) {
resp := &api.ListResponse{}
for _, c := range s.s.Containers() {
state, err := c.State(ctx)
if err != nil {
return nil, err
}
var status container.Status
switch state.Status() {
case containerd.CreatedStatus:
status = container.Status_CREATED
case containerd.RunningStatus:
status = container.Status_RUNNING
case containerd.StoppedStatus:
status = container.Status_STOPPED
case containerd.PausedStatus:
status = container.Status_PAUSED
}
resp.Containers = append(resp.Containers, &container.Container{
ID: c.ID(),
Pid: state.Pid(),
Status: status,
})
}
return resp, nil
}
func (s *Service) Events(r *api.EventsRequest, server api.ContainerService_EventsServer) error {
w := &grpcEventWriter{
server: server,
}
return s.s.ForwardEvents(w)
}
type grpcEventWriter struct {
server api.ContainerService_EventsServer
}
func (g *grpcEventWriter) Write(e *containerd.Event) error {
var t container.Event_EventType
switch e.Type {
case containerd.ExitEvent:
t = container.Event_EXIT
case containerd.ExecAddEvent:
t = container.Event_EXEC_ADDED
case containerd.PausedEvent:
t = container.Event_PAUSED
case containerd.CreateEvent:
t = container.Event_CREATE
case containerd.StartEvent:
t = container.Event_START
case containerd.OOMEvent:
t = container.Event_OOM
}
return g.server.Send(&container.Event{
Type: t,
ID: e.ID,
Pid: e.Pid,
ExitStatus: e.ExitStatus,
})
}

View file

@ -9,6 +9,7 @@ import (
"github.com/crosbymichael/console"
runc "github.com/crosbymichael/go-runc"
"github.com/docker/containerd"
shimapi "github.com/docker/containerd/api/services/shim"
)
@ -29,6 +30,16 @@ func newInitProcess(context context.Context, r *shimapi.CreateRequest) (*initPro
if err != nil {
return nil, err
}
for _, rm := range r.Rootfs {
m := &containerd.Mount{
Type: rm.Type,
Source: rm.Source,
Options: rm.Options,
}
if err := m.Mount(filepath.Join(cwd, "rootfs")); err != nil {
return nil, err
}
}
runtime := &runc.Runc{
Command: r.Runtime,
Log: filepath.Join(cwd, "log.json"),

View file

@ -1,26 +1,26 @@
package shim
import (
"os"
"sync"
"syscall"
"github.com/crosbymichael/console"
shimapi "github.com/docker/containerd/api/services/shim"
processapi "github.com/docker/containerd/api/types/process"
stateapi "github.com/docker/containerd/api/types/state"
"github.com/docker/containerd/api/types/container"
"github.com/docker/containerd/utils"
google_protobuf "github.com/golang/protobuf/ptypes/empty"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
var emptyResponse = &google_protobuf.Empty{}
var empty = &google_protobuf.Empty{}
// New returns a new shim service that can be used via GRPC
func New() *Service {
return &Service{
processes: make(map[int]process),
events: make(chan *shimapi.Event, 4096),
events: make(chan *container.Event, 4096),
}
}
@ -30,7 +30,7 @@ type Service struct {
bundle string
mu sync.Mutex
processes map[int]process
events chan *shimapi.Event
events chan *container.Event
execID int
}
@ -46,8 +46,8 @@ func (s *Service) Create(ctx context.Context, r *shimapi.CreateRequest) (*shimap
pid := process.Pid()
s.processes[pid] = process
s.mu.Unlock()
s.events <- &shimapi.Event{
Type: shimapi.EventType_CREATE,
s.events <- &container.Event{
Type: container.Event_CREATE,
ID: r.ID,
Pid: uint32(pid),
}
@ -60,12 +60,12 @@ func (s *Service) Start(ctx context.Context, r *shimapi.StartRequest) (*google_p
if err := s.initProcess.Start(ctx); err != nil {
return nil, err
}
s.events <- &shimapi.Event{
Type: shimapi.EventType_START,
s.events <- &container.Event{
Type: container.Event_START,
ID: s.id,
Pid: uint32(s.initProcess.Pid()),
}
return emptyResponse, nil
return empty, nil
}
func (s *Service) Delete(ctx context.Context, r *shimapi.DeleteRequest) (*shimapi.DeleteResponse, error) {
@ -73,7 +73,7 @@ func (s *Service) Delete(ctx context.Context, r *shimapi.DeleteRequest) (*shimap
p, ok := s.processes[int(r.Pid)]
s.mu.Unlock()
if !ok {
return nil, errors.Errorf("process does not exist %d", r.Pid)
p = s.initProcess
}
if err := p.Delete(ctx); err != nil {
return nil, err
@ -96,8 +96,8 @@ func (s *Service) Exec(ctx context.Context, r *shimapi.ExecRequest) (*shimapi.Ex
}
pid := process.Pid()
s.processes[pid] = process
s.events <- &shimapi.Event{
Type: shimapi.EventType_EXEC_ADDED,
s.events <- &container.Event{
Type: container.Event_EXEC_ADDED,
ID: s.id,
Pid: uint32(pid),
}
@ -123,7 +123,7 @@ func (s *Service) Pty(ctx context.Context, r *shimapi.PtyRequest) (*google_proto
if err := p.Resize(ws); err != nil {
return nil, err
}
return emptyResponse, nil
return empty, nil
}
func (s *Service) Events(r *shimapi.EventsRequest, stream shimapi.Shim_EventsServer) error {
@ -139,22 +139,22 @@ func (s *Service) State(ctx context.Context, r *shimapi.StateRequest) (*shimapi.
o := &shimapi.StateResponse{
ID: s.id,
Bundle: s.bundle,
InitPid: uint32(s.initProcess.Pid()),
Processes: []*processapi.Process{},
Pid: uint32(s.initProcess.Pid()),
Processes: []*container.Process{},
}
s.mu.Lock()
defer s.mu.Unlock()
for _, p := range s.processes {
state := stateapi.State_RUNNING
status := container.Status_RUNNING
if err := syscall.Kill(p.Pid(), 0); err != nil {
if err != syscall.ESRCH {
return nil, err
}
state = stateapi.State_STOPPED
status = container.Status_STOPPED
}
o.Processes = append(o.Processes, &processapi.Process{
o.Processes = append(o.Processes, &container.Process{
Pid: uint32(p.Pid()),
State: state,
Status: status,
})
}
return o, nil
@ -164,22 +164,30 @@ func (s *Service) Pause(ctx context.Context, r *shimapi.PauseRequest) (*google_p
if err := s.initProcess.Pause(ctx); err != nil {
return nil, err
}
return emptyResponse, nil
return empty, nil
}
func (s *Service) Resume(ctx context.Context, r *shimapi.ResumeRequest) (*google_protobuf.Empty, error) {
if err := s.initProcess.Resume(ctx); err != nil {
return nil, err
}
return emptyResponse, nil
return empty, nil
}
func (s *Service) Exit(ctx context.Context, r *shimapi.ExitRequest) (*google_protobuf.Empty, error) {
// signal ourself to exit
if err := syscall.Kill(os.Getpid(), syscall.SIGTERM); err != nil {
return nil, err
}
return empty, nil
}
func (s *Service) ProcessExit(e utils.Exit) error {
s.mu.Lock()
if p, ok := s.processes[e.Pid]; ok {
p.Exited(e.Status)
s.events <- &shimapi.Event{
Type: shimapi.EventType_EXIT,
s.events <- &container.Event{
Type: container.Event_EXIT,
ID: s.id,
Pid: uint32(p.Pid()),
ExitStatus: uint32(e.Status),

View file

@ -1,70 +0,0 @@
package specification
import (
"runtime"
"github.com/docker/containerd"
"github.com/opencontainers/runtime-spec/specs-go"
)
var rwm = "rwm"
func Default(config containerd.Config, mounts []containerd.Mount) *specs.Spec {
s := &specs.Spec{
Version: specs.Version,
Platform: specs.Platform{
OS: runtime.GOOS,
Arch: runtime.GOARCH,
},
Root: specs.Root{
Path: "rootfs",
Readonly: false,
},
Process: specs.Process{
Args: config.Process.Args,
Env: config.Process.Env,
Terminal: config.Process.TTY,
Cwd: config.Process.Cwd,
NoNewPrivileges: true,
},
Hostname: config.Hostname,
Linux: &specs.Linux{
Resources: &specs.LinuxResources{
Devices: []specs.LinuxDeviceCgroup{
{
Allow: false,
Access: &rwm,
},
},
},
Namespaces: []specs.LinuxNamespace{
{
Type: "pid",
},
{
Type: "ipc",
},
{
Type: "uts",
},
{
Type: "mount",
},
{
Type: "network",
},
},
},
Annotations: config.Labels,
}
// apply snapshot mounts
for _, m := range mounts {
s.Mounts = append(s.Mounts, specs.Mount{
Source: m.Source,
Destination: "/",
Type: m.Type,
Options: m.Options,
})
}
return s
}

100
supervisor.go Normal file
View file

@ -0,0 +1,100 @@
package containerd
import (
"sync"
"golang.org/x/net/context"
)
func NewSupervisor(ctx context.Context, runtimes map[string]Runtime) (*Supervisor, error) {
c, err := newCollector(ctx, runtimes)
if err != nil {
return nil, err
}
s := &Supervisor{
containers: make(map[string]Container),
runtimes: runtimes,
collector: c,
}
for _, r := range runtimes {
containers, err := r.Containers()
if err != nil {
return nil, err
}
for _, c := range containers {
s.containers[c.ID()] = c
}
}
return s, nil
}
// Supervisor supervises containers and events from multiple runtimes
type Supervisor struct {
mu sync.Mutex
containers map[string]Container
runtimes map[string]Runtime
collector *collector
}
// ForwardEvents is a blocking method that will forward all events from the supervisor
// to the EventWriter provided by the caller
func (s *Supervisor) ForwardEvents(w EventWriter) error {
return s.collector.forward(w)
}
// Create creates a new container with the provided runtime
func (s *Supervisor) Create(ctx context.Context, id, runtime string, opts CreateOpts) (Container, error) {
r, ok := s.runtimes[runtime]
if !ok {
return nil, ErrUnknownRuntime
}
// check to make sure the container's id is unique across the entire system
s.mu.Lock()
defer s.mu.Unlock()
if _, ok := s.containers[id]; ok {
return nil, ErrContainerExists
}
c, err := r.Create(ctx, id, opts)
if err != nil {
return nil, err
}
s.containers[c.ID()] = c
return c, nil
}
// Delete deletes the container
func (s *Supervisor) Delete(ctx context.Context, id string) error {
s.mu.Lock()
defer s.mu.Unlock()
c, ok := s.containers[id]
if !ok {
return ErrContainerNotExist
}
err := s.runtimes[c.Runtime()].Delete(ctx, c)
if err != nil {
return err
}
delete(s.containers, id)
return nil
}
// Containers returns all the containers for the supervisor
func (s *Supervisor) Containers() (o []Container) {
s.mu.Lock()
defer s.mu.Unlock()
for _, c := range s.containers {
o = append(o, c)
}
return o
}
func (s *Supervisor) Get(id string) (Container, error) {
s.mu.Lock()
c, ok := s.containers[id]
s.mu.Unlock()
if !ok {
return nil, ErrContainerNotExist
}
return c, nil
}

View file

@ -1,354 +0,0 @@
package supervisor
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"sync"
"time"
executionapi "github.com/docker/containerd/api/services/execution"
"github.com/docker/containerd/api/services/shim"
"github.com/docker/containerd/api/types/container"
"github.com/docker/containerd/api/types/process"
"github.com/docker/containerd/events"
"github.com/docker/containerd/execution"
"github.com/docker/containerd/log"
google_protobuf "github.com/golang/protobuf/ptypes/empty"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
var (
_ = (executionapi.ExecutionServiceServer)(&Service{})
empty = &google_protobuf.Empty{}
)
// New creates a new GRPC services for execution
func New(ctx context.Context, root string) (*Service, error) {
ctx = log.WithModule(ctx, "supervisor")
log.G(ctx).WithField("root", root).Debugf("New()")
if err := os.MkdirAll(root, 0700); err != nil {
return nil, errors.Wrapf(err, "unable to create root directory %q", root)
}
clients, err := loadClients(ctx, root)
if err != nil {
return nil, err
}
s := &Service{
root: root,
shims: clients,
ctx: ctx,
}
for _, c := range clients {
if err := s.monitor(events.GetPoster(ctx), c); err != nil {
return nil, err
}
}
return s, nil
}
type Service struct {
mu sync.Mutex
ctx context.Context
root string
shims map[string]*shimClient
}
func (s *Service) propagateRuntimeLog(client *shimClient, entries int) {
logs, err := client.readRuntimeLogEntries(entries)
if err != nil {
log.G(s.ctx).WithError(err).WithField("container", client.id).
Warnf("failed to read shim log")
return
}
log.G(s.ctx).WithField("container", client.id).
Warnf("shim log (last %d entry): %v", entries, logs)
}
func (s *Service) CreateContainer(ctx context.Context, r *executionapi.CreateContainerRequest) (*executionapi.CreateContainerResponse, error) {
client, err := s.newShim(r.ID)
if err != nil {
return nil, err
}
defer func() {
if err != nil {
s.propagateRuntimeLog(client, 1)
s.removeShim(r.ID)
}
}()
if err := s.monitor(events.GetPoster(ctx), client); err != nil {
return nil, err
}
createResponse, err := client.Create(ctx, &shim.CreateRequest{
ID: r.ID,
Bundle: r.BundlePath,
Terminal: r.Console,
Stdin: r.Stdin,
Stdout: r.Stdout,
Stderr: r.Stderr,
})
if err != nil {
return nil, errors.Wrapf(err, "shim create request failed")
}
client.initPid = createResponse.Pid
return &executionapi.CreateContainerResponse{
Container: &container.Container{
ID: r.ID,
},
InitProcess: &process.Process{
Pid: createResponse.Pid,
},
}, nil
}
func (s *Service) StartContainer(ctx context.Context, r *executionapi.StartContainerRequest) (*google_protobuf.Empty, error) {
client, err := s.getShim(r.ID)
if err != nil {
return nil, err
}
if _, err := client.Start(ctx, &shim.StartRequest{}); err != nil {
return nil, err
}
return empty, nil
}
func (s *Service) DeleteContainer(ctx context.Context, r *executionapi.DeleteContainerRequest) (*google_protobuf.Empty, error) {
client, err := s.getShim(r.ID)
if err != nil {
return nil, err
}
_, err = client.Delete(ctx, &shim.DeleteRequest{
Pid: client.initPid,
})
if err != nil {
return nil, err
}
s.removeShim(r.ID)
return empty, nil
}
func (s *Service) ListContainers(ctx context.Context, r *executionapi.ListContainersRequest) (*executionapi.ListContainersResponse, error) {
resp := &executionapi.ListContainersResponse{}
for _, client := range s.shims {
status, err := client.State(ctx, &shim.StateRequest{})
if err != nil {
return nil, err
}
resp.Containers = append(resp.Containers, &container.Container{
ID: status.ID,
Bundle: status.Bundle,
})
}
return resp, nil
}
func (s *Service) GetContainer(ctx context.Context, r *executionapi.GetContainerRequest) (*executionapi.GetContainerResponse, error) {
client, err := s.getShim(r.ID)
if err != nil {
return nil, err
}
state, err := client.State(ctx, &shim.StateRequest{})
if err != nil {
return nil, err
}
return &executionapi.GetContainerResponse{
Container: &container.Container{
ID: state.ID,
Bundle: state.Bundle,
// TODO: add processes
},
}, nil
}
func (s *Service) UpdateContainer(ctx context.Context, r *executionapi.UpdateContainerRequest) (*google_protobuf.Empty, error) {
panic("not implemented")
return empty, nil
}
func (s *Service) PauseContainer(ctx context.Context, r *executionapi.PauseContainerRequest) (*google_protobuf.Empty, error) {
client, err := s.getShim(r.ID)
if err != nil {
return nil, err
}
return client.Pause(ctx, &shim.PauseRequest{})
}
func (s *Service) ResumeContainer(ctx context.Context, r *executionapi.ResumeContainerRequest) (*google_protobuf.Empty, error) {
client, err := s.getShim(r.ID)
if err != nil {
return nil, err
}
return client.Resume(ctx, &shim.ResumeRequest{})
}
func (s *Service) StartProcess(ctx context.Context, r *executionapi.StartProcessRequest) (*executionapi.StartProcessResponse, error) {
client, err := s.getShim(r.ContainerID)
if err != nil {
return nil, err
}
er := &shim.ExecRequest{
Terminal: r.Console,
Stdin: r.Stdin,
Stdout: r.Stdout,
Stderr: r.Stderr,
Args: r.Process.Args,
Env: r.Process.Env,
Cwd: r.Process.Cwd,
}
if r.Process.User != nil {
er.User.Uid = r.Process.User.Uid
er.User.Gid = r.Process.User.Gid
er.User.AdditionalGids = r.Process.User.AdditionalGids
}
resp, err := client.Exec(ctx, er)
if err != nil {
return nil, errors.Wrapf(err, "failed to exec into container %q", r.ContainerID)
}
r.Process.Pid = resp.Pid
return &executionapi.StartProcessResponse{
Process: r.Process,
}, nil
}
// containerd managed execs + system pids forked in container
func (s *Service) GetProcess(ctx context.Context, r *executionapi.GetProcessRequest) (*executionapi.GetProcessResponse, error) {
panic("not implemented")
}
func (s *Service) SignalProcess(ctx context.Context, r *executionapi.SignalProcessRequest) (*google_protobuf.Empty, error) {
panic("not implemented")
}
func (s *Service) DeleteProcess(ctx context.Context, r *executionapi.DeleteProcessRequest) (*google_protobuf.Empty, error) {
client, err := s.getShim(r.ContainerID)
if err != nil {
return nil, err
}
_, err = client.Delete(ctx, &shim.DeleteRequest{
Pid: r.Pid,
})
if err != nil {
return nil, err
}
if r.Pid == client.initPid {
s.removeShim(r.ContainerID)
}
return empty, nil
}
func (s *Service) ListProcesses(ctx context.Context, r *executionapi.ListProcessesRequest) (*executionapi.ListProcessesResponse, error) {
panic("not implemented")
}
// monitor monitors the shim's event rpc and forwards container and process
// events to callers
func (s *Service) monitor(poster events.Poster, client *shimClient) error {
// we use the service context here because we don't want to be
// tied to the Create rpc call
stream, err := client.Events(s.ctx, &shim.EventsRequest{})
if err != nil {
return errors.Wrapf(err, "failed to get events stream for client at %q", client.root)
}
go func() {
for {
e, err := stream.Recv()
if err != nil {
if err.Error() == "EOF" || strings.Contains(err.Error(), "transport is closing") {
break
}
log.G(s.ctx).WithError(err).WithField("container", client.id).
Warnf("event stream for client at %q got terminated", client.root)
break
}
var topic string
if e.Type == shim.EventType_CREATE {
topic = "containers"
} else {
topic = fmt.Sprintf("containers.%s", e.ID)
}
ctx := events.WithTopic(s.ctx, topic)
poster.Post(ctx, execution.ContainerEvent{
Timestamp: time.Now(),
ID: e.ID,
Type: toExecutionEventType(e.Type),
Pid: e.Pid,
ExitStatus: e.ExitStatus,
})
}
}()
return nil
}
func (s *Service) newShim(id string) (*shimClient, error) {
s.mu.Lock()
defer s.mu.Unlock()
if _, ok := s.shims[id]; ok {
return nil, errors.Errorf("container %q already exists", id)
}
client, err := newShimClient(filepath.Join(s.root, id), id)
if err != nil {
return nil, err
}
s.shims[id] = client
return client, nil
}
func (s *Service) getShim(id string) (*shimClient, error) {
s.mu.Lock()
defer s.mu.Unlock()
client, ok := s.shims[id]
if !ok {
return nil, fmt.Errorf("container does not exist %q", id)
}
return client, nil
}
func (s *Service) removeShim(id string) {
s.mu.Lock()
defer s.mu.Unlock()
client, ok := s.shims[id]
if ok {
client.stop()
delete(s.shims, id)
}
}
func loadClients(ctx context.Context, root string) (map[string]*shimClient, error) {
files, err := ioutil.ReadDir(root)
if err != nil {
return nil, err
}
out := make(map[string]*shimClient)
for _, f := range files {
if !f.IsDir() {
continue
}
//
id := f.Name()
client, err := loadShimClient(filepath.Join(root, id), id)
if err != nil {
log.G(ctx).WithError(err).WithField("id", id).Warn("failed to load container")
// TODO: send an exit event with 255 as exit status
continue
}
out[f.Name()] = client
}
return out, nil
}
func toExecutionEventType(et shim.EventType) string {
return strings.Replace(strings.ToLower(et.String()), "_", "-", -1)
}

View file

@ -1,160 +0,0 @@
package supervisor
import (
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"
"time"
"github.com/docker/containerd/api/services/shim"
"github.com/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
)
func newShimClient(root, id string) (*shimClient, error) {
if err := os.Mkdir(root, 0700); err != nil {
return nil, errors.Wrap(err, "failed to create shim working dir")
}
cmd := exec.Command("containerd-shim")
cmd.Dir = root
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
if err := cmd.Start(); err != nil {
return nil, errors.Wrapf(err, "failed to start shim")
}
socket := filepath.Join(root, "shim.sock")
sc, err := connectToShim(socket)
if err != nil {
syscall.Kill(cmd.Process.Pid, syscall.SIGKILL)
cmd.Wait()
return nil, err
}
s := &shimClient{
ShimClient: sc,
shimCmd: cmd,
syncCh: make(chan struct{}),
root: root,
id: id,
}
go func() {
cmd.Wait()
close(s.syncCh)
}()
return s, nil
}
func loadShimClient(root, id string) (*shimClient, error) {
socket := filepath.Join(root, "shim.sock")
client, err := connectToShim(socket)
if err != nil {
// TODO: failed to connect to the shim, check if it's alive
// - if it is kill it
// - in both case call runc killall and runc delete on the id
return nil, err
}
resp, err := client.State(context.Background(), &shim.StateRequest{})
if err != nil {
return nil, errors.Wrapf(err, "failed to fetch state for container %s", id)
}
return &shimClient{
ShimClient: client,
root: root,
id: id,
initPid: resp.InitPid,
}, nil
}
type shimClient struct {
shim.ShimClient
shimCmd *exec.Cmd
syncCh chan struct{}
root string
id string
initPid uint32
}
func (s *shimClient) stop() {
if s.shimCmd != nil {
select {
case <-s.syncCh:
default:
syscall.Kill(s.shimCmd.Process.Pid, syscall.SIGTERM)
select {
case <-s.syncCh:
case <-time.After(10 * time.Second):
syscall.Kill(s.shimCmd.Process.Pid, syscall.SIGKILL)
}
}
}
os.RemoveAll(s.root)
}
func (s *shimClient) readRuntimeLogEntries(lastEntries int) ([]map[string]interface{}, error) {
f, err := os.Open(filepath.Join(s.root, "log.json"))
if err != nil {
return nil, err
}
defer f.Close()
return parseRuntimeLog(f, lastEntries)
}
// parseRuntimeLog parses log.json.
// If lastEntries is greater than 0, only some last entries are returned.
func parseRuntimeLog(r io.Reader, lastEntries int) ([]map[string]interface{}, error) {
b, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
lines := strings.Split(string(b), "\n")
if lastEntries > 0 {
lines = lines[len(lines)-lastEntries-1 : len(lines)]
}
var entries []map[string]interface{}
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" {
continue
}
var entry map[string]interface{}
if err := json.Unmarshal([]byte(line), &entry); err != nil {
return nil, errors.Wrapf(err, "cannot unmarshal JSON string %q", line)
}
entries = append(entries, entry)
}
return entries, nil
}
func connectToShim(socket string) (shim.ShimClient, error) {
// reset the logger for grpc to log to dev/null so that it does not mess with our stdio
grpclog.SetLogger(log.New(ioutil.Discard, "", log.LstdFlags))
dialOpts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithTimeout(100 * time.Second)}
dialOpts = append(dialOpts,
grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout("unix", socket, timeout)
}),
grpc.WithBlock(),
grpc.WithTimeout(2*time.Second),
)
conn, err := grpc.Dial(fmt.Sprintf("unix://%s", socket), dialOpts...)
if err != nil {
return nil, errors.Wrapf(err, "failed to connect to shim via \"%s\"", fmt.Sprintf("unix://%s", socket))
}
return shim.NewShimClient(conn), nil
}