cmd/ctr, service/containers: implement container filter
Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
parent
3332042ab6
commit
396d89e423
@ -125,7 +125,17 @@ func (*GetContainerResponse) ProtoMessage() {}
|
||||
func (*GetContainerResponse) Descriptor() ([]byte, []int) { return fileDescriptorContainers, []int{2} }
|
||||
|
||||
type ListContainersRequest struct {
|
||||
Filter string `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"`
|
||||
// Filters contains one or more filters using the syntax defined in the
|
||||
// containerd filter package.
|
||||
//
|
||||
// The returned result will be those that match any of the provided
|
||||
// filters. Expanded, containers that match the following will be
|
||||
// returned:
|
||||
//
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
//
|
||||
// If filters is zero-length or nil, all items will be returned.
|
||||
Filters []string `protobuf:"bytes,1,rep,name=filters" json:"filters,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ListContainersRequest) Reset() { *m = ListContainersRequest{} }
|
||||
@ -601,11 +611,20 @@ func (m *ListContainersRequest) MarshalTo(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Filter) > 0 {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintContainers(dAtA, i, uint64(len(m.Filter)))
|
||||
i += copy(dAtA[i:], m.Filter)
|
||||
if len(m.Filters) > 0 {
|
||||
for _, s := range m.Filters {
|
||||
dAtA[i] = 0xa
|
||||
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)
|
||||
}
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -878,9 +897,11 @@ func (m *GetContainerResponse) Size() (n int) {
|
||||
func (m *ListContainersRequest) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Filter)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovContainers(uint64(l))
|
||||
if len(m.Filters) > 0 {
|
||||
for _, s := range m.Filters {
|
||||
l = len(s)
|
||||
n += 1 + l + sovContainers(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
@ -1019,7 +1040,7 @@ func (this *ListContainersRequest) String() string {
|
||||
return "nil"
|
||||
}
|
||||
s := strings.Join([]string{`&ListContainersRequest{`,
|
||||
`Filter:` + fmt.Sprintf("%v", this.Filter) + `,`,
|
||||
`Filters:` + fmt.Sprintf("%v", this.Filters) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
@ -1774,7 +1795,7 @@ func (m *ListContainersRequest) Unmarshal(dAtA []byte) error {
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Filter", wireType)
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Filters", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
@ -1799,7 +1820,7 @@ func (m *ListContainersRequest) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Filter = string(dAtA[iNdEx:postIndex])
|
||||
m.Filters = append(m.Filters, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
@ -2445,52 +2466,52 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptorContainers = []byte{
|
||||
// 738 bytes of a gzipped FileDescriptorProto
|
||||
// 742 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcd, 0x6e, 0xd3, 0x4a,
|
||||
0x14, 0xae, 0x93, 0xd4, 0x69, 0x4e, 0x36, 0x57, 0x73, 0x73, 0x73, 0x8d, 0x91, 0x92, 0x90, 0x55,
|
||||
0x16, 0x60, 0xd3, 0x80, 0xa0, 0x3f, 0xab, 0xa6, 0x7f, 0x42, 0x6a, 0x51, 0x35, 0xc0, 0x06, 0x16,
|
||||
0xc5, 0x49, 0x26, 0xa9, 0x89, 0xe3, 0x31, 0x9e, 0x49, 0xa4, 0x88, 0x05, 0x3c, 0x02, 0x6f, 0xc1,
|
||||
0x16, 0xe0, 0xd0, 0x80, 0xa0, 0x3f, 0xab, 0xa6, 0x7f, 0x42, 0x6a, 0x51, 0x35, 0xc0, 0x06, 0x16,
|
||||
0xc5, 0x49, 0x26, 0xa9, 0x89, 0xed, 0x31, 0x9e, 0x49, 0xa4, 0x88, 0x05, 0x3c, 0x02, 0x6f, 0xc1,
|
||||
0x53, 0xb0, 0xef, 0x92, 0x25, 0xab, 0xd2, 0xe6, 0x49, 0x90, 0xc7, 0xe3, 0x3a, 0xe4, 0x47, 0x38,
|
||||
0x85, 0xee, 0xe6, 0x78, 0xce, 0xf7, 0x9d, 0x33, 0xdf, 0x7c, 0x67, 0x64, 0x38, 0xea, 0xda, 0xfc,
|
||||
0x6c, 0xd0, 0x34, 0x5a, 0xb4, 0x6f, 0xb6, 0xa8, 0xcb, 0x2d, 0xdb, 0x25, 0x7e, 0x7b, 0x72, 0x69,
|
||||
0x79, 0xb6, 0xc9, 0x88, 0x3f, 0xb4, 0x5b, 0x84, 0xc5, 0xdf, 0x99, 0x39, 0x5c, 0x9f, 0x88, 0x0c,
|
||||
0xcf, 0xa7, 0x9c, 0xa2, 0x7b, 0x31, 0xce, 0x88, 0x30, 0xc6, 0x44, 0xd6, 0x70, 0x5d, 0x2f, 0x74,
|
||||
0x69, 0x97, 0x8a, 0x6c, 0x33, 0x58, 0x85, 0x40, 0xfd, 0x4e, 0x97, 0xd2, 0xae, 0x43, 0x4c, 0x11,
|
||||
0x35, 0x07, 0x1d, 0xd3, 0x72, 0x47, 0x72, 0xeb, 0xee, 0xf4, 0x16, 0xe9, 0x7b, 0x3c, 0xda, 0xac,
|
||||
0x4c, 0x6f, 0x76, 0x6c, 0xe2, 0xb4, 0x4f, 0xfb, 0x16, 0xeb, 0xc9, 0x8c, 0xf2, 0x74, 0x06, 0xb7,
|
||||
0xfb, 0x84, 0x71, 0xab, 0xef, 0xc9, 0x84, 0xed, 0x44, 0x0a, 0xf0, 0x91, 0x47, 0x98, 0xd9, 0x26,
|
||||
0xac, 0xe5, 0xdb, 0x1e, 0xa7, 0x7e, 0x08, 0xae, 0x7e, 0xcd, 0x40, 0x6e, 0x37, 0xca, 0x44, 0x45,
|
||||
0x48, 0xd9, 0x6d, 0x4d, 0xa9, 0x28, 0xb5, 0x5c, 0x43, 0x1d, 0x5f, 0x94, 0x53, 0xcf, 0xf6, 0x70,
|
||||
0xca, 0x6e, 0xa3, 0x13, 0x50, 0x1d, 0xab, 0x49, 0x1c, 0xa6, 0xa5, 0x2a, 0xe9, 0x5a, 0xbe, 0xbe,
|
||||
0x61, 0xfc, 0x56, 0x27, 0xe3, 0x9a, 0xd5, 0x38, 0x12, 0xd0, 0x7d, 0x97, 0xfb, 0x23, 0x2c, 0x79,
|
||||
0x50, 0x01, 0x56, 0xed, 0xbe, 0xd5, 0x25, 0x5a, 0x3a, 0x28, 0x86, 0xc3, 0x00, 0x3d, 0x87, 0xac,
|
||||
0x3f, 0x70, 0x83, 0x03, 0x6a, 0x99, 0x8a, 0x52, 0xcb, 0xd7, 0x1f, 0x2f, 0x55, 0x08, 0x87, 0x58,
|
||||
0x1c, 0x91, 0xa0, 0x1a, 0x64, 0x98, 0x47, 0x5a, 0xda, 0xaa, 0x20, 0x2b, 0x18, 0xa1, 0x94, 0x46,
|
||||
0x24, 0xa5, 0xb1, 0xe3, 0x8e, 0xb0, 0xc8, 0x40, 0x55, 0x50, 0x7d, 0x4a, 0x79, 0x87, 0x69, 0xaa,
|
||||
0x38, 0x3d, 0x8c, 0x2f, 0xca, 0x2a, 0xa6, 0x94, 0x1f, 0xbc, 0xc0, 0x72, 0x07, 0xed, 0x02, 0xb4,
|
||||
0x7c, 0x62, 0x71, 0xd2, 0x3e, 0xb5, 0xb8, 0x96, 0x15, 0x9c, 0xfa, 0x0c, 0xe7, 0xcb, 0xe8, 0x7a,
|
||||
0x1a, 0x6b, 0xe7, 0x17, 0xe5, 0x95, 0xcf, 0x3f, 0xca, 0x0a, 0xce, 0x49, 0xdc, 0x0e, 0x0f, 0x48,
|
||||
0x06, 0x5e, 0x3b, 0x22, 0x59, 0x5b, 0x86, 0x44, 0xe2, 0x76, 0xb8, 0xbe, 0x09, 0xf9, 0x09, 0x51,
|
||||
0xd1, 0x3f, 0x90, 0xee, 0x91, 0x51, 0x78, 0x6f, 0x38, 0x58, 0x06, 0xf2, 0x0e, 0x2d, 0x67, 0x40,
|
||||
0xb4, 0x54, 0x28, 0xaf, 0x08, 0xb6, 0x52, 0x1b, 0x8a, 0x7e, 0x0c, 0x59, 0x29, 0x13, 0x42, 0x90,
|
||||
0x71, 0xad, 0x3e, 0x91, 0x38, 0xb1, 0x46, 0x06, 0x64, 0xa9, 0xc7, 0x6d, 0xea, 0x32, 0x01, 0x5d,
|
||||
0x85, 0xee, 0xe6, 0x78, 0xce, 0xf7, 0x9d, 0x33, 0xdf, 0x7c, 0x67, 0x64, 0x38, 0xea, 0x59, 0xfc,
|
||||
0x6c, 0xd0, 0x32, 0xda, 0xd4, 0xa9, 0xb7, 0xa9, 0xcb, 0x4d, 0xcb, 0x25, 0x7e, 0x67, 0x72, 0x69,
|
||||
0x7a, 0x56, 0x9d, 0x11, 0x7f, 0x68, 0xb5, 0x09, 0x8b, 0xbf, 0xb3, 0xfa, 0x70, 0x7d, 0x22, 0x32,
|
||||
0x3c, 0x9f, 0x72, 0x8a, 0xee, 0xc5, 0x38, 0x23, 0xc2, 0x18, 0x13, 0x59, 0xc3, 0x75, 0xbd, 0xd0,
|
||||
0xa3, 0x3d, 0x2a, 0xb2, 0xeb, 0xc1, 0x2a, 0x04, 0xea, 0x77, 0x7a, 0x94, 0xf6, 0x6c, 0x52, 0x17,
|
||||
0x51, 0x6b, 0xd0, 0xad, 0x9b, 0xee, 0x48, 0x6e, 0xdd, 0x9d, 0xde, 0x22, 0x8e, 0xc7, 0xa3, 0xcd,
|
||||
0xca, 0xf4, 0x66, 0xd7, 0x22, 0x76, 0xe7, 0xd4, 0x31, 0x59, 0x5f, 0x66, 0x94, 0xa7, 0x33, 0xb8,
|
||||
0xe5, 0x10, 0xc6, 0x4d, 0xc7, 0x93, 0x09, 0xdb, 0x89, 0x14, 0xe0, 0x23, 0x8f, 0xb0, 0x7a, 0x87,
|
||||
0xb0, 0xb6, 0x6f, 0x79, 0x9c, 0xfa, 0x21, 0xb8, 0xfa, 0x35, 0x03, 0xb9, 0xdd, 0x28, 0x13, 0x15,
|
||||
0x21, 0x65, 0x75, 0x34, 0xa5, 0xa2, 0xd4, 0x72, 0x4d, 0x75, 0x7c, 0x51, 0x4e, 0x3d, 0xdb, 0xc3,
|
||||
0x29, 0xab, 0x83, 0x4e, 0x40, 0xb5, 0xcd, 0x16, 0xb1, 0x99, 0x96, 0xaa, 0xa4, 0x6b, 0xf9, 0xc6,
|
||||
0x86, 0xf1, 0x5b, 0x9d, 0x8c, 0x6b, 0x56, 0xe3, 0x48, 0x40, 0xf7, 0x5d, 0xee, 0x8f, 0xb0, 0xe4,
|
||||
0x41, 0x05, 0x58, 0xb5, 0x1c, 0xb3, 0x47, 0xb4, 0x74, 0x50, 0x0c, 0x87, 0x01, 0x7a, 0x0e, 0x59,
|
||||
0x7f, 0xe0, 0x06, 0x07, 0xd4, 0x32, 0x15, 0xa5, 0x96, 0x6f, 0x3c, 0x5e, 0xaa, 0x10, 0x0e, 0xb1,
|
||||
0x38, 0x22, 0x41, 0x35, 0xc8, 0x30, 0x8f, 0xb4, 0xb5, 0x55, 0x41, 0x56, 0x30, 0x42, 0x29, 0x8d,
|
||||
0x48, 0x4a, 0x63, 0xc7, 0x1d, 0x61, 0x91, 0x81, 0xaa, 0xa0, 0xfa, 0x94, 0xf2, 0x2e, 0xd3, 0x54,
|
||||
0x71, 0x7a, 0x18, 0x5f, 0x94, 0x55, 0x4c, 0x29, 0x3f, 0x78, 0x81, 0xe5, 0x0e, 0xda, 0x05, 0x68,
|
||||
0xfb, 0xc4, 0xe4, 0xa4, 0x73, 0x6a, 0x72, 0x2d, 0x2b, 0x38, 0xf5, 0x19, 0xce, 0x97, 0xd1, 0xf5,
|
||||
0x34, 0xd7, 0xce, 0x2f, 0xca, 0x2b, 0x9f, 0x7f, 0x94, 0x15, 0x9c, 0x93, 0xb8, 0x1d, 0x1e, 0x90,
|
||||
0x0c, 0xbc, 0x4e, 0x44, 0xb2, 0xb6, 0x0c, 0x89, 0xc4, 0xed, 0x70, 0x7d, 0x13, 0xf2, 0x13, 0xa2,
|
||||
0xa2, 0x7f, 0x20, 0xdd, 0x27, 0xa3, 0xf0, 0xde, 0x70, 0xb0, 0x0c, 0xe4, 0x1d, 0x9a, 0xf6, 0x80,
|
||||
0x68, 0xa9, 0x50, 0x5e, 0x11, 0x6c, 0xa5, 0x36, 0x14, 0xfd, 0x18, 0xb2, 0x52, 0x26, 0x84, 0x20,
|
||||
0xe3, 0x9a, 0x0e, 0x91, 0x38, 0xb1, 0x46, 0x06, 0x64, 0xa9, 0xc7, 0x2d, 0xea, 0x32, 0x01, 0x5d,
|
||||
0x24, 0x5a, 0x94, 0x54, 0x7d, 0x00, 0xff, 0x1e, 0x12, 0x7e, 0x7d, 0x05, 0x98, 0xbc, 0x1f, 0x10,
|
||||
0xc6, 0x17, 0x19, 0xa9, 0x7a, 0x06, 0x85, 0x5f, 0xd3, 0x99, 0x47, 0x5d, 0x46, 0xd0, 0x09, 0xe4,
|
||||
0xae, 0x2f, 0x55, 0xc0, 0xf2, 0xf5, 0xfb, 0xcb, 0x5c, 0x7d, 0x23, 0x13, 0xc8, 0x84, 0x63, 0x92,
|
||||
0xaa, 0x09, 0xff, 0x1d, 0xd9, 0x2c, 0x2e, 0xc5, 0xe2, 0xd6, 0xd4, 0x8e, 0xed, 0x70, 0x59, 0x27,
|
||||
0x87, 0x65, 0x54, 0x75, 0xa0, 0x38, 0x0d, 0x90, 0xcd, 0x61, 0x80, 0xb8, 0xac, 0xa6, 0x88, 0x09,
|
||||
0xb8, 0x49, 0x77, 0x13, 0x2c, 0xd5, 0x77, 0x50, 0xdc, 0x15, 0x9e, 0x98, 0x91, 0xee, 0xef, 0x4b,
|
||||
0xd1, 0x83, 0xff, 0x67, 0x6a, 0xdd, 0x9a, 0xee, 0x5f, 0x14, 0x28, 0xbe, 0x12, 0x46, 0xbd, 0xfd,
|
||||
0x93, 0xa1, 0x6d, 0xc8, 0x87, 0x43, 0x21, 0x1e, 0x4c, 0xe9, 0xd8, 0xd9, 0x69, 0x3a, 0x08, 0xde,
|
||||
0xd4, 0x63, 0x8b, 0xf5, 0xb0, 0x9c, 0xbd, 0x60, 0x1d, 0xc8, 0x32, 0xd3, 0xe8, 0xad, 0xc9, 0xf2,
|
||||
0x10, 0x8a, 0x7b, 0xc4, 0x21, 0x73, 0x54, 0x59, 0x30, 0x2a, 0xf5, 0xcb, 0x0c, 0x40, 0x6c, 0x46,
|
||||
0x34, 0x84, 0xf4, 0x21, 0xe1, 0xe8, 0x49, 0x82, 0x36, 0xe6, 0x0c, 0xa4, 0xfe, 0x74, 0x69, 0x9c,
|
||||
0x94, 0xe2, 0x03, 0x64, 0x82, 0xb1, 0x40, 0x49, 0x9e, 0xfc, 0xb9, 0x03, 0xa7, 0x6f, 0xde, 0x00,
|
||||
0x29, 0x8b, 0x7f, 0x04, 0x35, 0x74, 0x2e, 0x4a, 0x42, 0x32, 0x7f, 0xa0, 0xf4, 0xad, 0x9b, 0x40,
|
||||
0xe3, 0x06, 0x42, 0x8f, 0x24, 0x6a, 0x60, 0xbe, 0xef, 0x13, 0x35, 0xb0, 0xc8, 0x89, 0x6f, 0x40,
|
||||
0x0d, 0x7d, 0x93, 0xa8, 0x81, 0xf9, 0x16, 0xd3, 0x8b, 0x33, 0x13, 0xb1, 0x1f, 0xfc, 0x82, 0x34,
|
||||
0xde, 0x9e, 0x5f, 0x95, 0x56, 0xbe, 0x5f, 0x95, 0x56, 0x3e, 0x8d, 0x4b, 0xca, 0xf9, 0xb8, 0xa4,
|
||||
0x7c, 0x1b, 0x97, 0x94, 0xcb, 0x71, 0x49, 0x79, 0x7d, 0xf0, 0x07, 0x7f, 0x55, 0xdb, 0x71, 0xd4,
|
||||
0x54, 0x45, 0xc5, 0x47, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x07, 0x2d, 0x75, 0x3c, 0xa6, 0x09,
|
||||
0x00, 0x00,
|
||||
0xae, 0x2f, 0x55, 0xc0, 0xf2, 0x8d, 0xfb, 0xcb, 0x5c, 0x7d, 0x33, 0x13, 0xc8, 0x84, 0x63, 0x92,
|
||||
0xea, 0x3a, 0xfc, 0x77, 0x64, 0xb1, 0xb8, 0x14, 0x8b, 0x5a, 0xd3, 0x20, 0xdb, 0xb5, 0x6c, 0x4e,
|
||||
0x7c, 0xa6, 0x29, 0x95, 0x74, 0x2d, 0x87, 0xa3, 0xb0, 0x6a, 0x43, 0x71, 0x1a, 0x22, 0xdb, 0xc3,
|
||||
0x00, 0x71, 0x61, 0x01, 0xbb, 0x59, 0x7f, 0x13, 0x2c, 0xd5, 0x77, 0x50, 0xdc, 0x15, 0xae, 0x98,
|
||||
0x11, 0xef, 0xef, 0x8b, 0xd1, 0x87, 0xff, 0x67, 0x6a, 0xdd, 0x9a, 0xf2, 0x5f, 0x14, 0x28, 0xbe,
|
||||
0x12, 0x56, 0xbd, 0xfd, 0x93, 0xa1, 0x6d, 0xc8, 0x87, 0x63, 0x21, 0x9e, 0x4c, 0xe9, 0xd9, 0xd9,
|
||||
0x79, 0x3a, 0x08, 0x5e, 0xd5, 0x63, 0x93, 0xf5, 0xb1, 0x9c, 0xbe, 0x60, 0x1d, 0xc8, 0x32, 0xd3,
|
||||
0xe8, 0xad, 0xc9, 0xf2, 0x10, 0x8a, 0x7b, 0xc4, 0x26, 0x73, 0x54, 0x59, 0x30, 0x2c, 0x8d, 0xcb,
|
||||
0x0c, 0x40, 0x6c, 0x46, 0x34, 0x84, 0xf4, 0x21, 0xe1, 0xe8, 0x49, 0x82, 0x36, 0xe6, 0x8c, 0xa4,
|
||||
0xfe, 0x74, 0x69, 0x9c, 0x94, 0xe2, 0x03, 0x64, 0x82, 0xb1, 0x40, 0x49, 0x1e, 0xfd, 0xb9, 0x23,
|
||||
0xa7, 0x6f, 0xde, 0x00, 0x29, 0x8b, 0x7f, 0x04, 0x35, 0x74, 0x2e, 0x4a, 0x42, 0x32, 0x7f, 0xa0,
|
||||
0xf4, 0xad, 0x9b, 0x40, 0xe3, 0x06, 0x42, 0x8f, 0x24, 0x6a, 0x60, 0xbe, 0xef, 0x13, 0x35, 0xb0,
|
||||
0xc8, 0x89, 0x6f, 0x40, 0x0d, 0x7d, 0x93, 0xa8, 0x81, 0xf9, 0x16, 0xd3, 0x8b, 0x33, 0x13, 0xb1,
|
||||
0x1f, 0xfc, 0x84, 0x34, 0xdf, 0x9e, 0x5f, 0x95, 0x56, 0xbe, 0x5f, 0x95, 0x56, 0x3e, 0x8d, 0x4b,
|
||||
0xca, 0xf9, 0xb8, 0xa4, 0x7c, 0x1b, 0x97, 0x94, 0xcb, 0x71, 0x49, 0x79, 0x7d, 0xf0, 0x07, 0xff,
|
||||
0x55, 0xdb, 0x71, 0xd4, 0x52, 0x45, 0xc5, 0x47, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x6b, 0x95,
|
||||
0xa9, 0x10, 0xa8, 0x09, 0x00, 0x00,
|
||||
}
|
||||
|
@ -91,7 +91,17 @@ message GetContainerResponse {
|
||||
}
|
||||
|
||||
message ListContainersRequest {
|
||||
string filter = 1; // TODO(stevvooe): Define a filtering syntax to make these queries.
|
||||
// Filters contains one or more filters using the syntax defined in the
|
||||
// containerd filter package.
|
||||
//
|
||||
// The returned result will be those that match any of the provided
|
||||
// filters. Expanded, containers that match the following will be
|
||||
// returned:
|
||||
//
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
//
|
||||
// If filters is zero-length or nil, all items will be returned.
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListContainersResponse {
|
||||
|
@ -127,8 +127,10 @@ func (c *Client) IsServing(ctx context.Context) (bool, error) {
|
||||
}
|
||||
|
||||
// Containers returns all containers created in containerd
|
||||
func (c *Client) Containers(ctx context.Context) ([]Container, error) {
|
||||
r, err := c.ContainerService().List(ctx, &containers.ListContainersRequest{})
|
||||
func (c *Client) Containers(ctx context.Context, filters ...string) ([]Container, error) {
|
||||
r, err := c.ContainerService().List(ctx, &containers.ListContainersRequest{
|
||||
Filters: filters,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
52
cmd/ctr/labels.go
Normal file
52
cmd/ctr/labels.go
Normal file
@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var containersSetLabelsCommand = cli.Command{
|
||||
Name: "set-labels",
|
||||
Usage: "Set and clear labels for a container.",
|
||||
ArgsUsage: "[flags] <name> [<key>=<value>, ...]",
|
||||
Description: "Set and clear labels for a container.",
|
||||
Flags: []cli.Flag{},
|
||||
Action: func(clicontext *cli.Context) error {
|
||||
var (
|
||||
ctx, cancel = appContext(clicontext)
|
||||
containerID, labels = objectWithLabelArgs(clicontext)
|
||||
)
|
||||
defer cancel()
|
||||
|
||||
client, err := newClient(clicontext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if containerID == "" {
|
||||
return errors.New("please specify a container")
|
||||
}
|
||||
|
||||
container, err := client.LoadContainer(ctx, containerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
setlabels, err := container.SetLabels(ctx, labels)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var labelStrings []string
|
||||
for k, v := range setlabels {
|
||||
labelStrings = append(labelStrings, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
|
||||
fmt.Println(strings.Join(labelStrings, ","))
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
113
cmd/ctr/list.go
113
cmd/ctr/list.go
@ -3,11 +3,11 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/containerd/containerd"
|
||||
tasks "github.com/containerd/containerd/api/services/tasks/v1"
|
||||
tasktypes "github.com/containerd/containerd/api/types/task"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
@ -31,24 +31,18 @@ var taskListCommand = cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var containerListCommand = cli.Command{
|
||||
Name: "containers",
|
||||
Usage: "manage containers (metadata)",
|
||||
Aliases: []string{"c"},
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "list",
|
||||
Usage: "list tasks",
|
||||
Aliases: []string{"ls"},
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "print only the container id",
|
||||
},
|
||||
},
|
||||
Action: containerListFn,
|
||||
var containersListCommand = cli.Command{
|
||||
Name: "list",
|
||||
Usage: "list all tasks or those that match a filter",
|
||||
ArgsUsage: "[filter, ...]",
|
||||
Aliases: []string{"ls"},
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "print only the container id",
|
||||
},
|
||||
},
|
||||
Action: containerListFn,
|
||||
}
|
||||
|
||||
func taskListFn(context *cli.Context) error {
|
||||
@ -62,66 +56,25 @@ func taskListFn(context *cli.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containers, err := client.Containers(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s := client.TaskService()
|
||||
|
||||
tasksResponse, err := s.List(ctx, &tasks.ListTasksRequest{})
|
||||
response, err := s.List(ctx, &tasks.ListTasksRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Join with tasks to get status.
|
||||
tasksByContainerID := map[string]*tasktypes.Task{}
|
||||
for _, task := range tasksResponse.Tasks {
|
||||
tasksByContainerID[task.ContainerID] = task
|
||||
}
|
||||
|
||||
if quiet {
|
||||
for _, c := range containers {
|
||||
task, ok := tasksByContainerID[c.ID()]
|
||||
if ok {
|
||||
fmt.Printf("%s\t%d\n", c.ID(), task.Pid)
|
||||
} else {
|
||||
//Since task is not running, PID is printed 0
|
||||
fmt.Printf("%s\t%d\n", c.ID(), 0)
|
||||
}
|
||||
for _, task := range response.Tasks {
|
||||
fmt.Println(task.ID)
|
||||
}
|
||||
} else {
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0)
|
||||
fmt.Fprintln(w, "TASK-ID\tIMAGE\tPID\tSTATUS")
|
||||
for _, c := range containers {
|
||||
var imageName string
|
||||
if image, err := c.Image(ctx); err != nil {
|
||||
if err != containerd.ErrNoImage {
|
||||
return err
|
||||
}
|
||||
imageName = "-"
|
||||
} else {
|
||||
imageName = image.Name()
|
||||
}
|
||||
var (
|
||||
status string
|
||||
pid uint32
|
||||
)
|
||||
task, ok := tasksByContainerID[c.ID()]
|
||||
if ok {
|
||||
status = task.Status.String()
|
||||
pid = task.Pid
|
||||
} else {
|
||||
status = "STOPPED" // TODO(stevvooe): Is this assumption correct?
|
||||
pid = 0
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprintf(w, "%s\t%s\t%d\t%s\n",
|
||||
c.ID(),
|
||||
imageName,
|
||||
pid,
|
||||
status,
|
||||
w := tabwriter.NewWriter(os.Stdout, 4, 8, 4, ' ', 0)
|
||||
fmt.Fprintln(w, "TASK\tPID\tSTATUS\t")
|
||||
for _, task := range response.Tasks {
|
||||
if _, err := fmt.Fprintf(w, "%s\t%d\t%s\n",
|
||||
task.ID,
|
||||
task.Pid,
|
||||
task.Status.String(),
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -133,6 +86,7 @@ func taskListFn(context *cli.Context) error {
|
||||
|
||||
func containerListFn(context *cli.Context) error {
|
||||
var (
|
||||
filters = context.Args()
|
||||
quiet = context.Bool("quiet")
|
||||
ctx, cancel = appContext(context)
|
||||
)
|
||||
@ -142,18 +96,28 @@ func containerListFn(context *cli.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containers, err := client.Containers(ctx)
|
||||
containers, err := client.Containers(ctx, filters...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if quiet {
|
||||
for _, c := range containers {
|
||||
fmt.Printf("%s\n", c.ID())
|
||||
}
|
||||
} else {
|
||||
cl := tabwriter.NewWriter(os.Stdout, 10, 1, 3, ' ', 0)
|
||||
fmt.Fprintln(cl, "ID\tIMAGE\tRUNTIME\tSIZE")
|
||||
w := tabwriter.NewWriter(os.Stdout, 4, 8, 4, ' ', 0)
|
||||
fmt.Fprintln(w, "CONTAINER\tIMAGE\tRUNTIME\tLABELS\t")
|
||||
for _, c := range containers {
|
||||
var labelStrings []string
|
||||
for k, v := range c.Proto().Labels {
|
||||
labelStrings = append(labelStrings, strings.Join([]string{k, v}, "="))
|
||||
}
|
||||
labels := strings.Join(labelStrings, ",")
|
||||
if labels == "" {
|
||||
labels = "-"
|
||||
}
|
||||
|
||||
var imageName string
|
||||
if image, err := c.Image(ctx); err != nil {
|
||||
if err != containerd.ErrNoImage {
|
||||
@ -163,17 +127,18 @@ func containerListFn(context *cli.Context) error {
|
||||
} else {
|
||||
imageName = image.Name()
|
||||
}
|
||||
|
||||
proto := c.Proto()
|
||||
if _, err := fmt.Fprintf(cl, "%s\t%s\t%s\t%d\n",
|
||||
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%v\t\n",
|
||||
c.ID(),
|
||||
imageName,
|
||||
proto.Runtime.Name,
|
||||
proto.Size(),
|
||||
labels,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return cl.Flush()
|
||||
return w.Flush()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ containerd CLI
|
||||
deleteCommand,
|
||||
namespacesCommand,
|
||||
eventsCommand,
|
||||
containerListCommand,
|
||||
containersCommand,
|
||||
taskListCommand,
|
||||
infoCommand,
|
||||
killCommand,
|
||||
@ -83,3 +83,13 @@ containerd CLI
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
var containersCommand = cli.Command{
|
||||
Name: "containers",
|
||||
Usage: "manage containers (metadata)",
|
||||
Aliases: []string{"c"},
|
||||
Subcommands: []cli.Command{
|
||||
containersListCommand,
|
||||
containersSetLabelsCommand,
|
||||
},
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ var namespacesCreateCommand = cli.Command{
|
||||
Action: func(clicontext *cli.Context) error {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
namespace, labels = namespaceWithLabelArgs(clicontext)
|
||||
namespace, labels = objectWithLabelArgs(clicontext)
|
||||
)
|
||||
|
||||
if namespace == "" {
|
||||
@ -53,27 +53,6 @@ var namespacesCreateCommand = cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func namespaceWithLabelArgs(clicontext *cli.Context) (string, map[string]string) {
|
||||
var (
|
||||
namespace = clicontext.Args().First()
|
||||
labelStrings = clicontext.Args().Tail()
|
||||
labels = make(map[string]string, len(labelStrings))
|
||||
)
|
||||
|
||||
for _, label := range labelStrings {
|
||||
parts := strings.SplitN(label, "=", 2)
|
||||
key := parts[0]
|
||||
value := "true"
|
||||
if len(parts) > 1 {
|
||||
value = parts[1]
|
||||
}
|
||||
|
||||
labels[key] = value
|
||||
}
|
||||
|
||||
return namespace, labels
|
||||
}
|
||||
|
||||
var namespacesSetLabelsCommand = cli.Command{
|
||||
Name: "set-labels",
|
||||
Usage: "Set and clear labels for a namespace.",
|
||||
@ -83,7 +62,7 @@ var namespacesSetLabelsCommand = cli.Command{
|
||||
Action: func(clicontext *cli.Context) error {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
namespace, labels = namespaceWithLabelArgs(clicontext)
|
||||
namespace, labels = objectWithLabelArgs(clicontext)
|
||||
)
|
||||
|
||||
namespaces, err := getNamespacesService(clicontext)
|
||||
|
@ -74,6 +74,10 @@ var runCommand = cli.Command{
|
||||
Name: "env",
|
||||
Usage: "specify additional container environment variables (i.e. FOO=bar)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "label",
|
||||
Usage: "specify additional labels (foo=bar)",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "rm",
|
||||
Usage: "remove the container after running",
|
||||
|
@ -57,11 +57,15 @@ func newContainer(ctx gocontext.Context, client *containerd.Client, context *cli
|
||||
err error
|
||||
checkpointIndex digest.Digest
|
||||
|
||||
ref = context.Args().First()
|
||||
id = context.Args().Get(1)
|
||||
args = context.Args()[2:]
|
||||
tty = context.Bool("tty")
|
||||
ref = context.Args().First()
|
||||
id = context.Args().Get(1)
|
||||
args = context.Args()[2:]
|
||||
tty = context.Bool("tty")
|
||||
labelStrings = context.StringSlice("label")
|
||||
)
|
||||
|
||||
labels := labelArgs(labelStrings)
|
||||
|
||||
if raw := context.String("checkpoint"); raw != "" {
|
||||
if checkpointIndex, err = digest.Parse(raw); err != nil {
|
||||
return nil, err
|
||||
@ -71,6 +75,7 @@ func newContainer(ctx gocontext.Context, client *containerd.Client, context *cli
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if checkpointIndex == "" {
|
||||
opts := []containerd.SpecOpts{
|
||||
containerd.WithImageConfig(ctx, image),
|
||||
@ -96,12 +101,15 @@ func newContainer(ctx gocontext.Context, client *containerd.Client, context *cli
|
||||
} else {
|
||||
rootfs = containerd.WithNewRootFS(id, image)
|
||||
}
|
||||
|
||||
return client.NewContainer(ctx, id,
|
||||
containerd.WithSpec(spec),
|
||||
containerd.WithImage(image),
|
||||
containerd.WithContainerLabels(labels),
|
||||
rootfs,
|
||||
)
|
||||
}
|
||||
|
||||
return client.NewContainer(ctx, id, containerd.WithCheckpoint(v1.Descriptor{
|
||||
Digest: checkpointIndex,
|
||||
}, id))
|
||||
|
@ -247,3 +247,28 @@ func replaceOrAppendEnvValues(defaults, overrides []string) []string {
|
||||
|
||||
return defaults
|
||||
}
|
||||
|
||||
func objectWithLabelArgs(clicontext *cli.Context) (string, map[string]string) {
|
||||
var (
|
||||
namespace = clicontext.Args().First()
|
||||
labelStrings = clicontext.Args().Tail()
|
||||
)
|
||||
|
||||
return namespace, labelArgs(labelStrings)
|
||||
}
|
||||
|
||||
func labelArgs(labelStrings []string) map[string]string {
|
||||
labels := make(map[string]string, len(labelStrings))
|
||||
for _, label := range labelStrings {
|
||||
parts := strings.SplitN(label, "=", 2)
|
||||
key := parts[0]
|
||||
value := "true"
|
||||
if len(parts) > 1 {
|
||||
value = parts[1]
|
||||
}
|
||||
|
||||
labels[key] = value
|
||||
}
|
||||
|
||||
return labels
|
||||
}
|
||||
|
51
container.go
51
container.go
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
@ -12,6 +13,7 @@ import (
|
||||
"github.com/containerd/containerd/api/services/containers/v1"
|
||||
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||
"github.com/containerd/containerd/api/types"
|
||||
ptypes "github.com/gogo/protobuf/types"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -33,6 +35,8 @@ type Container interface {
|
||||
Spec() (*specs.Spec, error)
|
||||
Task(context.Context, IOAttach) (Task, error)
|
||||
Image(context.Context) (Image, error)
|
||||
Labels(context.Context) (map[string]string, error)
|
||||
SetLabels(context.Context, map[string]string) (map[string]string, error)
|
||||
}
|
||||
|
||||
func containerFromProto(client *Client, c containers.Container) *container {
|
||||
@ -60,6 +64,53 @@ func (c *container) Proto() containers.Container {
|
||||
return c.c
|
||||
}
|
||||
|
||||
func (c *container) Labels(ctx context.Context) (map[string]string, error) {
|
||||
resp, err := c.client.ContainerService().Get(ctx, &containers.GetContainerRequest{
|
||||
ID: c.ID(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.c = resp.Container
|
||||
|
||||
m := make(map[string]string, len(resp.Container.Labels))
|
||||
for k, v := range c.c.Labels {
|
||||
m[k] = v
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *container) SetLabels(ctx context.Context, labels map[string]string) (map[string]string, error) {
|
||||
var req containers.UpdateContainerRequest
|
||||
|
||||
req.Container.ID = c.ID()
|
||||
req.Container.Labels = labels
|
||||
|
||||
req.UpdateMask = &ptypes.FieldMask{
|
||||
Paths: make([]string, 0, len(labels)),
|
||||
}
|
||||
// mask off paths so we only muck with the labels encountered in labels.
|
||||
// Labels not in the passed in argument will be left alone.
|
||||
for k := range labels {
|
||||
req.UpdateMask.Paths = append(req.UpdateMask.Paths, strings.Join([]string{"labels", k}, "."))
|
||||
}
|
||||
|
||||
resp, err := c.client.ContainerService().Update(ctx, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.c = resp.Container // update our local container
|
||||
|
||||
m := make(map[string]string, len(resp.Container.Labels))
|
||||
for k, v := range c.c.Labels {
|
||||
m[k] = v
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Spec returns the current OCI specification for the container
|
||||
func (c *container) Spec() (*specs.Spec, error) {
|
||||
var s specs.Spec
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/filters"
|
||||
"github.com/gogo/protobuf/types"
|
||||
)
|
||||
|
||||
@ -29,7 +30,10 @@ type RuntimeInfo struct {
|
||||
|
||||
type Store interface {
|
||||
Get(ctx context.Context, id string) (Container, error)
|
||||
List(ctx context.Context, filter string) ([]Container, error)
|
||||
|
||||
// List returns containers that match one or more of the provided filters.
|
||||
List(ctx context.Context, filters ...filters.Filter) ([]Container, error)
|
||||
|
||||
Create(ctx context.Context, container Container) (Container, error)
|
||||
Update(ctx context.Context, container Container) (Container, error)
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
@ -2,11 +2,13 @@ package metadata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/filters"
|
||||
"github.com/containerd/containerd/identifiers"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
@ -43,16 +45,22 @@ func (s *containerStore) Get(ctx context.Context, id string) (containers.Contain
|
||||
return container, nil
|
||||
}
|
||||
|
||||
func (s *containerStore) List(ctx context.Context, filter string) ([]containers.Container, error) {
|
||||
func (s *containerStore) List(ctx context.Context, fs ...filters.Filter) ([]containers.Container, error) {
|
||||
namespace, err := namespaces.NamespaceRequired(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
m []containers.Container
|
||||
bkt = getContainersBucket(s.tx, namespace)
|
||||
m []containers.Container
|
||||
filter = filters.Filter(filters.Any(fs))
|
||||
bkt = getContainersBucket(s.tx, namespace)
|
||||
)
|
||||
|
||||
if len(fs) == 0 {
|
||||
filter = filters.Always
|
||||
}
|
||||
|
||||
if bkt == nil {
|
||||
return m, nil
|
||||
}
|
||||
@ -66,7 +74,10 @@ func (s *containerStore) List(ctx context.Context, filter string) ([]containers.
|
||||
if err := readContainer(&container, cbkt); err != nil {
|
||||
return errors.Wrap(err, "failed to read container")
|
||||
}
|
||||
m = append(m, container)
|
||||
|
||||
if filter.Match(adaptContainer(container)) {
|
||||
m = append(m, container)
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
@ -75,6 +86,46 @@ func (s *containerStore) List(ctx context.Context, filter string) ([]containers.
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func adaptContainer(o interface{}) filters.Adaptor {
|
||||
obj := o.(containers.Container)
|
||||
return filters.AdapterFunc(func(fieldpath []string) (string, bool) {
|
||||
if len(fieldpath) == 0 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
switch fieldpath[0] {
|
||||
case "id":
|
||||
return obj.ID, len(obj.ID) > 0
|
||||
case "runtime":
|
||||
if len(fieldpath) <= 1 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
switch fieldpath[1] {
|
||||
case "name":
|
||||
return obj.Runtime.Name, len(obj.Runtime.Name) > 0
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
case "image":
|
||||
return obj.Image, len(obj.Image) > 0
|
||||
case "labels":
|
||||
return checkMap(fieldpath[1:], obj.Labels)
|
||||
}
|
||||
|
||||
return "", false
|
||||
})
|
||||
}
|
||||
|
||||
func checkMap(fieldpath []string, m map[string]string) (string, bool) {
|
||||
if len(m) == 0 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
value, ok := m[strings.Join(fieldpath, ".")]
|
||||
return value, ok
|
||||
}
|
||||
|
||||
func (s *containerStore) Create(ctx context.Context, container containers.Container) (containers.Container, error) {
|
||||
namespace, err := namespaces.NamespaceRequired(ctx)
|
||||
if err != nil {
|
||||
@ -268,14 +319,22 @@ func writeContainer(container *containers.Container, bkt *bolt.Bucket) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
lbkt, err := bkt.CreateBucket(bucketKeyLabels)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for k, v := range container.Labels {
|
||||
if v == "" {
|
||||
delete(container.Labels, k) // remove since we don't actually set it
|
||||
continue
|
||||
}
|
||||
|
||||
if err := lbkt.Put([]byte(k), []byte(v)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ func (s *namespaceStore) namespaceEmpty(ctx context.Context, namespace string) (
|
||||
}
|
||||
|
||||
containerStore := NewContainerStore(s.tx)
|
||||
containers, err := containerStore.List(ctx, "")
|
||||
containers, err := containerStore.List(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -35,15 +35,25 @@ func containerToProto(container *containers.Container) api.Container {
|
||||
}
|
||||
|
||||
func containerFromProto(containerpb *api.Container) containers.Container {
|
||||
return containers.Container{
|
||||
ID: containerpb.ID,
|
||||
Labels: containerpb.Labels,
|
||||
Image: containerpb.Image,
|
||||
Runtime: containers.RuntimeInfo{
|
||||
var runtime containers.RuntimeInfo
|
||||
if containerpb.Runtime != nil {
|
||||
runtime = containers.RuntimeInfo{
|
||||
Name: containerpb.Runtime.Name,
|
||||
Options: containerpb.Runtime.Options,
|
||||
},
|
||||
Spec: containerpb.Spec.Value,
|
||||
RootFS: containerpb.RootFS,
|
||||
}
|
||||
}
|
||||
|
||||
var spec []byte
|
||||
if containerpb.Spec != nil {
|
||||
spec = containerpb.Spec.Value
|
||||
}
|
||||
|
||||
return containers.Container{
|
||||
ID: containerpb.ID,
|
||||
Labels: containerpb.Labels,
|
||||
Image: containerpb.Image,
|
||||
Runtime: runtime,
|
||||
Spec: spec,
|
||||
RootFS: containerpb.RootFS,
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
api "github.com/containerd/containerd/api/services/containers/v1"
|
||||
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/events"
|
||||
"github.com/containerd/containerd/filters"
|
||||
"github.com/containerd/containerd/metadata"
|
||||
"github.com/containerd/containerd/plugin"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
@ -65,8 +68,18 @@ func (s *Service) Get(ctx context.Context, req *api.GetContainerRequest) (*api.G
|
||||
func (s *Service) List(ctx context.Context, req *api.ListContainersRequest) (*api.ListContainersResponse, error) {
|
||||
var resp api.ListContainersResponse
|
||||
|
||||
var fs []filters.Filter
|
||||
for _, s := range req.Filters {
|
||||
f, err := filters.Parse(s)
|
||||
if err != nil {
|
||||
return nil, grpc.Errorf(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
fs = append(fs, f)
|
||||
}
|
||||
|
||||
return &resp, errdefs.ToGRPC(s.withStoreView(ctx, func(ctx context.Context, store containers.Store) error {
|
||||
containers, err := store.List(ctx, req.Filter)
|
||||
containers, err := store.List(ctx, fs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -108,18 +121,20 @@ func (s *Service) Create(ctx context.Context, req *api.CreateContainerRequest) (
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, req *api.UpdateContainerRequest) (*api.UpdateContainerResponse, error) {
|
||||
var resp api.UpdateContainerResponse
|
||||
var (
|
||||
resp api.UpdateContainerResponse
|
||||
incoming = containerFromProto(&req.Container)
|
||||
)
|
||||
|
||||
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store containers.Store) error {
|
||||
container := containerFromProto(&req.Container)
|
||||
|
||||
current, err := store.Get(ctx, container.ID)
|
||||
container, err := store.Get(ctx, incoming.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if current.ID != container.ID {
|
||||
return grpc.Errorf(codes.InvalidArgument, "container ids must match: %v != %v", current.ID, container.ID)
|
||||
if container.ID != incoming.ID {
|
||||
return grpc.Errorf(codes.InvalidArgument, "container ids must match: %v != %v", container.ID, incoming.ID)
|
||||
}
|
||||
|
||||
// apply the field mask. If you update this code, you better follow the
|
||||
@ -127,34 +142,39 @@ func (s *Service) Update(ctx context.Context, req *api.UpdateContainerRequest) (
|
||||
// is, do not update this code.
|
||||
if req.UpdateMask != nil && len(req.UpdateMask.Paths) > 0 {
|
||||
for _, path := range req.UpdateMask.Paths {
|
||||
if strings.HasPrefix(path, "labels.") {
|
||||
key := strings.TrimPrefix(path, "labels.")
|
||||
container.Labels[key] = incoming.Labels[key]
|
||||
continue
|
||||
}
|
||||
|
||||
switch path {
|
||||
case "labels":
|
||||
current.Labels = container.Labels
|
||||
container.Labels = incoming.Labels
|
||||
case "image":
|
||||
current.Image = container.Image
|
||||
container.Image = incoming.Image
|
||||
case "runtime":
|
||||
// TODO(stevvooe): Should this actually be allowed?
|
||||
current.Runtime = container.Runtime
|
||||
container.Runtime = incoming.Runtime
|
||||
case "spec":
|
||||
current.Spec = container.Spec
|
||||
container.Spec = incoming.Spec
|
||||
case "rootfs":
|
||||
current.RootFS = container.RootFS
|
||||
container.RootFS = incoming.RootFS
|
||||
default:
|
||||
return grpc.Errorf(codes.InvalidArgument, "cannot update %q field", path)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no field mask present, just replace everything
|
||||
current = container
|
||||
container = incoming
|
||||
}
|
||||
|
||||
created, err := store.Update(ctx, container)
|
||||
updated, err := store.Update(ctx, container)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp.Container = containerToProto(&created)
|
||||
|
||||
resp.Container = containerToProto(&updated)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return &resp, errdefs.ToGRPC(err)
|
||||
|
Loading…
Reference in New Issue
Block a user