Add exec and terminal support

Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
Kenfe-Mickael Laventure 2016-12-09 09:17:34 -08:00
parent aee6045292
commit 0aad42f5cf
10 changed files with 531 additions and 231 deletions

View File

@ -102,9 +102,10 @@ func (*StartContainerRequest) Descriptor() ([]byte, []int) { return fileDescript
type CreateContainerRequest struct { type CreateContainerRequest struct {
ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
BundlePath string `protobuf:"bytes,2,opt,name=bundle_path,json=bundlePath,proto3" json:"bundle_path,omitempty"` BundlePath string `protobuf:"bytes,2,opt,name=bundle_path,json=bundlePath,proto3" json:"bundle_path,omitempty"`
Stdin string `protobuf:"bytes,3,opt,name=stdin,proto3" json:"stdin,omitempty"` Console bool `protobuf:"varint,3,opt,name=console,proto3" json:"console,omitempty"`
Stdout string `protobuf:"bytes,4,opt,name=stdout,proto3" json:"stdout,omitempty"` Stdin string `protobuf:"bytes,4,opt,name=stdin,proto3" json:"stdin,omitempty"`
Stderr string `protobuf:"bytes,5,opt,name=stderr,proto3" json:"stderr,omitempty"` Stdout string `protobuf:"bytes,5,opt,name=stdout,proto3" json:"stdout,omitempty"`
Stderr string `protobuf:"bytes,6,opt,name=stderr,proto3" json:"stderr,omitempty"`
} }
func (m *CreateContainerRequest) Reset() { *m = CreateContainerRequest{} } func (m *CreateContainerRequest) Reset() { *m = CreateContainerRequest{} }
@ -146,9 +147,10 @@ func (*ListContainersResponse) Descriptor() ([]byte, []int) { return fileDescrip
type StartProcessRequest struct { type StartProcessRequest struct {
ContainerId string `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` ContainerId string `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"`
Process *Process `protobuf:"bytes,2,opt,name=process" json:"process,omitempty"` Process *Process `protobuf:"bytes,2,opt,name=process" json:"process,omitempty"`
Stdin string `protobuf:"bytes,3,opt,name=stdin,proto3" json:"stdin,omitempty"` Console bool `protobuf:"varint,3,opt,name=console,proto3" json:"console,omitempty"`
Stdout string `protobuf:"bytes,4,opt,name=stdout,proto3" json:"stdout,omitempty"` Stdin string `protobuf:"bytes,4,opt,name=stdin,proto3" json:"stdin,omitempty"`
Stderr string `protobuf:"bytes,5,opt,name=stderr,proto3" json:"stderr,omitempty"` Stdout string `protobuf:"bytes,5,opt,name=stdout,proto3" json:"stdout,omitempty"`
Stderr string `protobuf:"bytes,6,opt,name=stderr,proto3" json:"stderr,omitempty"`
} }
func (m *StartProcessRequest) Reset() { *m = StartProcessRequest{} } func (m *StartProcessRequest) Reset() { *m = StartProcessRequest{} }
@ -330,10 +332,11 @@ func (this *CreateContainerRequest) GoString() string {
if this == nil { if this == nil {
return "nil" return "nil"
} }
s := make([]string, 0, 9) s := make([]string, 0, 10)
s = append(s, "&execution.CreateContainerRequest{") s = append(s, "&execution.CreateContainerRequest{")
s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n")
s = append(s, "BundlePath: "+fmt.Sprintf("%#v", this.BundlePath)+",\n") s = append(s, "BundlePath: "+fmt.Sprintf("%#v", this.BundlePath)+",\n")
s = append(s, "Console: "+fmt.Sprintf("%#v", this.Console)+",\n")
s = append(s, "Stdin: "+fmt.Sprintf("%#v", this.Stdin)+",\n") s = append(s, "Stdin: "+fmt.Sprintf("%#v", this.Stdin)+",\n")
s = append(s, "Stdout: "+fmt.Sprintf("%#v", this.Stdout)+",\n") s = append(s, "Stdout: "+fmt.Sprintf("%#v", this.Stdout)+",\n")
s = append(s, "Stderr: "+fmt.Sprintf("%#v", this.Stderr)+",\n") s = append(s, "Stderr: "+fmt.Sprintf("%#v", this.Stderr)+",\n")
@ -388,12 +391,13 @@ func (this *StartProcessRequest) GoString() string {
if this == nil { if this == nil {
return "nil" return "nil"
} }
s := make([]string, 0, 9) s := make([]string, 0, 10)
s = append(s, "&execution.StartProcessRequest{") s = append(s, "&execution.StartProcessRequest{")
s = append(s, "ContainerId: "+fmt.Sprintf("%#v", this.ContainerId)+",\n") s = append(s, "ContainerId: "+fmt.Sprintf("%#v", this.ContainerId)+",\n")
if this.Process != nil { if this.Process != nil {
s = append(s, "Process: "+fmt.Sprintf("%#v", this.Process)+",\n") s = append(s, "Process: "+fmt.Sprintf("%#v", this.Process)+",\n")
} }
s = append(s, "Console: "+fmt.Sprintf("%#v", this.Console)+",\n")
s = append(s, "Stdin: "+fmt.Sprintf("%#v", this.Stdin)+",\n") s = append(s, "Stdin: "+fmt.Sprintf("%#v", this.Stdin)+",\n")
s = append(s, "Stdout: "+fmt.Sprintf("%#v", this.Stdout)+",\n") s = append(s, "Stdout: "+fmt.Sprintf("%#v", this.Stdout)+",\n")
s = append(s, "Stderr: "+fmt.Sprintf("%#v", this.Stderr)+",\n") s = append(s, "Stderr: "+fmt.Sprintf("%#v", this.Stderr)+",\n")
@ -1136,20 +1140,30 @@ func (m *CreateContainerRequest) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintExecution(dAtA, i, uint64(len(m.BundlePath))) i = encodeVarintExecution(dAtA, i, uint64(len(m.BundlePath)))
i += copy(dAtA[i:], m.BundlePath) i += copy(dAtA[i:], m.BundlePath)
} }
if m.Console {
dAtA[i] = 0x18
i++
if m.Console {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if len(m.Stdin) > 0 { if len(m.Stdin) > 0 {
dAtA[i] = 0x1a dAtA[i] = 0x22
i++ i++
i = encodeVarintExecution(dAtA, i, uint64(len(m.Stdin))) i = encodeVarintExecution(dAtA, i, uint64(len(m.Stdin)))
i += copy(dAtA[i:], m.Stdin) i += copy(dAtA[i:], m.Stdin)
} }
if len(m.Stdout) > 0 { if len(m.Stdout) > 0 {
dAtA[i] = 0x22 dAtA[i] = 0x2a
i++ i++
i = encodeVarintExecution(dAtA, i, uint64(len(m.Stdout))) i = encodeVarintExecution(dAtA, i, uint64(len(m.Stdout)))
i += copy(dAtA[i:], m.Stdout) i += copy(dAtA[i:], m.Stdout)
} }
if len(m.Stderr) > 0 { if len(m.Stderr) > 0 {
dAtA[i] = 0x2a dAtA[i] = 0x32
i++ i++
i = encodeVarintExecution(dAtA, i, uint64(len(m.Stderr))) i = encodeVarintExecution(dAtA, i, uint64(len(m.Stderr)))
i += copy(dAtA[i:], m.Stderr) i += copy(dAtA[i:], m.Stderr)
@ -1303,20 +1317,30 @@ func (m *StartProcessRequest) MarshalTo(dAtA []byte) (int, error) {
} }
i += n2 i += n2
} }
if m.Console {
dAtA[i] = 0x18
i++
if m.Console {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if len(m.Stdin) > 0 { if len(m.Stdin) > 0 {
dAtA[i] = 0x1a dAtA[i] = 0x22
i++ i++
i = encodeVarintExecution(dAtA, i, uint64(len(m.Stdin))) i = encodeVarintExecution(dAtA, i, uint64(len(m.Stdin)))
i += copy(dAtA[i:], m.Stdin) i += copy(dAtA[i:], m.Stdin)
} }
if len(m.Stdout) > 0 { if len(m.Stdout) > 0 {
dAtA[i] = 0x22 dAtA[i] = 0x2a
i++ i++
i = encodeVarintExecution(dAtA, i, uint64(len(m.Stdout))) i = encodeVarintExecution(dAtA, i, uint64(len(m.Stdout)))
i += copy(dAtA[i:], m.Stdout) i += copy(dAtA[i:], m.Stdout)
} }
if len(m.Stderr) > 0 { if len(m.Stderr) > 0 {
dAtA[i] = 0x2a dAtA[i] = 0x32
i++ i++
i = encodeVarintExecution(dAtA, i, uint64(len(m.Stderr))) i = encodeVarintExecution(dAtA, i, uint64(len(m.Stderr)))
i += copy(dAtA[i:], m.Stderr) i += copy(dAtA[i:], m.Stderr)
@ -1905,6 +1929,9 @@ func (m *CreateContainerRequest) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovExecution(uint64(l)) n += 1 + l + sovExecution(uint64(l))
} }
if m.Console {
n += 2
}
l = len(m.Stdin) l = len(m.Stdin)
if l > 0 { if l > 0 {
n += 1 + l + sovExecution(uint64(l)) n += 1 + l + sovExecution(uint64(l))
@ -1975,6 +2002,9 @@ func (m *StartProcessRequest) Size() (n int) {
l = m.Process.Size() l = m.Process.Size()
n += 1 + l + sovExecution(uint64(l)) n += 1 + l + sovExecution(uint64(l))
} }
if m.Console {
n += 2
}
l = len(m.Stdin) l = len(m.Stdin)
if l > 0 { if l > 0 {
n += 1 + l + sovExecution(uint64(l)) n += 1 + l + sovExecution(uint64(l))
@ -2236,6 +2266,7 @@ func (this *CreateContainerRequest) String() string {
s := strings.Join([]string{`&CreateContainerRequest{`, s := strings.Join([]string{`&CreateContainerRequest{`,
`ID:` + fmt.Sprintf("%v", this.ID) + `,`, `ID:` + fmt.Sprintf("%v", this.ID) + `,`,
`BundlePath:` + fmt.Sprintf("%v", this.BundlePath) + `,`, `BundlePath:` + fmt.Sprintf("%v", this.BundlePath) + `,`,
`Console:` + fmt.Sprintf("%v", this.Console) + `,`,
`Stdin:` + fmt.Sprintf("%v", this.Stdin) + `,`, `Stdin:` + fmt.Sprintf("%v", this.Stdin) + `,`,
`Stdout:` + fmt.Sprintf("%v", this.Stdout) + `,`, `Stdout:` + fmt.Sprintf("%v", this.Stdout) + `,`,
`Stderr:` + fmt.Sprintf("%v", this.Stderr) + `,`, `Stderr:` + fmt.Sprintf("%v", this.Stderr) + `,`,
@ -2290,6 +2321,7 @@ func (this *StartProcessRequest) String() string {
s := strings.Join([]string{`&StartProcessRequest{`, s := strings.Join([]string{`&StartProcessRequest{`,
`ContainerId:` + fmt.Sprintf("%v", this.ContainerId) + `,`, `ContainerId:` + fmt.Sprintf("%v", this.ContainerId) + `,`,
`Process:` + strings.Replace(fmt.Sprintf("%v", this.Process), "Process", "Process", 1) + `,`, `Process:` + strings.Replace(fmt.Sprintf("%v", this.Process), "Process", "Process", 1) + `,`,
`Console:` + fmt.Sprintf("%v", this.Console) + `,`,
`Stdin:` + fmt.Sprintf("%v", this.Stdin) + `,`, `Stdin:` + fmt.Sprintf("%v", this.Stdin) + `,`,
`Stdout:` + fmt.Sprintf("%v", this.Stdout) + `,`, `Stdout:` + fmt.Sprintf("%v", this.Stdout) + `,`,
`Stderr:` + fmt.Sprintf("%v", this.Stderr) + `,`, `Stderr:` + fmt.Sprintf("%v", this.Stderr) + `,`,
@ -2638,6 +2670,26 @@ func (m *CreateContainerRequest) Unmarshal(dAtA []byte) error {
m.BundlePath = string(dAtA[iNdEx:postIndex]) m.BundlePath = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 3: case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Console", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowExecution
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Console = bool(v != 0)
case 4:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Stdin", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Stdin", wireType)
} }
@ -2666,7 +2718,7 @@ func (m *CreateContainerRequest) Unmarshal(dAtA []byte) error {
} }
m.Stdin = string(dAtA[iNdEx:postIndex]) m.Stdin = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 4: case 5:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Stdout", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Stdout", wireType)
} }
@ -2695,7 +2747,7 @@ func (m *CreateContainerRequest) Unmarshal(dAtA []byte) error {
} }
m.Stdout = string(dAtA[iNdEx:postIndex]) m.Stdout = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 5: case 6:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Stderr", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Stderr", wireType)
} }
@ -3159,6 +3211,26 @@ func (m *StartProcessRequest) Unmarshal(dAtA []byte) error {
} }
iNdEx = postIndex iNdEx = postIndex
case 3: case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Console", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowExecution
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Console = bool(v != 0)
case 4:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Stdin", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Stdin", wireType)
} }
@ -3187,7 +3259,7 @@ func (m *StartProcessRequest) Unmarshal(dAtA []byte) error {
} }
m.Stdin = string(dAtA[iNdEx:postIndex]) m.Stdin = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 4: case 5:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Stdout", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Stdout", wireType)
} }
@ -3216,7 +3288,7 @@ func (m *StartProcessRequest) Unmarshal(dAtA []byte) error {
} }
m.Stdout = string(dAtA[iNdEx:postIndex]) m.Stdout = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 5: case 6:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Stderr", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Stderr", wireType)
} }
@ -5033,66 +5105,67 @@ var (
func init() { proto.RegisterFile("execution.proto", fileDescriptorExecution) } func init() { proto.RegisterFile("execution.proto", fileDescriptorExecution) }
var fileDescriptorExecution = []byte{ var fileDescriptorExecution = []byte{
// 967 bytes of a gzipped FileDescriptorProto // 980 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xc4, 0x56, 0xdd, 0x6e, 0x1b, 0x45, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xc4, 0x56, 0xdd, 0x6e, 0x1b, 0x45,
0x14, 0xce, 0xfa, 0x2f, 0xf1, 0x71, 0xb7, 0x98, 0x89, 0xb3, 0xac, 0x0c, 0xb8, 0xe9, 0xd2, 0x96, 0x14, 0xce, 0xfa, 0x37, 0x3e, 0xee, 0x16, 0x33, 0x71, 0x96, 0x95, 0x01, 0x37, 0x5d, 0xda, 0x12,
0x08, 0x29, 0x4e, 0x30, 0x08, 0x21, 0x71, 0xd5, 0xc6, 0xc6, 0x44, 0x0a, 0xc6, 0x1d, 0xd7, 0xaa, 0x21, 0xc5, 0x09, 0x06, 0x21, 0x24, 0xae, 0xda, 0xd8, 0x98, 0x48, 0xc1, 0xb8, 0xe3, 0x5a, 0x95,
0xc4, 0x4d, 0xb4, 0xf1, 0x0e, 0xee, 0x22, 0x67, 0xd7, 0xdd, 0x99, 0x4d, 0xcb, 0x5d, 0xdf, 0x02, 0xb8, 0x89, 0x36, 0xde, 0xc1, 0x5d, 0xe4, 0xec, 0xba, 0x3b, 0xb3, 0x69, 0xb9, 0xeb, 0x63, 0x70,
0x6e, 0x78, 0x07, 0x1e, 0xa3, 0x97, 0x70, 0xc7, 0x15, 0x22, 0x7e, 0x02, 0x1e, 0x01, 0xcd, 0xcf, 0xc3, 0x43, 0xf0, 0x16, 0x15, 0x57, 0x70, 0xc7, 0x15, 0x22, 0x7e, 0x02, 0x1e, 0x01, 0xcd, 0xcf,
0xfa, 0x67, 0x77, 0xed, 0x18, 0xb7, 0x12, 0x77, 0x33, 0x67, 0xbf, 0xf9, 0xe6, 0x3b, 0x73, 0x66, 0xfa, 0x67, 0x77, 0xed, 0x98, 0x14, 0xc4, 0xdd, 0xcc, 0xd9, 0xef, 0x9c, 0xf9, 0xce, 0x39, 0xb3,
0xbf, 0x39, 0xf0, 0x0e, 0x79, 0x49, 0x06, 0x21, 0x73, 0x7d, 0xaf, 0x3e, 0x0e, 0x7c, 0xe6, 0x23, 0xdf, 0x1c, 0x78, 0x8b, 0xbc, 0x24, 0xc3, 0x90, 0xb9, 0xbe, 0xd7, 0x98, 0x04, 0x3e, 0xf3, 0x91,
0x7d, 0xe0, 0x7b, 0xcc, 0x76, 0x3d, 0x12, 0x38, 0xf5, 0xab, 0x4f, 0xab, 0xef, 0x0f, 0x7d, 0x7f, 0x3e, 0xf4, 0x3d, 0x66, 0xbb, 0x1e, 0x09, 0x9c, 0xc6, 0xe5, 0xc7, 0xb5, 0x77, 0x47, 0xbe, 0x3f,
0x38, 0x22, 0x47, 0xe2, 0xe3, 0x45, 0xf8, 0xc3, 0x11, 0xb9, 0x1c, 0xb3, 0x9f, 0x24, 0xb6, 0x5a, 0x1a, 0x93, 0x43, 0xf1, 0xf1, 0x3c, 0xfc, 0xee, 0x90, 0x5c, 0x4c, 0xd8, 0x0f, 0x12, 0x5b, 0xab,
0x19, 0xfa, 0x43, 0x5f, 0x0c, 0x8f, 0xf8, 0x48, 0x46, 0xad, 0x23, 0xd8, 0xeb, 0x31, 0x3b, 0x60, 0x8e, 0xfc, 0x91, 0x2f, 0x96, 0x87, 0x7c, 0x25, 0xad, 0xd6, 0x21, 0xec, 0xf6, 0x99, 0x1d, 0xb0,
0x27, 0x11, 0x11, 0x26, 0xcf, 0x43, 0x42, 0x19, 0x32, 0x20, 0xe3, 0x3a, 0xa6, 0xb6, 0xaf, 0x1d, 0xe3, 0x28, 0x10, 0x26, 0xcf, 0x43, 0x42, 0x19, 0x32, 0x20, 0xe3, 0x3a, 0xa6, 0xb6, 0xa7, 0xed,
0x14, 0x1f, 0x15, 0x26, 0x7f, 0xdd, 0xc9, 0x9c, 0x36, 0x71, 0xc6, 0x75, 0xac, 0x9f, 0x35, 0x30, 0x97, 0x1e, 0x15, 0xa6, 0x7f, 0xdc, 0xc9, 0x9c, 0xb4, 0x70, 0xc6, 0x75, 0xac, 0x9f, 0x35, 0x30,
0x4e, 0x02, 0x62, 0x33, 0xb2, 0xee, 0x12, 0x74, 0x07, 0x4a, 0x17, 0xa1, 0xe7, 0x8c, 0xc8, 0xf9, 0x8e, 0x03, 0x62, 0x33, 0xb2, 0xa9, 0x0b, 0xba, 0x03, 0xe5, 0xf3, 0xd0, 0x73, 0xc6, 0xe4, 0x6c,
0xd8, 0x66, 0xcf, 0xcc, 0x0c, 0x07, 0x60, 0x90, 0xa1, 0xae, 0xcd, 0x9e, 0xa1, 0x0a, 0xe4, 0x29, 0x62, 0xb3, 0x67, 0x66, 0x86, 0x03, 0x30, 0x48, 0x53, 0xcf, 0x66, 0xcf, 0x90, 0x09, 0xc5, 0xa1,
0x73, 0x5c, 0xcf, 0xcc, 0x8a, 0x4f, 0x72, 0x82, 0x0c, 0x28, 0x50, 0xe6, 0xf8, 0x21, 0x33, 0x73, 0xef, 0x51, 0x7f, 0x4c, 0xcc, 0xec, 0x9e, 0xb6, 0xbf, 0x8d, 0xa3, 0x2d, 0xaa, 0x42, 0x9e, 0x32,
0x22, 0xac, 0x66, 0x2a, 0x4e, 0x82, 0xc0, 0xcc, 0x4f, 0xe3, 0x24, 0x08, 0xac, 0xc7, 0xf0, 0x5e, 0xc7, 0xf5, 0xcc, 0x9c, 0x70, 0x92, 0x1b, 0x64, 0x40, 0x81, 0x32, 0xc7, 0x0f, 0x99, 0x99, 0x17,
0x42, 0x18, 0x1d, 0xfb, 0x1e, 0x25, 0xe8, 0x0b, 0x28, 0x4e, 0x4f, 0x4a, 0x08, 0x2c, 0x35, 0xcc, 0x66, 0xb5, 0x53, 0x76, 0x12, 0x04, 0x66, 0x61, 0x66, 0x27, 0x41, 0x60, 0x3d, 0x86, 0x77, 0x12,
0xfa, 0xc2, 0xd9, 0xd5, 0x67, 0x8b, 0x66, 0x50, 0xeb, 0x18, 0x8c, 0x26, 0x19, 0x91, 0xf5, 0x73, 0x94, 0xe9, 0xc4, 0xf7, 0x28, 0x41, 0x9f, 0x41, 0x69, 0x56, 0x43, 0x41, 0xbd, 0xdc, 0x34, 0x1b,
0xb5, 0x0e, 0x61, 0xef, 0xcc, 0xa5, 0xb3, 0xe3, 0xa4, 0xd1, 0x82, 0x0a, 0xe4, 0xfd, 0x17, 0x72, 0x4b, 0x55, 0x6d, 0xcc, 0x9d, 0xe6, 0x50, 0xeb, 0x08, 0x8c, 0x16, 0x19, 0x93, 0xcd, 0xab, 0x60,
0xfb, 0x2c, 0xcf, 0x51, 0x4c, 0x2c, 0x0c, 0x46, 0x1c, 0xae, 0x24, 0x7f, 0x09, 0x30, 0xd5, 0x41, 0x1d, 0xc0, 0xee, 0xa9, 0x4b, 0xe7, 0x85, 0xa6, 0x91, 0x43, 0x15, 0xf2, 0xfe, 0x0b, 0x79, 0x7c,
0xc5, 0xa2, 0x55, 0x9a, 0xe7, 0xb0, 0xd6, 0x6f, 0x1a, 0xec, 0x8a, 0x9a, 0x76, 0x03, 0x7f, 0x40, 0x96, 0xe7, 0x28, 0x36, 0x16, 0x06, 0x23, 0x0e, 0x57, 0x94, 0x3f, 0x07, 0x98, 0xf1, 0xa0, 0xc2,
0xe8, 0x54, 0xc1, 0x5d, 0xb8, 0x35, 0x45, 0x9d, 0x47, 0xe2, 0x71, 0x69, 0x1a, 0x3b, 0x75, 0xd0, 0x69, 0x1d, 0xe7, 0x05, 0xac, 0xf5, 0x8b, 0x06, 0x3b, 0xa2, 0xdb, 0xbd, 0xc0, 0x1f, 0x12, 0x3a,
0x31, 0x6c, 0x8f, 0xe5, 0x22, 0x51, 0xa5, 0x52, 0xc3, 0x88, 0xed, 0x18, 0x51, 0x46, 0xb0, 0xb7, 0x63, 0x70, 0x17, 0x6e, 0xcd, 0x50, 0x67, 0x11, 0x79, 0x5c, 0x9e, 0xd9, 0x4e, 0x1c, 0x74, 0x04,
0x54, 0xba, 0x6f, 0xa0, 0xb2, 0xa8, 0x58, 0x1d, 0xc2, 0x9c, 0x1e, 0x6d, 0x2d, 0x3d, 0x16, 0x85, 0xc5, 0x89, 0x74, 0x12, 0xfd, 0x2b, 0x37, 0x8d, 0xd8, 0x89, 0x51, 0xc8, 0x08, 0xf6, 0x9f, 0x37,
0xe2, 0xf4, 0x54, 0x36, 0xbf, 0x90, 0x87, 0x5c, 0xa7, 0xcd, 0x42, 0x2a, 0xf4, 0xdf, 0x6e, 0xec, 0xf5, 0x2b, 0xa8, 0x2e, 0xe7, 0xa2, 0xca, 0xb3, 0xc0, 0x54, 0xdb, 0x88, 0xa9, 0x45, 0xa1, 0x34,
0xc5, 0xb6, 0xed, 0x89, 0x8f, 0x58, 0x81, 0xac, 0x3f, 0x34, 0xd8, 0x56, 0x4a, 0x96, 0xee, 0x59, 0xab, 0xd7, 0xcd, 0x2f, 0xf1, 0x01, 0xe7, 0x69, 0xb3, 0x90, 0x8a, 0xb4, 0x6e, 0x37, 0x77, 0x63,
0x86, 0xec, 0xd8, 0x75, 0xc4, 0x5e, 0x59, 0xcc, 0x87, 0x08, 0x41, 0xce, 0x0e, 0x86, 0xd4, 0xcc, 0xc7, 0xf6, 0xc5, 0x47, 0xac, 0x40, 0xd6, 0x6f, 0x1a, 0x14, 0x15, 0x93, 0x95, 0x67, 0x56, 0x20,
0x8a, 0x0b, 0x21, 0xc6, 0x1c, 0x45, 0xbc, 0x2b, 0x33, 0x27, 0x42, 0x7c, 0x88, 0x3e, 0x86, 0x5c, 0x3b, 0x71, 0x1d, 0x71, 0x56, 0x16, 0xf3, 0x25, 0x42, 0x90, 0xb3, 0x83, 0x11, 0x35, 0xb3, 0xe2,
0x48, 0x89, 0x3c, 0xb0, 0x52, 0x63, 0x37, 0x26, 0xa4, 0x4f, 0x49, 0x80, 0x05, 0x80, 0x2f, 0x1d, 0xaa, 0x88, 0x35, 0x47, 0x11, 0xef, 0xd2, 0xcc, 0x09, 0x13, 0x5f, 0xa2, 0x0f, 0x21, 0x17, 0x52,
0xbc, 0x70, 0xcc, 0x82, 0x48, 0x86, 0x0f, 0x51, 0x15, 0x76, 0x18, 0x09, 0x2e, 0x5d, 0xcf, 0x1e, 0x12, 0x88, 0x42, 0x96, 0x9b, 0x3b, 0x31, 0x22, 0x03, 0x4a, 0x02, 0x2c, 0x00, 0xdc, 0x75, 0xf8,
0x99, 0xdb, 0xfb, 0xda, 0xc1, 0x0e, 0x9e, 0xce, 0xf9, 0x11, 0x90, 0x97, 0x2e, 0x3b, 0x57, 0x69, 0xc2, 0x51, 0x85, 0xe5, 0x4b, 0x54, 0x83, 0x6d, 0x46, 0x82, 0x0b, 0xd7, 0xb3, 0xc7, 0x66, 0x51,
0xee, 0xec, 0x6b, 0x07, 0x3a, 0x06, 0x1e, 0x92, 0xb9, 0x59, 0x18, 0x72, 0x7d, 0x45, 0x1b, 0xaa, 0xb4, 0x6d, 0xb6, 0xe7, 0x25, 0x20, 0x2f, 0x5d, 0x76, 0xa6, 0xd2, 0xdc, 0xde, 0xd3, 0xf6, 0x75,
0x84, 0x74, 0xcc, 0x87, 0x3c, 0x32, 0x54, 0x99, 0xe8, 0x98, 0x0f, 0xd1, 0x03, 0xb8, 0x6d, 0x3b, 0x0c, 0xdc, 0x24, 0x73, 0xb3, 0x30, 0xe4, 0x06, 0x2a, 0x6c, 0xa8, 0x12, 0xd2, 0x31, 0x5f, 0x72,
0x8e, 0xcb, 0x8d, 0xc9, 0x1e, 0xb5, 0x5d, 0x47, 0xe6, 0xa4, 0xe3, 0x58, 0xd4, 0x3a, 0x84, 0xdd, 0xcb, 0x48, 0x65, 0xa2, 0x63, 0xbe, 0x44, 0x0f, 0xe0, 0xb6, 0xed, 0x38, 0x2e, 0x17, 0x33, 0x7b,
0x36, 0x59, 0xdf, 0x6a, 0x3a, 0x50, 0x59, 0x84, 0xbf, 0xe1, 0xdf, 0xfc, 0x1c, 0x8c, 0xfe, 0xd8, 0xdc, 0x71, 0x1d, 0x99, 0x93, 0x8e, 0x63, 0x56, 0xeb, 0x00, 0x76, 0x3a, 0x64, 0x73, 0x79, 0xea,
0x49, 0x73, 0xae, 0x0d, 0x19, 0x6f, 0xbc, 0x48, 0xdc, 0x5e, 0xbb, 0x76, 0x48, 0xd7, 0xf7, 0x8f, 0x42, 0x75, 0x19, 0xfe, 0x86, 0xff, 0xf9, 0x73, 0x30, 0x06, 0x13, 0x27, 0x4d, 0xed, 0x6e, 0x18,
0x63, 0x30, 0x30, 0xa1, 0xe1, 0xe5, 0xfa, 0x2b, 0x7e, 0x84, 0x77, 0xdb, 0x24, 0xfe, 0xaf, 0x6f, 0xf1, 0xda, 0x8b, 0xc4, 0x25, 0xb9, 0x67, 0x87, 0x74, 0x73, 0x65, 0x39, 0x02, 0x03, 0x13, 0x1a,
0x9a, 0xd0, 0x87, 0x00, 0xea, 0x4f, 0x3a, 0x57, 0x25, 0x2e, 0xe2, 0xa2, 0x8a, 0x9c, 0x3a, 0xd6, 0x5e, 0x6c, 0xee, 0xf1, 0x3d, 0xbc, 0xdd, 0x21, 0x71, 0x15, 0xb8, 0x69, 0x42, 0xef, 0x03, 0xa8,
0xd7, 0x80, 0xe6, 0xf7, 0xda, 0xf8, 0x2f, 0xfd, 0x45, 0x83, 0x4a, 0xcf, 0x1d, 0x7a, 0xf6, 0xe8, 0x3f, 0xe9, 0x4c, 0xb5, 0xb8, 0x84, 0x4b, 0xca, 0x72, 0xe2, 0x58, 0x5f, 0x02, 0x5a, 0x3c, 0xeb,
0x2d, 0xe9, 0xfe, 0xef, 0xc6, 0xc5, 0xad, 0x48, 0x28, 0x10, 0xce, 0xa5, 0x63, 0x35, 0xb3, 0x5e, 0xc6, 0x7f, 0xe9, 0x8f, 0x1a, 0x54, 0xfb, 0xee, 0xc8, 0xb3, 0xc7, 0xff, 0x12, 0xef, 0x7f, 0x2e,
0x69, 0x50, 0x91, 0x9e, 0xff, 0x7f, 0x49, 0xe3, 0xf7, 0x9e, 0x3f, 0x0a, 0x2a, 0x4e, 0xde, 0x54, 0x69, 0x5c, 0x8a, 0x04, 0x03, 0xa1, 0x68, 0x3a, 0x56, 0x3b, 0xeb, 0x95, 0x06, 0x55, 0xf9, 0x1a,
0x81, 0xf5, 0xad, 0x7c, 0x93, 0xe6, 0xf8, 0x54, 0xe1, 0x3e, 0x87, 0xa8, 0xb6, 0x24, 0x7a, 0x62, 0xfc, 0x5f, 0xd4, 0xf8, 0xbd, 0xe7, 0xcf, 0x85, 0xb2, 0x93, 0x37, 0x65, 0x60, 0x7d, 0x2d, 0x5f,
0x96, 0x89, 0x9b, 0x01, 0x3f, 0xf9, 0x0a, 0x0a, 0xd2, 0x23, 0x50, 0x09, 0xb6, 0x4f, 0x70, 0xeb, 0xab, 0x85, 0x78, 0xaa, 0x71, 0x9f, 0x42, 0xd4, 0x5b, 0x12, 0x3d, 0x3e, 0xab, 0xc8, 0xcd, 0x81,
0xe1, 0x93, 0x56, 0xb3, 0xbc, 0xc5, 0x27, 0xb8, 0xdf, 0xe9, 0x9c, 0x76, 0xda, 0x65, 0x8d, 0x4f, 0x1f, 0x7d, 0x01, 0x05, 0xa9, 0x11, 0xa8, 0x0c, 0xc5, 0x63, 0xdc, 0x7e, 0xf8, 0xa4, 0xdd, 0xaa,
0x7a, 0x4f, 0xbe, 0xeb, 0x76, 0x5b, 0xcd, 0x72, 0x06, 0x01, 0x14, 0xba, 0x0f, 0xfb, 0xbd, 0x56, 0x6c, 0xf1, 0x0d, 0x1e, 0x74, 0xbb, 0x27, 0xdd, 0x4e, 0x45, 0xe3, 0x9b, 0xfe, 0x93, 0x6f, 0x7a,
0xb3, 0x9c, 0x6d, 0xfc, 0xba, 0x03, 0xe5, 0x56, 0xd4, 0xc5, 0xf4, 0x48, 0x70, 0xe5, 0x0e, 0x08, 0xbd, 0x76, 0xab, 0x92, 0x41, 0x00, 0x85, 0xde, 0xc3, 0x41, 0xbf, 0xdd, 0xaa, 0x64, 0x9b, 0x3f,
0x7a, 0x0a, 0x05, 0xf9, 0x72, 0xa3, 0xfb, 0xf1, 0x7c, 0x52, 0x3b, 0x8d, 0xea, 0x83, 0x9b, 0x60, 0x6d, 0x43, 0xa5, 0x1d, 0x4d, 0x3e, 0x7d, 0x12, 0x5c, 0xba, 0x43, 0x82, 0x9e, 0x42, 0x41, 0xbe,
0x2a, 0xc1, 0x16, 0xe4, 0xc5, 0xbb, 0x82, 0xee, 0x25, 0x0d, 0x3c, 0xd9, 0xf3, 0x54, 0x8d, 0xba, 0xe9, 0xe8, 0x7e, 0x3c, 0x9f, 0xd4, 0xe9, 0xa4, 0xf6, 0xe0, 0x3a, 0x98, 0x4a, 0xb0, 0x0d, 0x79,
0x6c, 0xa0, 0xea, 0x51, 0x03, 0x55, 0x6f, 0xf1, 0x06, 0x0a, 0xb5, 0xa1, 0x20, 0x8d, 0x23, 0xa1, 0xf1, 0xae, 0xa0, 0x7b, 0x49, 0x01, 0x4f, 0xce, 0x49, 0x35, 0xa3, 0x21, 0x87, 0xae, 0x46, 0x34,
0x2f, 0xdd, 0x4f, 0x96, 0x12, 0xb5, 0x20, 0x2f, 0xec, 0x20, 0xa1, 0x27, 0xd5, 0x24, 0x56, 0xe9, 0x74, 0x35, 0xda, 0x7c, 0xe8, 0x42, 0x1d, 0x28, 0x48, 0xe1, 0x48, 0xf0, 0x4b, 0xd7, 0x93, 0x95,
0x91, 0x26, 0x91, 0xd0, 0x93, 0xee, 0x1d, 0xab, 0x88, 0xe4, 0x5d, 0x4f, 0x10, 0xa5, 0xb7, 0x3d, 0x81, 0xda, 0x90, 0x17, 0x72, 0x90, 0xe0, 0x93, 0x2a, 0x12, 0xeb, 0xf8, 0x48, 0x91, 0x48, 0xf0,
0x4b, 0x89, 0x3a, 0x90, 0x6d, 0x13, 0x86, 0xac, 0x18, 0x4b, 0x8a, 0xdb, 0x57, 0x3f, 0x5a, 0x89, 0x49, 0xd7, 0x8e, 0x75, 0x81, 0xe4, 0x5d, 0x4f, 0x04, 0x4a, 0x1f, 0x88, 0x56, 0x06, 0xea, 0x42,
0x51, 0x85, 0xeb, 0x41, 0x8e, 0x5f, 0xd9, 0xc4, 0x39, 0xa5, 0xf6, 0x56, 0xd5, 0xfb, 0x37, 0xa0, 0xb6, 0x43, 0x18, 0xb2, 0x62, 0x51, 0x52, 0xd4, 0xbe, 0xf6, 0xc1, 0x5a, 0x8c, 0x6a, 0x5c, 0x1f,
0x14, 0xe9, 0x53, 0xb8, 0x35, 0xdf, 0x65, 0x24, 0xd4, 0xa6, 0x34, 0x4d, 0x09, 0xb5, 0xa9, 0x6d, 0x72, 0xfc, 0xca, 0x26, 0xea, 0x94, 0x3a, 0x75, 0xd5, 0xee, 0x5f, 0x83, 0x52, 0x41, 0x9f, 0xc2,
0xca, 0x63, 0x80, 0x99, 0x2d, 0xa2, 0xfd, 0x64, 0x82, 0x31, 0xd2, 0xbb, 0x2b, 0x10, 0x8a, 0xf2, 0xad, 0xc5, 0x29, 0x23, 0xc1, 0x36, 0x65, 0x9c, 0x4a, 0xb0, 0x4d, 0x1d, 0x53, 0x1e, 0x03, 0xcc,
0x0c, 0xf4, 0x05, 0x83, 0x44, 0x09, 0x21, 0x29, 0xf6, 0xb9, 0xb4, 0x3c, 0x67, 0xa0, 0x2f, 0x78, 0x65, 0x11, 0xed, 0x25, 0x13, 0x8c, 0x05, 0xbd, 0xbb, 0x06, 0xa1, 0x42, 0x9e, 0x82, 0xbe, 0x24,
0x5a, 0x82, 0x2d, 0xcd, 0xf1, 0x96, 0xb2, 0x7d, 0x0f, 0xfa, 0x82, 0x9f, 0x24, 0xd8, 0xd2, 0xdc, 0x90, 0x28, 0x41, 0x24, 0x45, 0x3e, 0x57, 0xb6, 0xe7, 0x14, 0xf4, 0x25, 0x4d, 0x4b, 0x44, 0x4b,
0xab, 0x7a, 0x6f, 0x35, 0x48, 0xe6, 0xfd, 0xe8, 0x83, 0xd7, 0xd7, 0xb5, 0xad, 0x3f, 0xaf, 0x6b, 0x53, 0xbc, 0x95, 0xd1, 0xbe, 0x05, 0x7d, 0x49, 0x4f, 0x12, 0xd1, 0xd2, 0xd4, 0xab, 0x76, 0x6f,
0x5b, 0xff, 0x5c, 0xd7, 0xb4, 0x57, 0x93, 0x9a, 0xf6, 0x7a, 0x52, 0xd3, 0x7e, 0x9f, 0xd4, 0xb4, 0x3d, 0x48, 0xe6, 0xfd, 0xe8, 0xbd, 0xd7, 0x57, 0xf5, 0xad, 0xdf, 0xaf, 0xea, 0x5b, 0x7f, 0x5d,
0xbf, 0x27, 0x35, 0xed, 0xa2, 0x20, 0x94, 0x7c, 0xf6, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x47, 0xd5, 0xb5, 0x57, 0xd3, 0xba, 0xf6, 0x7a, 0x5a, 0xd7, 0x7e, 0x9d, 0xd6, 0xb5, 0x3f, 0xa7, 0x75,
0xce, 0x74, 0xfe, 0x09, 0x0d, 0x00, 0x00, 0xed, 0xbc, 0x20, 0x98, 0x7c, 0xf2, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0xeb, 0x07, 0xf1, 0x5d,
0x3d, 0x0d, 0x00, 0x00,
} }

View File

@ -30,9 +30,10 @@ message StartContainerRequest {
message CreateContainerRequest { message CreateContainerRequest {
string id = 1 [(gogoproto.customname) = "ID"]; string id = 1 [(gogoproto.customname) = "ID"];
string bundle_path = 2; string bundle_path = 2;
string stdin = 3; bool console = 3;
string stdout = 4; string stdin = 4;
string stderr = 5; string stdout = 5;
string stderr = 6;
} }
message CreateContainerResponse { message CreateContainerResponse {
@ -54,9 +55,10 @@ message ListContainersResponse {
message StartProcessRequest { message StartProcessRequest {
string container_id = 1; string container_id = 1;
Process process = 2; Process process = 2;
string stdin = 3; bool console = 3;
string stdout = 4; string stdin = 4;
string stderr = 5; string stdout = 5;
string stderr = 6;
} }
message StartProcessResponse { message StartProcessResponse {

87
cmd/ctr/exec.go Normal file
View File

@ -0,0 +1,87 @@
package main
import (
"os"
"path/filepath"
gocontext "context"
"github.com/docker/containerd/api/execution"
"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
}
id := context.String("id")
tmpDir, err := getTempDir(id)
if err != nil {
return err
}
defer os.RemoveAll(tmpDir)
sOpts := &execution.StartProcessRequest{
ContainerId: id,
Process: &execution.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)
if err != nil {
return err
}
sr, err := executionService.StartProcess(gocontext.Background(), sOpts)
if err != nil {
return err
}
_, err = executionService.DeleteProcess(gocontext.Background(), &execution.DeleteProcessRequest{
Container: &execution.Container{
ID: id,
},
Process: sr.Process,
})
if err != nil {
return err
}
// Ensure we read all io
fwg.Wait()
return nil
},
}

View File

@ -14,12 +14,12 @@ func main() {
app.Name = "ctr" app.Name = "ctr"
app.Version = containerd.Version app.Version = containerd.Version
app.Usage = ` app.Usage = `
__ __
_____/ /______ _____/ /______
/ ___/ __/ ___/ / ___/ __/ ___/
/ /__/ /_/ / / /__/ /_/ /
\___/\__/_/ \___/\__/_/
containerd client containerd client
` `
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
@ -35,6 +35,7 @@ containerd client
} }
app.Commands = []cli.Command{ app.Commands = []cli.Command{
runCommand, runCommand,
execCommand,
} }
app.Before = func(context *cli.Context) error { app.Before = func(context *cli.Context) error {
if context.GlobalBool("debug") { if context.GlobalBool("debug") {

View File

@ -2,23 +2,13 @@ package main
import ( import (
"fmt" "fmt"
"io"
"io/ioutil"
"log"
"net"
"os" "os"
"path/filepath" "path/filepath"
"sync"
"syscall"
"time" "time"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
gocontext "context" gocontext "context"
"github.com/docker/containerd/api/execution" "github.com/docker/containerd/api/execution"
"github.com/tonistiigi/fifo"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@ -47,6 +37,10 @@ var runCommand = cli.Command{
Name: "bundle, b", Name: "bundle, b",
Usage: "path to the container's bundle", Usage: "path to the container's bundle",
}, },
cli.BoolFlag{
Name: "tty, t",
Usage: "allocate a TTY for the container",
},
}, },
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
// var config runConfig // var config runConfig
@ -71,6 +65,7 @@ var runCommand = cli.Command{
crOpts := &execution.CreateContainerRequest{ crOpts := &execution.CreateContainerRequest{
ID: id, ID: id,
BundlePath: context.String("bundle"), BundlePath: context.String("bundle"),
Console: context.Bool("tty"),
Stdin: filepath.Join(tmpDir, "stdin"), Stdin: filepath.Join(tmpDir, "stdin"),
Stdout: filepath.Join(tmpDir, "stdout"), Stdout: filepath.Join(tmpDir, "stdout"),
Stderr: filepath.Join(tmpDir, "stderr"), Stderr: filepath.Join(tmpDir, "stderr"),
@ -118,103 +113,3 @@ var runCommand = cli.Command{
return nil return nil
}, },
} }
var grpcConn *grpc.ClientConn
func prepareStdio(in, out, err string) (*sync.WaitGroup, error) {
var (
wg sync.WaitGroup
dst io.Writer
src io.Reader
close func()
)
for _, f := range []struct {
name string
flags int
src bool
reader io.Reader
writer io.Writer
}{
{in, syscall.O_WRONLY | syscall.O_CREAT | syscall.O_NONBLOCK, false, os.Stdin, nil},
{out, syscall.O_RDONLY | syscall.O_CREAT | syscall.O_NONBLOCK, true, nil, os.Stdout},
{err, syscall.O_RDONLY | syscall.O_CREAT | syscall.O_NONBLOCK, true, nil, os.Stderr},
} {
ff, err := fifo.OpenFifo(gocontext.Background(), f.name, f.flags, 0700)
if err != nil {
return nil, err
}
defer func(c io.Closer) {
if err != nil {
c.Close()
}
}(ff)
if f.src {
src = ff
dst = f.writer
close = func() {
ff.Close()
wg.Done()
}
wg.Add(1)
} else {
src = f.reader
dst = ff
close = func() { ff.Close() }
}
go func(dst io.Writer, src io.Reader, close func()) {
io.Copy(dst, src)
close()
}(dst, src, close)
}
return &wg, nil
}
func getGRPCConnection(context *cli.Context) (*grpc.ClientConn, error) {
if grpcConn != nil {
return grpcConn, nil
}
bindSocket := context.GlobalString("socket")
// 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", bindSocket, timeout)
},
))
conn, err := grpc.Dial(fmt.Sprintf("unix://%s", bindSocket), dialOpts...)
if err != nil {
return nil, err
}
grpcConn = conn
return grpcConn, nil
}
func getExecutionService(context *cli.Context) (execution.ExecutionServiceClient, error) {
conn, err := getGRPCConnection(context)
if err != nil {
return nil, err
}
return execution.NewExecutionServiceClient(conn), nil
}
func getTempDir(id string) (string, error) {
err := os.MkdirAll(filepath.Join(os.TempDir(), "ctr"), 0700)
if err != nil {
return "", err
}
tmpDir, err := ioutil.TempDir(filepath.Join(os.TempDir(), "ctr"), fmt.Sprintf("%s-", id))
if err != nil {
return "", err
}
return tmpDir, nil
}

122
cmd/ctr/utils.go Normal file
View File

@ -0,0 +1,122 @@
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"net"
"os"
"path/filepath"
"sync"
"syscall"
"time"
gocontext "context"
"github.com/docker/containerd/api/execution"
"github.com/tonistiigi/fifo"
"github.com/urfave/cli"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
)
var grpcConn *grpc.ClientConn
func prepareStdio(in, out, err string) (*sync.WaitGroup, error) {
var (
wg sync.WaitGroup
dst io.Writer
src io.Reader
close func()
)
for _, f := range []struct {
name string
flags int
src bool
reader io.Reader
writer io.Writer
}{
{in, syscall.O_WRONLY | syscall.O_CREAT | syscall.O_NONBLOCK, false, os.Stdin, nil},
{out, syscall.O_RDONLY | syscall.O_CREAT | syscall.O_NONBLOCK, true, nil, os.Stdout},
{err, syscall.O_RDONLY | syscall.O_CREAT | syscall.O_NONBLOCK, true, nil, os.Stderr},
} {
ff, err := fifo.OpenFifo(gocontext.Background(), f.name, f.flags, 0700)
if err != nil {
return nil, err
}
defer func(c io.Closer) {
if err != nil {
c.Close()
}
}(ff)
if f.src {
src = ff
dst = f.writer
close = func() {
ff.Close()
wg.Done()
}
wg.Add(1)
} else {
src = f.reader
dst = ff
close = func() { ff.Close() }
}
go func(dst io.Writer, src io.Reader, close func()) {
io.Copy(dst, src)
close()
}(dst, src, close)
}
return &wg, nil
}
func getGRPCConnection(context *cli.Context) (*grpc.ClientConn, error) {
if grpcConn != nil {
return grpcConn, nil
}
bindSocket := context.GlobalString("socket")
// 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", bindSocket, timeout)
},
))
conn, err := grpc.Dial(fmt.Sprintf("unix://%s", bindSocket), dialOpts...)
if err != nil {
return nil, err
}
grpcConn = conn
return grpcConn, nil
}
func getExecutionService(context *cli.Context) (execution.ExecutionServiceClient, error) {
conn, err := getGRPCConnection(context)
if err != nil {
return nil, err
}
return execution.NewExecutionServiceClient(conn), nil
}
func getTempDir(id string) (string, error) {
err := os.MkdirAll(filepath.Join(os.TempDir(), "ctr"), 0700)
if err != nil {
return "", err
}
tmpDir, err := ioutil.TempDir(filepath.Join(os.TempDir(), "ctr"), fmt.Sprintf("%s-", id))
if err != nil {
return "", err
}
return tmpDir, nil
}

View File

@ -7,17 +7,19 @@ import (
) )
type CreateOpts struct { type CreateOpts struct {
Bundle string Bundle string
Stdin string Console bool
Stdout string Stdin string
Stderr string Stdout string
Stderr string
} }
type CreateProcessOpts struct { type StartProcessOpts struct {
Spec specs.Process Spec specs.Process
Stdin string Console bool
Stdout string Stdin string
Stderr string Stdout string
Stderr string
} }
type Executor interface { type Executor interface {
@ -30,7 +32,7 @@ type Executor interface {
Delete(*Container) error Delete(*Container) error
Start(*Container) error Start(*Container) error
StartProcess(*Container, CreateProcessOpts) (Process, error) StartProcess(*Container, StartProcessOpts) (Process, error)
SignalProcess(*Container, string, os.Signal) error SignalProcess(*Container, string, os.Signal) error
DeleteProcess(*Container, string) error DeleteProcess(*Container, string) error
} }

View File

@ -0,0 +1,54 @@
package oci
import (
"fmt"
"os"
"syscall"
"unsafe"
)
// NewConsole returns an initialized console that can be used within a container by copying bytes
// from the master side to the slave that is attached as the tty for the container's init process.
func newConsole(uid, gid int) (*os.File, string, error) {
master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
if err != nil {
return nil, "", err
}
console, err := ptsname(master)
if err != nil {
return nil, "", err
}
if err := unlockpt(master); err != nil {
return nil, "", err
}
if err := os.Chmod(console, 0600); err != nil {
return nil, "", err
}
if err := os.Chown(console, uid, gid); err != nil {
return nil, "", err
}
return master, console, nil
}
func ioctl(fd uintptr, flag, data uintptr) error {
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, flag, data); err != 0 {
return err
}
return nil
}
// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
// unlockpt should be called before opening the slave side of a pty.
func unlockpt(f *os.File) error {
var u int32
return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u)))
}
// ptsname retrieves the name of the first available pts for the given master.
func ptsname(f *os.File) (string, error) {
var n int32
if err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))); err != nil {
return "", err
}
return fmt.Sprintf("/dev/pts/%d", n), nil
}

View File

@ -3,6 +3,7 @@ package oci
import ( import (
"errors" "errors"
"fmt" "fmt"
"io"
"os" "os"
"path/filepath" "path/filepath"
"syscall" "syscall"
@ -62,16 +63,43 @@ func getRuncIO(stdin, stdout, stderr string) (io runc.IO, err error) {
return return
} }
func setupConsole(rio runc.IO) (*os.File, string, error) {
master, console, err := newConsole(0, 0)
if err != nil {
return nil, "", err
}
go io.Copy(master, rio.Stdin)
go func() {
io.Copy(rio.Stdout, master)
master.Close()
}()
return master, console, nil
}
func (r *OCIRuntime) Create(id string, o execution.CreateOpts) (container *execution.Container, err error) { func (r *OCIRuntime) Create(id string, o execution.CreateOpts) (container *execution.Container, err error) {
io, err := getRuncIO(o.Stdin, o.Stdout, o.Stderr) rio, err := getRuncIO(o.Stdin, o.Stdout, o.Stderr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer func() { defer func() {
if err != nil { if err != nil {
closeRuncIO(io) closeRuncIO(rio)
} }
}() }()
consolePath := ""
if o.Console {
master, console, err := setupConsole(rio)
if err != nil {
return nil, err
}
consolePath = console
defer func() {
if err != nil {
master.Close()
}
}()
}
if container, err = execution.NewContainer(r.root, id, o.Bundle, "created"); err != nil { if container, err = execution.NewContainer(r.root, id, o.Bundle, "created"); err != nil {
return nil, err return nil, err
@ -89,7 +117,8 @@ func (r *OCIRuntime) Create(id string, o execution.CreateOpts) (container *execu
pidFile := filepath.Join(initDir, "pid") pidFile := filepath.Join(initDir, "pid")
err = r.runc.Create(id, o.Bundle, &runc.CreateOpts{ err = r.runc.Create(id, o.Bundle, &runc.CreateOpts{
PidFile: pidFile, PidFile: pidFile,
IO: io, Console: consolePath,
IO: rio,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -112,7 +141,7 @@ func (r *OCIRuntime) Create(id string, o execution.CreateOpts) (container *execu
container.AddProcess(process, true) container.AddProcess(process, true)
r.ios[id] = io r.ios[id] = rio
return container, nil return container, nil
} }
@ -145,6 +174,10 @@ func (r *OCIRuntime) load(runcC *runc.Container) (*execution.Container, error) {
for _, d := range dirs { for _, d := range dirs {
pid, err := runc.ReadPidFile(filepath.Join(d, "pid")) pid, err := runc.ReadPidFile(filepath.Join(d, "pid"))
if err != nil { if err != nil {
if os.IsNotExist(err) {
// Process died in between
continue
}
return nil, err return nil, err
} }
process, err := newProcess(filepath.Base(d), pid) process, err := newProcess(filepath.Base(d), pid)
@ -203,16 +236,29 @@ func (r *OCIRuntime) Resume(c *execution.Container) error {
return r.runc.Resume(c.ID()) return r.runc.Resume(c.ID())
} }
func (r *OCIRuntime) StartProcess(c *execution.Container, o execution.CreateProcessOpts) (p execution.Process, err error) { func (r *OCIRuntime) StartProcess(c *execution.Container, o execution.StartProcessOpts) (p execution.Process, err error) {
io, err := getRuncIO(o.Stdin, o.Stdout, o.Stderr) rio, err := getRuncIO(o.Stdin, o.Stdout, o.Stderr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer func() { defer func() {
if err != nil { if err != nil {
closeRuncIO(io) closeRuncIO(rio)
} }
}() }()
consolePath := ""
if o.Console {
master, console, err := setupConsole(rio)
if err != nil {
return nil, err
}
consolePath = console
defer func() {
if err != nil {
master.Close()
}
}()
}
processStateDir, err := c.StateDir().NewProcess() processStateDir, err := c.StateDir().NewProcess()
if err != nil { if err != nil {
@ -227,8 +273,10 @@ func (r *OCIRuntime) StartProcess(c *execution.Container, o execution.CreateProc
pidFile := filepath.Join(processStateDir, "pid") pidFile := filepath.Join(processStateDir, "pid")
if err := r.runc.ExecProcess(c.ID(), o.Spec, &runc.ExecOpts{ if err := r.runc.ExecProcess(c.ID(), o.Spec, &runc.ExecOpts{
PidFile: pidFile, PidFile: pidFile,
Detach: true, Detach: false,
IO: io, Console: consolePath,
Cwd: o.Spec.Cwd,
IO: rio,
}); err != nil { }); err != nil {
return nil, err return nil, err
} }
@ -244,7 +292,7 @@ func (r *OCIRuntime) StartProcess(c *execution.Container, o execution.CreateProc
c.AddProcess(process, false) c.AddProcess(process, false)
r.ios[fmt.Sprintf("%s-%s", c.ID(), process.ID())] = io r.ios[fmt.Sprintf("%s-%s", c.ID(), process.ID())] = rio
return process, nil return process, nil
} }

View File

@ -10,7 +10,10 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
) )
var emptyResponse = &google_protobuf.Empty{} var (
emptyResponse = &google_protobuf.Empty{}
ErrProcessNotFound = fmt.Errorf("Process not found")
)
func New(executor Executor) (*Service, error) { func New(executor Executor) (*Service, error) {
return &Service{ return &Service{
@ -28,10 +31,11 @@ func (s *Service) Create(ctx context.Context, r *api.CreateContainerRequest) (*a
var err error var err error
container, err := s.executor.Create(r.ID, CreateOpts{ container, err := s.executor.Create(r.ID, CreateOpts{
Bundle: r.BundlePath, Bundle: r.BundlePath,
Stdin: r.Stdin, Console: r.Console,
Stdout: r.Stdout, Stdin: r.Stdin,
Stderr: r.Stderr, Stdout: r.Stdout,
Stderr: r.Stderr,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -112,12 +116,24 @@ func (s *Service) StartProcess(ctx context.Context, r *api.StartProcessRequest)
} }
// TODO: generate spec // TODO: generate spec
var spec specs.Process spec := specs.Process{
process, err := s.executor.StartProcess(container, CreateProcessOpts{ Terminal: r.Process.Terminal,
Spec: spec, ConsoleSize: specs.Box{
Stdin: r.Stdin, 80,
Stdout: r.Stdout, 80,
Stderr: r.Stderr, },
Args: r.Process.Args,
Env: r.Process.Env,
Cwd: r.Process.Cwd,
NoNewPrivileges: true,
}
process, err := s.executor.StartProcess(container, StartProcessOpts{
Spec: spec,
Console: r.Console,
Stdin: r.Stdin,
Stdout: r.Stdout,
Stderr: r.Stderr,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -137,7 +153,7 @@ func (s *Service) GetProcess(ctx context.Context, r *api.GetProcessRequest) (*ap
} }
process := container.GetProcess(r.ProcessId) process := container.GetProcess(r.ProcessId)
if process == nil { if process == nil {
return nil, fmt.Errorf("Make me a constant! Process not foumd!") return nil, ErrProcessNotFound
} }
return &api.GetProcessResponse{ return &api.GetProcessResponse{
Process: toGRPCProcess(process), Process: toGRPCProcess(process),