diff --git a/cmd/dockerd/daemon_unix.go b/cmd/dockerd/daemon_unix.go index 51e56673a0..ed066bd928 100644 --- a/cmd/dockerd/daemon_unix.go +++ b/cmd/dockerd/daemon_unix.go @@ -10,7 +10,7 @@ import ( "path/filepath" "strconv" - "github.com/containerd/containerd/runtime/linux" + "github.com/containerd/containerd/runtime/v1/linux" "github.com/docker/docker/cmd/dockerd/hack" "github.com/docker/docker/daemon" "github.com/docker/docker/libcontainerd" diff --git a/libcontainerd/client_daemon.go b/libcontainerd/client_daemon.go index 1bea770c29..5f67a93722 100644 --- a/libcontainerd/client_daemon.go +++ b/libcontainerd/client_daemon.go @@ -563,7 +563,17 @@ func (c *client) CreateCheckpoint(ctx context.Context, containerID, checkpointDi opts := []containerd.CheckpointTaskOpts{} if exit { - opts = append(opts, containerd.WithExit) + opts = append(opts, func(r *containerd.CheckpointTaskInfo) error { + if r.Options == nil { + r.Options = &runctypes.CheckpointOptions{ + Exit: true, + } + } else { + opts, _ := r.Options.(*runctypes.CheckpointOptions) + opts.Exit = true + } + return nil + }) } img, err := p.(containerd.Task).Checkpoint(ctx, opts...) if err != nil { diff --git a/vendor.conf b/vendor.conf index 0e9c5264ab..66d988fc5f 100644 --- a/vendor.conf +++ b/vendor.conf @@ -76,7 +76,7 @@ google.golang.org/grpc v1.12.0 # This does not need to match RUNC_COMMIT as it is used for helper packages but should be newer or equal github.com/opencontainers/runc ad0f5255060d36872be04de22f8731f38ef2d7b1 -github.com/opencontainers/runtime-spec v1.0.1 +github.com/opencontainers/runtime-spec d810dbc60d8c5aeeb3d054bd1132fab2121968ce # v1.0.1-43-gd810dbc github.com/opencontainers/image-spec v1.0.1 github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0 @@ -114,12 +114,12 @@ github.com/googleapis/gax-go v2.0.0 google.golang.org/genproto 694d95ba50e67b2e363f3483057db5d4910c18f9 # containerd -github.com/containerd/containerd b41633746ed4833f52c3c071e8edcfa2713e5677 +github.com/containerd/containerd v1.2.0-beta.0 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c -github.com/containerd/continuity 0377f7d767206f3a9e8881d0f02267b0d89c7a62 -github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130 -github.com/containerd/console 5d1b48d6114b8c9666f0c8b916f871af97b0a761 -github.com/containerd/go-runc f271fa2021de855d4d918dbef83c5fe19db1bdd +github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b +github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2 +github.com/containerd/console 4d8a41f4ce5b9bae77c41786ea2458330f43f081 +github.com/containerd/go-runc edcf3de1f4971445c42d61f20d506b30612aa031 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef diff --git a/vendor/github.com/containerd/cgroups/cgroup.go b/vendor/github.com/containerd/cgroups/cgroup.go index d4c40f749f..7959feb490 100644 --- a/vendor/github.com/containerd/cgroups/cgroup.go +++ b/vendor/github.com/containerd/cgroups/cgroup.go @@ -137,6 +137,36 @@ func (c *cgroup) add(process Process) error { return nil } +// AddTask moves the provided tasks (threads) into the new cgroup +func (c *cgroup) AddTask(process Process) error { + if process.Pid <= 0 { + return ErrInvalidPid + } + c.mu.Lock() + defer c.mu.Unlock() + if c.err != nil { + return c.err + } + return c.addTask(process) +} + +func (c *cgroup) addTask(process Process) error { + for _, s := range pathers(c.subsystems) { + p, err := c.path(s.Name()) + if err != nil { + return err + } + if err := ioutil.WriteFile( + filepath.Join(s.Path(p), cgroupTasks), + []byte(strconv.Itoa(process.Pid)), + defaultFilePerm, + ); err != nil { + return err + } + } + return nil +} + // Delete will remove the control group from each of the subsystems registered func (c *cgroup) Delete() error { c.mu.Lock() diff --git a/vendor/github.com/containerd/cgroups/control.go b/vendor/github.com/containerd/cgroups/control.go index a554a528fe..63e2df93dd 100644 --- a/vendor/github.com/containerd/cgroups/control.go +++ b/vendor/github.com/containerd/cgroups/control.go @@ -24,6 +24,7 @@ import ( const ( cgroupProcs = "cgroup.procs" + cgroupTasks = "tasks" defaultDirPerm = 0755 ) @@ -48,8 +49,10 @@ type Process struct { type Cgroup interface { // New creates a new cgroup under the calling cgroup New(string, *specs.LinuxResources) (Cgroup, error) - // Add adds a process to the cgroup + // Add adds a process to the cgroup (cgroup.procs) Add(Process) error + // AddTask adds a process to the cgroup (tasks) + AddTask(Process) error // Delete removes the cgroup as a whole Delete() error // MoveTo moves all the processes under the calling cgroup to the provided one diff --git a/vendor/github.com/containerd/cgroups/cpuset.go b/vendor/github.com/containerd/cgroups/cpuset.go index 50d95da93e..f182aa68c1 100644 --- a/vendor/github.com/containerd/cgroups/cpuset.go +++ b/vendor/github.com/containerd/cgroups/cpuset.go @@ -82,6 +82,10 @@ func (c *cpusetController) Create(path string, resources *specs.LinuxResources) return nil } +func (c *cpusetController) Update(path string, resources *specs.LinuxResources) error { + return c.Create(path, resources) +} + func (c *cpusetController) getValues(path string) (cpus []byte, mems []byte, err error) { if cpus, err = ioutil.ReadFile(filepath.Join(path, "cpuset.cpus")); err != nil && !os.IsNotExist(err) { return diff --git a/vendor/github.com/containerd/cgroups/metrics.pb.go b/vendor/github.com/containerd/cgroups/metrics.pb.go index c1125588a2..6043a8f7db 100644 --- a/vendor/github.com/containerd/cgroups/metrics.pb.go +++ b/vendor/github.com/containerd/cgroups/metrics.pb.go @@ -19,6 +19,8 @@ MemoryEntry BlkIOStat BlkIOEntry + RdmaStat + RdmaEntry */ package cgroups @@ -49,6 +51,7 @@ type Metrics struct { CPU *CPUStat `protobuf:"bytes,3,opt,name=cpu" json:"cpu,omitempty"` Memory *MemoryStat `protobuf:"bytes,4,opt,name=memory" json:"memory,omitempty"` Blkio *BlkIOStat `protobuf:"bytes,5,opt,name=blkio" json:"blkio,omitempty"` + Rdma *RdmaStat `protobuf:"bytes,6,opt,name=rdma" json:"rdma,omitempty"` } func (m *Metrics) Reset() { *m = Metrics{} } @@ -187,6 +190,25 @@ func (m *BlkIOEntry) Reset() { *m = BlkIOEntry{} } func (*BlkIOEntry) ProtoMessage() {} func (*BlkIOEntry) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{9} } +type RdmaStat struct { + Current []*RdmaEntry `protobuf:"bytes,1,rep,name=current" json:"current,omitempty"` + Limit []*RdmaEntry `protobuf:"bytes,2,rep,name=limit" json:"limit,omitempty"` +} + +func (m *RdmaStat) Reset() { *m = RdmaStat{} } +func (*RdmaStat) ProtoMessage() {} +func (*RdmaStat) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{10} } + +type RdmaEntry struct { + Device string `protobuf:"bytes,1,opt,name=device,proto3" json:"device,omitempty"` + HcaHandles uint32 `protobuf:"varint,2,opt,name=hca_handles,json=hcaHandles,proto3" json:"hca_handles,omitempty"` + HcaObjects uint32 `protobuf:"varint,3,opt,name=hca_objects,json=hcaObjects,proto3" json:"hca_objects,omitempty"` +} + +func (m *RdmaEntry) Reset() { *m = RdmaEntry{} } +func (*RdmaEntry) ProtoMessage() {} +func (*RdmaEntry) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{11} } + func init() { proto.RegisterType((*Metrics)(nil), "io.containerd.cgroups.v1.Metrics") proto.RegisterType((*HugetlbStat)(nil), "io.containerd.cgroups.v1.HugetlbStat") @@ -198,6 +220,8 @@ func init() { proto.RegisterType((*MemoryEntry)(nil), "io.containerd.cgroups.v1.MemoryEntry") proto.RegisterType((*BlkIOStat)(nil), "io.containerd.cgroups.v1.BlkIOStat") proto.RegisterType((*BlkIOEntry)(nil), "io.containerd.cgroups.v1.BlkIOEntry") + proto.RegisterType((*RdmaStat)(nil), "io.containerd.cgroups.v1.RdmaStat") + proto.RegisterType((*RdmaEntry)(nil), "io.containerd.cgroups.v1.RdmaEntry") } func (m *Metrics) Marshal() (dAtA []byte, err error) { size := m.Size() @@ -266,6 +290,16 @@ func (m *Metrics) MarshalTo(dAtA []byte) (int, error) { } i += n4 } + if m.Rdma != nil { + dAtA[i] = 0x32 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.Rdma.Size())) + n5, err := m.Rdma.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n5 + } return i, nil } @@ -732,6 +766,7 @@ func (m *MemoryEntry) MarshalTo(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Limit != 0 { dAtA[i] = 0x8 i++ @@ -914,6 +949,82 @@ func (m *BlkIOEntry) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *RdmaStat) 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 *RdmaStat) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Current) > 0 { + for _, msg := range m.Current { + dAtA[i] = 0xa + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.Limit) > 0 { + for _, msg := range m.Limit { + dAtA[i] = 0x12 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *RdmaEntry) 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 *RdmaEntry) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Device) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintMetrics(dAtA, i, uint64(len(m.Device))) + i += copy(dAtA[i:], m.Device) + } + if m.HcaHandles != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.HcaHandles)) + } + if m.HcaObjects != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintMetrics(dAtA, i, uint64(m.HcaObjects)) + } + return i, nil +} + func encodeFixed64Metrics(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) dAtA[offset+1] = uint8(v >> 8) @@ -966,6 +1077,10 @@ func (m *Metrics) Size() (n int) { l = m.Blkio.Size() n += 1 + l + sovMetrics(uint64(l)) } + if m.Rdma != nil { + l = m.Rdma.Size() + n += 1 + l + sovMetrics(uint64(l)) + } return n } @@ -1264,6 +1379,40 @@ func (m *BlkIOEntry) Size() (n int) { return n } +func (m *RdmaStat) Size() (n int) { + var l int + _ = l + if len(m.Current) > 0 { + for _, e := range m.Current { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + if len(m.Limit) > 0 { + for _, e := range m.Limit { + l = e.Size() + n += 1 + l + sovMetrics(uint64(l)) + } + } + return n +} + +func (m *RdmaEntry) Size() (n int) { + var l int + _ = l + l = len(m.Device) + if l > 0 { + n += 1 + l + sovMetrics(uint64(l)) + } + if m.HcaHandles != 0 { + n += 1 + sovMetrics(uint64(m.HcaHandles)) + } + if m.HcaObjects != 0 { + n += 1 + sovMetrics(uint64(m.HcaObjects)) + } + return n +} + func sovMetrics(x uint64) (n int) { for { n++ @@ -1287,6 +1436,7 @@ func (this *Metrics) String() string { `CPU:` + strings.Replace(fmt.Sprintf("%v", this.CPU), "CPUStat", "CPUStat", 1) + `,`, `Memory:` + strings.Replace(fmt.Sprintf("%v", this.Memory), "MemoryStat", "MemoryStat", 1) + `,`, `Blkio:` + strings.Replace(fmt.Sprintf("%v", this.Blkio), "BlkIOStat", "BlkIOStat", 1) + `,`, + `Rdma:` + strings.Replace(fmt.Sprintf("%v", this.Rdma), "RdmaStat", "RdmaStat", 1) + `,`, `}`, }, "") return s @@ -1440,6 +1590,29 @@ func (this *BlkIOEntry) String() string { }, "") return s } +func (this *RdmaStat) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RdmaStat{`, + `Current:` + strings.Replace(fmt.Sprintf("%v", this.Current), "RdmaEntry", "RdmaEntry", 1) + `,`, + `Limit:` + strings.Replace(fmt.Sprintf("%v", this.Limit), "RdmaEntry", "RdmaEntry", 1) + `,`, + `}`, + }, "") + return s +} +func (this *RdmaEntry) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&RdmaEntry{`, + `Device:` + fmt.Sprintf("%v", this.Device) + `,`, + `HcaHandles:` + fmt.Sprintf("%v", this.HcaHandles) + `,`, + `HcaObjects:` + fmt.Sprintf("%v", this.HcaObjects) + `,`, + `}`, + }, "") + return s +} func valueToStringMetrics(v interface{}) string { rv := reflect.ValueOf(v) if rv.IsNil() { @@ -1451,6 +1624,7 @@ func valueToStringMetrics(v interface{}) string { func (m *Metrics) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 + for iNdEx < l { preIndex := iNdEx var wire uint64 @@ -1640,6 +1814,39 @@ func (m *Metrics) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Rdma", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Rdma == nil { + m.Rdma = &RdmaStat{} + } + if err := m.Rdma.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipMetrics(dAtA[iNdEx:]) @@ -3656,6 +3863,236 @@ func (m *BlkIOEntry) Unmarshal(dAtA []byte) error { } return nil } +func (m *RdmaStat) 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 ErrIntOverflowMetrics + } + 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: RdmaStat: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RdmaStat: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Current", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Current = append(m.Current, &RdmaEntry{}) + if err := m.Current[len(m.Current)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthMetrics + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Limit = append(m.Limit, &RdmaEntry{}) + if err := m.Limit[len(m.Limit)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RdmaEntry) 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 ErrIntOverflowMetrics + } + 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: RdmaEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RdmaEntry: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Device", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + 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 ErrInvalidLengthMetrics + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Device = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HcaHandles", wireType) + } + m.HcaHandles = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HcaHandles |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HcaObjects", wireType) + } + m.HcaObjects = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowMetrics + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HcaObjects |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipMetrics(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthMetrics + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} + func skipMetrics(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/vendor/github.com/containerd/cgroups/metrics.proto b/vendor/github.com/containerd/cgroups/metrics.proto index 8c3c3c4bd8..642623fcee 100644 --- a/vendor/github.com/containerd/cgroups/metrics.proto +++ b/vendor/github.com/containerd/cgroups/metrics.proto @@ -10,6 +10,7 @@ message Metrics { CPUStat cpu = 3 [(gogoproto.customname) = "CPU"]; MemoryStat memory = 4; BlkIOStat blkio = 5; + RdmaStat rdma = 6; } message HugetlbStat { @@ -109,3 +110,14 @@ message BlkIOEntry { uint64 minor = 4; uint64 value = 5; } + +message RdmaStat { + repeated RdmaEntry current = 1; + repeated RdmaEntry limit = 2; +} + +message RdmaEntry { + string device = 1; + uint32 hca_handles = 2; + uint32 hca_objects = 3; +} diff --git a/vendor/github.com/containerd/cgroups/rdma.go b/vendor/github.com/containerd/cgroups/rdma.go new file mode 100644 index 0000000000..4f423d33a0 --- /dev/null +++ b/vendor/github.com/containerd/cgroups/rdma.go @@ -0,0 +1,153 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cgroups + +import ( + "io/ioutil" + "math" + "os" + "path/filepath" + "strconv" + "strings" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +type rdmaController struct { + root string +} + +func (p *rdmaController) Name() Name { + return Rdma +} + +func (p *rdmaController) Path(path string) string { + return filepath.Join(p.root, path) +} + +func NewRdma(root string) *rdmaController { + return &rdmaController{ + root: filepath.Join(root, string(Rdma)), + } +} + +func createCmdString(device string, limits *specs.LinuxRdma) string { + var cmdString string + + cmdString = device + if limits.HcaHandles != nil { + cmdString = cmdString + " " + "hca_handle=" + strconv.FormatUint(uint64(*limits.HcaHandles), 10) + } + + if limits.HcaObjects != nil { + cmdString = cmdString + " " + "hca_object=" + strconv.FormatUint(uint64(*limits.HcaObjects), 10) + } + return cmdString +} + +func (p *rdmaController) Create(path string, resources *specs.LinuxResources) error { + if err := os.MkdirAll(p.Path(path), defaultDirPerm); err != nil { + return err + } + + for device, limit := range resources.Rdma { + if device != "" && (limit.HcaHandles != nil || limit.HcaObjects != nil) { + return ioutil.WriteFile( + filepath.Join(p.Path(path), "rdma.max"), + []byte(createCmdString(device, &limit)), + defaultFilePerm, + ) + } + } + return nil +} + +func (p *rdmaController) Update(path string, resources *specs.LinuxResources) error { + return p.Create(path, resources) +} + +func parseRdmaKV(raw string, entry *RdmaEntry) { + var value uint64 + var err error + + parts := strings.Split(raw, "=") + switch len(parts) { + case 2: + if parts[1] == "max" { + value = math.MaxUint32 + } else { + value, err = parseUint(parts[1], 10, 32) + if err != nil { + return + } + } + if parts[0] == "hca_handle" { + entry.HcaHandles = uint32(value) + } else if parts[0] == "hca_object" { + entry.HcaObjects = uint32(value) + } + } +} + +func toRdmaEntry(strEntries []string) []*RdmaEntry { + var rdmaEntries []*RdmaEntry + for i := range strEntries { + parts := strings.Fields(strEntries[i]) + switch len(parts) { + case 3: + entry := new(RdmaEntry) + entry.Device = parts[0] + parseRdmaKV(parts[1], entry) + parseRdmaKV(parts[2], entry) + + rdmaEntries = append(rdmaEntries, entry) + default: + continue + } + } + return rdmaEntries +} + +func (p *rdmaController) Stat(path string, stats *Metrics) error { + + currentData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "rdma.current")) + if err != nil { + return err + } + currentPerDevices := strings.Split(string(currentData), "\n") + + maxData, err := ioutil.ReadFile(filepath.Join(p.Path(path), "rdma.max")) + if err != nil { + return err + } + maxPerDevices := strings.Split(string(maxData), "\n") + + // If device got removed between reading two files, ignore returning + // stats. + if len(currentPerDevices) != len(maxPerDevices) { + return nil + } + + currentEntries := toRdmaEntry(currentPerDevices) + maxEntries := toRdmaEntry(maxPerDevices) + + stats.Rdma = &RdmaStat{ + Current: currentEntries, + Limit: maxEntries, + } + return nil +} diff --git a/vendor/github.com/containerd/cgroups/subsystem.go b/vendor/github.com/containerd/cgroups/subsystem.go index e1f10ec68f..933a6c38d6 100644 --- a/vendor/github.com/containerd/cgroups/subsystem.go +++ b/vendor/github.com/containerd/cgroups/subsystem.go @@ -38,6 +38,7 @@ const ( Cpuacct Name = "cpuacct" Memory Name = "memory" Blkio Name = "blkio" + Rdma Name = "rdma" ) // Subsystems returns a complete list of the default cgroups @@ -55,6 +56,7 @@ func Subsystems() []Name { Cpuacct, Memory, Blkio, + Rdma, } if !isUserNS { n = append(n, Devices) diff --git a/vendor/github.com/containerd/cgroups/utils.go b/vendor/github.com/containerd/cgroups/utils.go index 4e6a270544..345be4e463 100644 --- a/vendor/github.com/containerd/cgroups/utils.go +++ b/vendor/github.com/containerd/cgroups/utils.go @@ -80,6 +80,7 @@ func defaults(root string) ([]Subsystem, error) { NewCpuacct(root), NewMemory(root), NewBlkio(root), + NewRdma(root), } // only add the devices cgroup if we are not in a user namespace // because modifications are not allowed diff --git a/vendor/github.com/containerd/containerd/README.md b/vendor/github.com/containerd/containerd/README.md index 2130d68cfe..a8acc9181e 100644 --- a/vendor/github.com/containerd/containerd/README.md +++ b/vendor/github.com/containerd/containerd/README.md @@ -166,7 +166,7 @@ If you have [criu](https://criu.org/Main_Page) installed on your machine you can ```go // checkpoint the task then push it to a registry -checkpoint, err := task.Checkpoint(context, containerd.WithExit) +checkpoint, err := task.Checkpoint(context) err := client.Push(context, "myregistry/checkpoints/redis:master", checkpoint) @@ -184,6 +184,28 @@ defer task.Delete(context) err := task.Start(context) ``` +### Snapshot Plugins + +In addition to the built-in Snapshot plugins in containerd, additional external +plugins can be configured using GRPC. An external plugin is made available using +the configured name and appears as a plugin alongside the built-in ones. + +To add an external snapshot plugin, add the plugin to containerd's config file +(by default at `/etc/containerd/config.toml`). The string following +`proxy_plugin.` will be used as the name of the snapshotter and the address +should refer to a socket with a GRPC listener serving containerd's Snapshot +GRPC API. Remember to restart containerd for any configuration changes to take +effect. + +``` +[proxy_plugins] + [proxy_plugins.customsnapshot] + type = "snapshot" + address = "/var/run/mysnapshotter.sock" +``` + +See [PLUGINS.md](PLUGINS.md) for how to create plugins + ### Releases and API Stability Please see [RELEASES.md](RELEASES.md) for details on versioning and stability diff --git a/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.pb.go b/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.pb.go index a8720bb6ff..4d9322164e 100644 --- a/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.pb.go +++ b/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.pb.go @@ -18,6 +18,7 @@ UpdateContainerRequest UpdateContainerResponse DeleteContainerRequest + ListContainerMessage */ package containers @@ -218,6 +219,14 @@ func (m *DeleteContainerRequest) Reset() { *m = DeleteContain func (*DeleteContainerRequest) ProtoMessage() {} func (*DeleteContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorContainers, []int{9} } +type ListContainerMessage struct { + Container *Container `protobuf:"bytes,1,opt,name=container" json:"container,omitempty"` +} + +func (m *ListContainerMessage) Reset() { *m = ListContainerMessage{} } +func (*ListContainerMessage) ProtoMessage() {} +func (*ListContainerMessage) Descriptor() ([]byte, []int) { return fileDescriptorContainers, []int{10} } + func init() { proto.RegisterType((*Container)(nil), "containerd.services.containers.v1.Container") proto.RegisterType((*Container_Runtime)(nil), "containerd.services.containers.v1.Container.Runtime") @@ -230,6 +239,7 @@ func init() { proto.RegisterType((*UpdateContainerRequest)(nil), "containerd.services.containers.v1.UpdateContainerRequest") proto.RegisterType((*UpdateContainerResponse)(nil), "containerd.services.containers.v1.UpdateContainerResponse") proto.RegisterType((*DeleteContainerRequest)(nil), "containerd.services.containers.v1.DeleteContainerRequest") + proto.RegisterType((*ListContainerMessage)(nil), "containerd.services.containers.v1.ListContainerMessage") } // Reference imports to suppress errors if they are not otherwise used. @@ -245,6 +255,7 @@ const _ = grpc.SupportPackageIsVersion4 type ContainersClient interface { Get(ctx context.Context, in *GetContainerRequest, opts ...grpc.CallOption) (*GetContainerResponse, error) List(ctx context.Context, in *ListContainersRequest, opts ...grpc.CallOption) (*ListContainersResponse, error) + ListStream(ctx context.Context, in *ListContainersRequest, opts ...grpc.CallOption) (Containers_ListStreamClient, error) Create(ctx context.Context, in *CreateContainerRequest, opts ...grpc.CallOption) (*CreateContainerResponse, error) Update(ctx context.Context, in *UpdateContainerRequest, opts ...grpc.CallOption) (*UpdateContainerResponse, error) Delete(ctx context.Context, in *DeleteContainerRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) @@ -276,6 +287,38 @@ func (c *containersClient) List(ctx context.Context, in *ListContainersRequest, return out, nil } +func (c *containersClient) ListStream(ctx context.Context, in *ListContainersRequest, opts ...grpc.CallOption) (Containers_ListStreamClient, error) { + stream, err := grpc.NewClientStream(ctx, &_Containers_serviceDesc.Streams[0], c.cc, "/containerd.services.containers.v1.Containers/ListStream", opts...) + if err != nil { + return nil, err + } + x := &containersListStreamClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Containers_ListStreamClient interface { + Recv() (*ListContainerMessage, error) + grpc.ClientStream +} + +type containersListStreamClient struct { + grpc.ClientStream +} + +func (x *containersListStreamClient) Recv() (*ListContainerMessage, error) { + m := new(ListContainerMessage) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *containersClient) Create(ctx context.Context, in *CreateContainerRequest, opts ...grpc.CallOption) (*CreateContainerResponse, error) { out := new(CreateContainerResponse) err := grpc.Invoke(ctx, "/containerd.services.containers.v1.Containers/Create", in, out, c.cc, opts...) @@ -308,6 +351,7 @@ func (c *containersClient) Delete(ctx context.Context, in *DeleteContainerReques type ContainersServer interface { Get(context.Context, *GetContainerRequest) (*GetContainerResponse, error) List(context.Context, *ListContainersRequest) (*ListContainersResponse, error) + ListStream(*ListContainersRequest, Containers_ListStreamServer) error Create(context.Context, *CreateContainerRequest) (*CreateContainerResponse, error) Update(context.Context, *UpdateContainerRequest) (*UpdateContainerResponse, error) Delete(context.Context, *DeleteContainerRequest) (*google_protobuf2.Empty, error) @@ -353,6 +397,27 @@ func _Containers_List_Handler(srv interface{}, ctx context.Context, dec func(int return interceptor(ctx, in, info, handler) } +func _Containers_ListStream_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListContainersRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ContainersServer).ListStream(m, &containersListStreamServer{stream}) +} + +type Containers_ListStreamServer interface { + Send(*ListContainerMessage) error + grpc.ServerStream +} + +type containersListStreamServer struct { + grpc.ServerStream +} + +func (x *containersListStreamServer) Send(m *ListContainerMessage) error { + return x.ServerStream.SendMsg(m) +} + func _Containers_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateContainerRequest) if err := dec(in); err != nil { @@ -432,7 +497,13 @@ var _Containers_serviceDesc = grpc.ServiceDesc{ Handler: _Containers_Delete_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "ListStream", + Handler: _Containers_ListStream_Handler, + ServerStreams: true, + }, + }, Metadata: "github.com/containerd/containerd/api/services/containers/v1/containers.proto", } @@ -842,6 +913,34 @@ func (m *DeleteContainerRequest) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *ListContainerMessage) 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 *ListContainerMessage) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Container != nil { + dAtA[i] = 0xa + i++ + i = encodeVarintContainers(dAtA, i, uint64(m.Container.Size())) + n13, err := m.Container.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n13 + } + return i, nil +} + func encodeVarintContainers(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -1004,6 +1103,16 @@ func (m *DeleteContainerRequest) Size() (n int) { return n } +func (m *ListContainerMessage) Size() (n int) { + var l int + _ = l + if m.Container != nil { + l = m.Container.Size() + n += 1 + l + sovContainers(uint64(l)) + } + return n +} + func sovContainers(x uint64) (n int) { for { n++ @@ -1158,6 +1267,16 @@ func (this *DeleteContainerRequest) String() string { }, "") return s } +func (this *ListContainerMessage) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ListContainerMessage{`, + `Container:` + strings.Replace(fmt.Sprintf("%v", this.Container), "Container", "Container", 1) + `,`, + `}`, + }, "") + return s +} func valueToStringContainers(v interface{}) string { rv := reflect.ValueOf(v) if rv.IsNil() { @@ -2562,6 +2681,89 @@ func (m *DeleteContainerRequest) Unmarshal(dAtA []byte) error { } return nil } +func (m *ListContainerMessage) 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 ErrIntOverflowContainers + } + 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: ListContainerMessage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ListContainerMessage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Container", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowContainers + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthContainers + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Container == nil { + m.Container = &Container{} + } + if err := m.Container.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipContainers(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthContainers + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipContainers(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 @@ -2672,54 +2874,57 @@ func init() { } var fileDescriptorContainers = []byte{ - // 776 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcd, 0x72, 0xd2, 0x50, - 0x14, 0x26, 0x81, 0x86, 0x72, 0x70, 0x46, 0xe7, 0x8a, 0x18, 0xe3, 0x0c, 0x50, 0x56, 0x8c, 0xa3, - 0xc1, 0xa2, 0xa3, 0xfd, 0x71, 0x53, 0xfa, 0x37, 0x8e, 0xad, 0xd3, 0x89, 0x3a, 0xe3, 0xe8, 0xa2, - 0x06, 0xb8, 0xa5, 0x91, 0xfc, 0x99, 0x7b, 0x61, 0x64, 0x5c, 0xe8, 0x23, 0xb8, 0xf3, 0x11, 0x7c, - 0x95, 0x2e, 0x5d, 0xba, 0xaa, 0x2d, 0x4f, 0xe2, 0xe4, 0x26, 0x21, 0x29, 0x04, 0x85, 0x2a, 0xbb, - 0x7b, 0xb8, 0xe7, 0xfb, 0xce, 0xc7, 0x77, 0xce, 0xb9, 0x00, 0x7b, 0x6d, 0x8d, 0x1e, 0x77, 0x1b, - 0x72, 0xd3, 0x32, 0xaa, 0x4d, 0xcb, 0xa4, 0xaa, 0x66, 0x62, 0xa7, 0x15, 0x3d, 0xaa, 0xb6, 0x56, - 0x25, 0xd8, 0xe9, 0x69, 0x4d, 0x4c, 0xc2, 0xcf, 0x49, 0xb5, 0xb7, 0x1c, 0x89, 0x64, 0xdb, 0xb1, - 0xa8, 0x85, 0x96, 0x42, 0x9c, 0x1c, 0x60, 0xe4, 0x48, 0x56, 0x6f, 0x59, 0xca, 0xb5, 0xad, 0xb6, - 0xc5, 0xb2, 0xab, 0xee, 0xc9, 0x03, 0x4a, 0xb7, 0xda, 0x96, 0xd5, 0xd6, 0x71, 0x95, 0x45, 0x8d, - 0xee, 0x51, 0x55, 0x35, 0xfb, 0xfe, 0xd5, 0xed, 0xd1, 0x2b, 0x6c, 0xd8, 0x34, 0xb8, 0x2c, 0x8d, - 0x5e, 0x1e, 0x69, 0x58, 0x6f, 0x1d, 0x1a, 0x2a, 0xe9, 0xf8, 0x19, 0xc5, 0xd1, 0x0c, 0xaa, 0x19, - 0x98, 0x50, 0xd5, 0xb0, 0xbd, 0x84, 0xf2, 0x37, 0x01, 0x32, 0x9b, 0x81, 0x44, 0x94, 0x07, 0x5e, - 0x6b, 0x89, 0x5c, 0x89, 0xab, 0x64, 0xea, 0xc2, 0xe0, 0xb4, 0xc8, 0x3f, 0xdd, 0x52, 0x78, 0xad, - 0x85, 0x0e, 0x40, 0xd0, 0xd5, 0x06, 0xd6, 0x89, 0xc8, 0x97, 0x92, 0x95, 0x6c, 0x6d, 0x45, 0xfe, - 0xeb, 0x57, 0x95, 0x87, 0xac, 0xf2, 0x1e, 0x83, 0x6e, 0x9b, 0xd4, 0xe9, 0x2b, 0x3e, 0x0f, 0xca, - 0xc1, 0x82, 0x66, 0xa8, 0x6d, 0x2c, 0x26, 0xdd, 0x62, 0x8a, 0x17, 0xa0, 0xe7, 0x90, 0x76, 0xba, - 0xa6, 0xab, 0x51, 0x4c, 0x95, 0xb8, 0x4a, 0xb6, 0xf6, 0x70, 0xa6, 0x42, 0x8a, 0x87, 0x55, 0x02, - 0x12, 0x54, 0x81, 0x14, 0xb1, 0x71, 0x53, 0x5c, 0x60, 0x64, 0x39, 0xd9, 0x73, 0x43, 0x0e, 0xdc, - 0x90, 0x37, 0xcc, 0xbe, 0xc2, 0x32, 0x50, 0x09, 0xb2, 0xc4, 0x54, 0x6d, 0x72, 0x6c, 0x51, 0x8a, - 0x1d, 0x51, 0x60, 0xaa, 0xa2, 0x1f, 0xa1, 0x25, 0xb8, 0x12, 0x84, 0x87, 0x1d, 0xdc, 0x17, 0xd3, - 0x17, 0x53, 0x9e, 0xe1, 0x3e, 0xda, 0x04, 0x68, 0x3a, 0x58, 0xa5, 0xb8, 0x75, 0xa8, 0x52, 0x71, - 0x91, 0x15, 0x95, 0xc6, 0x8a, 0xbe, 0x0c, 0x5a, 0x50, 0x5f, 0x3c, 0x39, 0x2d, 0x26, 0xbe, 0xfe, - 0x2a, 0x72, 0x4a, 0xc6, 0xc7, 0x6d, 0x50, 0x97, 0xa4, 0x6b, 0xb7, 0x02, 0x92, 0xcc, 0x2c, 0x24, - 0x3e, 0x6e, 0x83, 0xa2, 0x06, 0x00, 0xfe, 0x48, 0xb1, 0x49, 0x34, 0xcb, 0x24, 0x22, 0xb0, 0xa6, - 0x3d, 0x99, 0xc9, 0xcb, 0xed, 0x21, 0x9c, 0x35, 0xae, 0x9e, 0x72, 0xcb, 0x28, 0x11, 0x56, 0x69, - 0x15, 0xb2, 0x91, 0xce, 0xa2, 0x6b, 0x90, 0x74, 0x6d, 0x61, 0xc3, 0xa3, 0xb8, 0x47, 0xb7, 0xc7, - 0x3d, 0x55, 0xef, 0x62, 0x91, 0xf7, 0x7a, 0xcc, 0x82, 0x35, 0x7e, 0x85, 0x93, 0xf6, 0x21, 0xed, - 0xf7, 0x0a, 0x21, 0x48, 0x99, 0xaa, 0x81, 0x7d, 0x1c, 0x3b, 0x23, 0x19, 0xd2, 0x96, 0x4d, 0x99, - 0x74, 0xfe, 0x0f, 0x9d, 0x0b, 0x92, 0xa4, 0x17, 0x70, 0x75, 0x44, 0x6e, 0x8c, 0x9a, 0x3b, 0x51, - 0x35, 0x93, 0x28, 0x43, 0x8d, 0xe5, 0x7b, 0x70, 0x7d, 0x17, 0xd3, 0xa1, 0x21, 0x0a, 0xfe, 0xd0, - 0xc5, 0x84, 0x4e, 0x5a, 0x91, 0xf2, 0x31, 0xe4, 0x2e, 0xa6, 0x13, 0xdb, 0x32, 0x09, 0x46, 0x07, - 0x90, 0x19, 0x5a, 0xcc, 0x60, 0xd9, 0xda, 0xdd, 0x59, 0x1a, 0xe1, 0x1b, 0x1f, 0x92, 0x94, 0x97, - 0xe1, 0xc6, 0x9e, 0x46, 0xc2, 0x52, 0x24, 0x90, 0x26, 0x42, 0xfa, 0x48, 0xd3, 0x29, 0x76, 0x88, - 0xc8, 0x95, 0x92, 0x95, 0x8c, 0x12, 0x84, 0x65, 0x1d, 0xf2, 0xa3, 0x10, 0x5f, 0x9e, 0x02, 0x10, - 0x16, 0x66, 0xb0, 0xcb, 0xe9, 0x8b, 0xb0, 0x94, 0xdf, 0x43, 0x7e, 0x93, 0x8d, 0xf3, 0x98, 0x79, - 0xff, 0xdf, 0x8c, 0x0e, 0xdc, 0x1c, 0xab, 0x35, 0x37, 0xe7, 0xbf, 0x73, 0x90, 0x7f, 0xc5, 0x76, - 0x6c, 0xfe, 0xdf, 0x0c, 0xad, 0x43, 0xd6, 0xdb, 0x67, 0xf6, 0x9e, 0xfb, 0x53, 0x3b, 0xfe, 0x10, - 0xec, 0xb8, 0x4f, 0xfe, 0xbe, 0x4a, 0x3a, 0x8a, 0xff, 0x6c, 0xb8, 0x67, 0xd7, 0x96, 0x31, 0xa1, - 0x73, 0xb3, 0xe5, 0x3e, 0xe4, 0xb7, 0xb0, 0x8e, 0x63, 0x5c, 0x99, 0xb0, 0x2c, 0xb5, 0xb3, 0x14, - 0x40, 0x38, 0x8c, 0xa8, 0x07, 0xc9, 0x5d, 0x4c, 0xd1, 0xa3, 0x29, 0x64, 0xc4, 0xac, 0xa4, 0xf4, - 0x78, 0x66, 0x9c, 0x6f, 0xc5, 0x27, 0x48, 0xb9, 0x6b, 0x81, 0xa6, 0xf9, 0x39, 0x8b, 0x5d, 0x39, - 0x69, 0xf5, 0x12, 0x48, 0xbf, 0xf8, 0x67, 0x10, 0xbc, 0xc9, 0x45, 0xd3, 0x90, 0xc4, 0x2f, 0x94, - 0xb4, 0x76, 0x19, 0x68, 0x28, 0xc0, 0x9b, 0x91, 0xa9, 0x04, 0xc4, 0xcf, 0xfd, 0x54, 0x02, 0x26, - 0x4d, 0xe2, 0x5b, 0x10, 0xbc, 0xb9, 0x99, 0x4a, 0x40, 0xfc, 0x88, 0x49, 0xf9, 0xb1, 0x8d, 0xd8, - 0x76, 0xff, 0x21, 0xd5, 0xdf, 0x9d, 0x9c, 0x17, 0x12, 0x3f, 0xcf, 0x0b, 0x89, 0x2f, 0x83, 0x02, - 0x77, 0x32, 0x28, 0x70, 0x3f, 0x06, 0x05, 0xee, 0x6c, 0x50, 0xe0, 0xde, 0xec, 0xfc, 0xc3, 0x9f, - 0xbe, 0xf5, 0x30, 0x7a, 0x9d, 0x68, 0x08, 0xac, 0xe6, 0x83, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, - 0x95, 0x94, 0x84, 0xf2, 0x47, 0x0a, 0x00, 0x00, + // 820 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcb, 0x6e, 0x13, 0x49, + 0x14, 0x75, 0xdb, 0x4e, 0x3b, 0xbe, 0x1e, 0x69, 0x46, 0x35, 0x1e, 0x4f, 0x4f, 0x8f, 0x64, 0x3b, + 0x5e, 0x59, 0xa3, 0xa1, 0x9d, 0x18, 0x44, 0x5e, 0x6c, 0xe2, 0xbc, 0x04, 0x24, 0x28, 0xea, 0x80, + 0x84, 0x60, 0x11, 0xda, 0x76, 0xc5, 0x69, 0xdc, 0x2f, 0xba, 0xca, 0x16, 0x16, 0x8b, 0xc0, 0x1f, + 0xb0, 0xe3, 0x13, 0xf8, 0x95, 0x2c, 0x59, 0xb2, 0x0a, 0xc4, 0xe2, 0x43, 0x50, 0x57, 0x57, 0xbb, + 0x3b, 0x7e, 0x80, 0x9d, 0x90, 0x5d, 0x5d, 0xd7, 0x3d, 0xf7, 0x9e, 0x3a, 0xb7, 0x4e, 0xb9, 0x61, + 0xaf, 0xa5, 0xd3, 0x93, 0x4e, 0x5d, 0x69, 0xd8, 0x66, 0xa5, 0x61, 0x5b, 0x54, 0xd3, 0x2d, 0xec, + 0x36, 0xa3, 0x4b, 0xcd, 0xd1, 0x2b, 0x04, 0xbb, 0x5d, 0xbd, 0x81, 0x49, 0xf8, 0x3b, 0xa9, 0x74, + 0x97, 0x22, 0x91, 0xe2, 0xb8, 0x36, 0xb5, 0xd1, 0x42, 0x88, 0x53, 0x02, 0x8c, 0x12, 0xc9, 0xea, + 0x2e, 0xc9, 0xd9, 0x96, 0xdd, 0xb2, 0x59, 0x76, 0xc5, 0x5b, 0xf9, 0x40, 0xf9, 0x9f, 0x96, 0x6d, + 0xb7, 0x0c, 0x5c, 0x61, 0x51, 0xbd, 0x73, 0x5c, 0xd1, 0xac, 0x1e, 0xdf, 0xfa, 0x77, 0x78, 0x0b, + 0x9b, 0x0e, 0x0d, 0x36, 0x8b, 0xc3, 0x9b, 0xc7, 0x3a, 0x36, 0x9a, 0x47, 0xa6, 0x46, 0xda, 0x3c, + 0xa3, 0x30, 0x9c, 0x41, 0x75, 0x13, 0x13, 0xaa, 0x99, 0x8e, 0x9f, 0x50, 0xfa, 0x20, 0x42, 0x7a, + 0x33, 0xa0, 0x88, 0x72, 0x10, 0xd7, 0x9b, 0x92, 0x50, 0x14, 0xca, 0xe9, 0x9a, 0xd8, 0x3f, 0x2f, + 0xc4, 0xef, 0x6f, 0xa9, 0x71, 0xbd, 0x89, 0x0e, 0x40, 0x34, 0xb4, 0x3a, 0x36, 0x88, 0x14, 0x2f, + 0x26, 0xca, 0x99, 0xea, 0x8a, 0xf2, 0xd3, 0xa3, 0x2a, 0x83, 0xaa, 0xca, 0x1e, 0x83, 0x6e, 0x5b, + 0xd4, 0xed, 0xa9, 0xbc, 0x0e, 0xca, 0xc2, 0x9c, 0x6e, 0x6a, 0x2d, 0x2c, 0x25, 0xbc, 0x66, 0xaa, + 0x1f, 0xa0, 0x47, 0x90, 0x72, 0x3b, 0x96, 0xc7, 0x51, 0x4a, 0x16, 0x85, 0x72, 0xa6, 0x7a, 0x67, + 0xa6, 0x46, 0xaa, 0x8f, 0x55, 0x83, 0x22, 0xa8, 0x0c, 0x49, 0xe2, 0xe0, 0x86, 0x34, 0xc7, 0x8a, + 0x65, 0x15, 0x5f, 0x0d, 0x25, 0x50, 0x43, 0xd9, 0xb0, 0x7a, 0x2a, 0xcb, 0x40, 0x45, 0xc8, 0x10, + 0x4b, 0x73, 0xc8, 0x89, 0x4d, 0x29, 0x76, 0x25, 0x91, 0xb1, 0x8a, 0xfe, 0x84, 0x16, 0xe0, 0xb7, + 0x20, 0x3c, 0x6a, 0xe3, 0x9e, 0x94, 0xba, 0x9c, 0xf2, 0x10, 0xf7, 0xd0, 0x26, 0x40, 0xc3, 0xc5, + 0x1a, 0xc5, 0xcd, 0x23, 0x8d, 0x4a, 0xf3, 0xac, 0xa9, 0x3c, 0xd2, 0xf4, 0x71, 0x30, 0x82, 0xda, + 0xfc, 0xd9, 0x79, 0x21, 0xf6, 0xfe, 0x4b, 0x41, 0x50, 0xd3, 0x1c, 0xb7, 0x41, 0xbd, 0x22, 0x1d, + 0xa7, 0x19, 0x14, 0x49, 0xcf, 0x52, 0x84, 0xe3, 0x36, 0x28, 0xaa, 0x03, 0xe0, 0xd7, 0x14, 0x5b, + 0x44, 0xb7, 0x2d, 0x22, 0x01, 0x1b, 0xda, 0xbd, 0x99, 0xb4, 0xdc, 0x1e, 0xc0, 0xd9, 0xe0, 0x6a, + 0x49, 0xaf, 0x8d, 0x1a, 0xa9, 0x2a, 0xaf, 0x42, 0x26, 0x32, 0x59, 0xf4, 0x07, 0x24, 0x3c, 0x59, + 0xd8, 0xe5, 0x51, 0xbd, 0xa5, 0x37, 0xe3, 0xae, 0x66, 0x74, 0xb0, 0x14, 0xf7, 0x67, 0xcc, 0x82, + 0xb5, 0xf8, 0x8a, 0x20, 0xef, 0x43, 0x8a, 0xcf, 0x0a, 0x21, 0x48, 0x5a, 0x9a, 0x89, 0x39, 0x8e, + 0xad, 0x91, 0x02, 0x29, 0xdb, 0xa1, 0x8c, 0x7a, 0xfc, 0x07, 0x93, 0x0b, 0x92, 0xe4, 0x43, 0xf8, + 0x7d, 0x88, 0xee, 0x18, 0x36, 0xff, 0x45, 0xd9, 0x4c, 0x2a, 0x19, 0x72, 0x2c, 0xdd, 0x82, 0x3f, + 0x77, 0x31, 0x1d, 0x08, 0xa2, 0xe2, 0x57, 0x1d, 0x4c, 0xe8, 0x24, 0x8b, 0x94, 0x4e, 0x20, 0x7b, + 0x39, 0x9d, 0x38, 0xb6, 0x45, 0x30, 0x3a, 0x80, 0xf4, 0x40, 0x62, 0x06, 0xcb, 0x54, 0xff, 0x9f, + 0x65, 0x10, 0x5c, 0xf8, 0xb0, 0x48, 0x69, 0x09, 0xfe, 0xda, 0xd3, 0x49, 0xd8, 0x8a, 0x04, 0xd4, + 0x24, 0x48, 0x1d, 0xeb, 0x06, 0xc5, 0x2e, 0x91, 0x84, 0x62, 0xa2, 0x9c, 0x56, 0x83, 0xb0, 0x64, + 0x40, 0x6e, 0x18, 0xc2, 0xe9, 0xa9, 0x00, 0x61, 0x63, 0x06, 0xbb, 0x1a, 0xbf, 0x48, 0x95, 0xd2, + 0x4b, 0xc8, 0x6d, 0xb2, 0xeb, 0x3c, 0x22, 0xde, 0xaf, 0x17, 0xa3, 0x0d, 0x7f, 0x8f, 0xf4, 0xba, + 0x31, 0xe5, 0x3f, 0x0a, 0x90, 0x7b, 0xc2, 0x3c, 0x76, 0xf3, 0x27, 0x43, 0xeb, 0x90, 0xf1, 0xfd, + 0xcc, 0xde, 0x73, 0x7e, 0x6b, 0x47, 0x1f, 0x82, 0x1d, 0xef, 0xc9, 0xdf, 0xd7, 0x48, 0x5b, 0xe5, + 0xcf, 0x86, 0xb7, 0xf6, 0x64, 0x19, 0x21, 0x7a, 0x63, 0xb2, 0x2c, 0x42, 0x6e, 0x0b, 0x1b, 0x78, + 0x8c, 0x2a, 0x93, 0xcc, 0x52, 0x87, 0xec, 0xa5, 0xfb, 0xb8, 0x8f, 0x09, 0xf1, 0xde, 0xff, 0x07, + 0xd7, 0xe4, 0x16, 0x61, 0x55, 0xfd, 0x36, 0x07, 0x10, 0x5e, 0x78, 0xd4, 0x85, 0xc4, 0x2e, 0xa6, + 0xe8, 0xee, 0x14, 0xe5, 0xc6, 0xd8, 0x5e, 0x5e, 0x9e, 0x19, 0xc7, 0xe5, 0x7e, 0x03, 0x49, 0xef, + 0xa8, 0x68, 0x9a, 0xbf, 0xcc, 0xb1, 0xb6, 0x96, 0x57, 0xaf, 0x80, 0xe4, 0xcd, 0xdf, 0x09, 0x00, + 0xde, 0xd6, 0x21, 0x75, 0xb1, 0x66, 0x5e, 0x83, 0xc3, 0xf2, 0xac, 0x48, 0x3e, 0xd1, 0x45, 0x01, + 0x9d, 0x82, 0xe8, 0x3b, 0x14, 0x4d, 0x73, 0x90, 0xf1, 0x0f, 0x87, 0xbc, 0x76, 0x15, 0x28, 0x17, + 0xe1, 0x14, 0x44, 0xdf, 0x0b, 0x53, 0x11, 0x18, 0xef, 0xef, 0xa9, 0x08, 0x4c, 0x72, 0xdc, 0x73, + 0x10, 0x7d, 0x7f, 0x4c, 0x45, 0x60, 0xbc, 0x95, 0xe4, 0xdc, 0x88, 0xf3, 0xb7, 0xbd, 0x2f, 0xc1, + 0xda, 0x8b, 0xb3, 0x8b, 0x7c, 0xec, 0xf3, 0x45, 0x3e, 0xf6, 0xb6, 0x9f, 0x17, 0xce, 0xfa, 0x79, + 0xe1, 0x53, 0x3f, 0x2f, 0x7c, 0xed, 0xe7, 0x85, 0x67, 0x3b, 0xd7, 0xf8, 0xb8, 0x5d, 0x0f, 0xa3, + 0xa7, 0xb1, 0xba, 0xc8, 0x7a, 0xde, 0xfe, 0x1e, 0x00, 0x00, 0xff, 0xff, 0xd0, 0xae, 0xca, 0xcb, + 0x2f, 0x0b, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.proto b/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.proto index b7b32d949a..d491f46cfa 100644 --- a/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.proto +++ b/vendor/github.com/containerd/containerd/api/services/containers/v1/containers.proto @@ -29,6 +29,7 @@ option go_package = "github.com/containerd/containerd/api/services/containers/v1 service Containers { rpc Get(GetContainerRequest) returns (GetContainerResponse); rpc List(ListContainersRequest) returns (ListContainersResponse); + rpc ListStream(ListContainersRequest) returns (stream ListContainerMessage); rpc Create(CreateContainerRequest) returns (CreateContainerResponse); rpc Update(UpdateContainerRequest) returns (UpdateContainerResponse); rpc Delete(DeleteContainerRequest) returns (google.protobuf.Empty); @@ -156,3 +157,7 @@ message UpdateContainerResponse { message DeleteContainerRequest { string id = 1; } + +message ListContainerMessage { + Container container = 1; +} diff --git a/vendor/github.com/containerd/containerd/api/services/leases/v1/leases.pb.go b/vendor/github.com/containerd/containerd/api/services/leases/v1/leases.pb.go index 3472b1ff97..1222c1aec0 100644 --- a/vendor/github.com/containerd/containerd/api/services/leases/v1/leases.pb.go +++ b/vendor/github.com/containerd/containerd/api/services/leases/v1/leases.pb.go @@ -82,6 +82,11 @@ func (*CreateResponse) Descriptor() ([]byte, []int) { return fileDescriptorLease type DeleteRequest struct { ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Sync indicates that the delete and cleanup should be done + // synchronously before returning to the caller + // + // Default is false + Sync bool `protobuf:"varint,2,opt,name=sync,proto3" json:"sync,omitempty"` } func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } @@ -404,6 +409,16 @@ func (m *DeleteRequest) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintLeases(dAtA, i, uint64(len(m.ID))) i += copy(dAtA[i:], m.ID) } + if m.Sync { + dAtA[i] = 0x10 + i++ + if m.Sync { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } return i, nil } @@ -534,6 +549,9 @@ func (m *DeleteRequest) Size() (n int) { if l > 0 { n += 1 + l + sovLeases(uint64(l)) } + if m.Sync { + n += 2 + } return n } @@ -633,6 +651,7 @@ func (this *DeleteRequest) String() string { } s := strings.Join([]string{`&DeleteRequest{`, `ID:` + fmt.Sprintf("%v", this.ID) + `,`, + `Sync:` + fmt.Sprintf("%v", this.Sync) + `,`, `}`, }, "") return s @@ -1230,6 +1249,26 @@ func (m *DeleteRequest) Unmarshal(dAtA []byte) error { } m.ID = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Sync", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLeases + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.Sync = bool(v != 0) default: iNdEx = preIndex skippy, err := skipLeases(dAtA[iNdEx:]) @@ -1521,37 +1560,38 @@ func init() { } var fileDescriptorLeases = []byte{ - // 504 bytes of a gzipped FileDescriptorProto + // 515 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xdf, 0x8a, 0xd3, 0x40, - 0x14, 0xc6, 0x3b, 0xa9, 0x8d, 0xf6, 0xc4, 0x15, 0x19, 0x96, 0x25, 0x44, 0x4c, 0x4b, 0x10, 0xb6, - 0xf8, 0x67, 0xe2, 0xd6, 0x9b, 0x75, 0x15, 0xc1, 0x6e, 0x17, 0x14, 0x82, 0x48, 0xf0, 0x62, 0xf1, - 0x66, 0x49, 0xdb, 0xb3, 0x31, 0x98, 0x36, 0x31, 0x33, 0x2d, 0xf4, 0xce, 0x47, 0xf0, 0x11, 0x7c, - 0x08, 0x1f, 0xa2, 0x97, 0x5e, 0x7a, 0xb5, 0xba, 0xb9, 0xf3, 0x2d, 0x24, 0x33, 0x09, 0xbb, 0x5b, - 0xd1, 0x56, 0xd9, 0xbb, 0x33, 0x99, 0xef, 0x3b, 0xe7, 0x77, 0x3e, 0x98, 0x40, 0x3f, 0x8c, 0xc4, - 0xbb, 0xe9, 0x80, 0x0d, 0x93, 0xb1, 0x3b, 0x4c, 0x26, 0x22, 0x88, 0x26, 0x98, 0x8d, 0xce, 0x97, - 0x41, 0x1a, 0xb9, 0x1c, 0xb3, 0x59, 0x34, 0x44, 0xee, 0xc6, 0x18, 0x70, 0xe4, 0xee, 0x6c, 0xa7, - 0xac, 0x58, 0x9a, 0x25, 0x22, 0xa1, 0xb7, 0xcf, 0xf4, 0xac, 0xd2, 0xb2, 0x52, 0x31, 0xdb, 0xb1, - 0x36, 0xc3, 0x24, 0x4c, 0xa4, 0xd2, 0x2d, 0x2a, 0x65, 0xb2, 0x6e, 0x85, 0x49, 0x12, 0xc6, 0xe8, - 0xca, 0xd3, 0x60, 0x7a, 0xec, 0xe2, 0x38, 0x15, 0xf3, 0xf2, 0xb2, 0xb5, 0x7c, 0x29, 0xa2, 0x31, - 0x72, 0x11, 0x8c, 0x53, 0x25, 0x70, 0x7e, 0x12, 0x68, 0x78, 0xc5, 0x04, 0xba, 0x05, 0x5a, 0x34, - 0x32, 0x49, 0x9b, 0x74, 0x9a, 0x3d, 0x3d, 0x3f, 0x69, 0x69, 0x2f, 0xfb, 0xbe, 0x16, 0x8d, 0xe8, - 0x3e, 0xc0, 0x30, 0xc3, 0x40, 0xe0, 0xe8, 0x28, 0x10, 0xa6, 0xd6, 0x26, 0x1d, 0xa3, 0x6b, 0x31, - 0xd5, 0x97, 0x55, 0x7d, 0xd9, 0x9b, 0xaa, 0x6f, 0xef, 0xda, 0xe2, 0xa4, 0x55, 0xfb, 0xf4, 0xbd, - 0x45, 0xfc, 0x66, 0xe9, 0x7b, 0x2e, 0xe8, 0x0b, 0xd0, 0xe3, 0x60, 0x80, 0x31, 0x37, 0xeb, 0xed, - 0x7a, 0xc7, 0xe8, 0x3e, 0x64, 0x7f, 0x5d, 0x95, 0x49, 0x24, 0xe6, 0x49, 0xcb, 0xc1, 0x44, 0x64, - 0x73, 0xbf, 0xf4, 0x5b, 0x8f, 0xc1, 0x38, 0xf7, 0x99, 0xde, 0x84, 0xfa, 0x7b, 0x9c, 0x2b, 0x6c, - 0xbf, 0x28, 0xe9, 0x26, 0x34, 0x66, 0x41, 0x3c, 0x45, 0x89, 0xda, 0xf4, 0xd5, 0x61, 0x4f, 0xdb, - 0x25, 0xce, 0x17, 0x02, 0x1b, 0xfb, 0x12, 0xc9, 0xc7, 0x0f, 0x53, 0xe4, 0xe2, 0x8f, 0x3b, 0xbf, - 0x5e, 0xc2, 0xdd, 0x5d, 0x81, 0x7b, 0xa1, 0xeb, 0x65, 0x63, 0x7b, 0x70, 0xa3, 0xea, 0xcf, 0xd3, - 0x64, 0xc2, 0x91, 0xee, 0x41, 0x43, 0xce, 0x96, 0x7e, 0xa3, 0x7b, 0x67, 0x9d, 0x30, 0x7d, 0x65, - 0x71, 0xb6, 0x61, 0xa3, 0x8f, 0x31, 0xae, 0xcc, 0xc0, 0xd9, 0x06, 0xc3, 0x8b, 0xb8, 0xa8, 0x64, - 0x26, 0x5c, 0x3d, 0x8e, 0x62, 0x81, 0x19, 0x37, 0x49, 0xbb, 0xde, 0x69, 0xfa, 0xd5, 0xd1, 0xf1, - 0xe0, 0xba, 0x12, 0x96, 0x74, 0x4f, 0x41, 0x57, 0xb3, 0xa5, 0x70, 0x5d, 0xbc, 0xd2, 0xd3, 0xfd, - 0xac, 0x81, 0x2e, 0xbf, 0x70, 0x8a, 0xa0, 0xab, 0xc5, 0xe9, 0xfd, 0x7f, 0xc9, 0xdf, 0x7a, 0xb0, - 0xa6, 0xba, 0xe4, 0x7d, 0x05, 0xba, 0x4a, 0x64, 0xe5, 0x98, 0x0b, 0xc1, 0x59, 0x5b, 0xbf, 0x3d, - 0x82, 0x83, 0xe2, 0xe5, 0xd1, 0x23, 0xb8, 0x52, 0xe4, 0x41, 0xef, 0xae, 0xda, 0xfb, 0x2c, 0x5d, - 0xeb, 0xde, 0x5a, 0x5a, 0x05, 0xdc, 0x3b, 0x5c, 0x9c, 0xda, 0xb5, 0x6f, 0xa7, 0x76, 0xed, 0x63, - 0x6e, 0x93, 0x45, 0x6e, 0x93, 0xaf, 0xb9, 0x4d, 0x7e, 0xe4, 0x36, 0x79, 0xfb, 0xec, 0x3f, 0x7f, - 0x43, 0x4f, 0x54, 0x75, 0x58, 0x1b, 0xe8, 0x72, 0x99, 0x47, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, - 0xad, 0x77, 0xda, 0x73, 0xd1, 0x04, 0x00, 0x00, + 0x14, 0xc6, 0x3b, 0xe9, 0x36, 0x6e, 0x4f, 0x5d, 0x91, 0x61, 0x59, 0x4a, 0xc4, 0xb4, 0x04, 0xc1, + 0xe2, 0x9f, 0x89, 0x5b, 0x6f, 0xd6, 0x5d, 0x11, 0xec, 0x76, 0x41, 0x21, 0x88, 0x04, 0x2f, 0x16, + 0x6f, 0x96, 0x34, 0x3d, 0x1b, 0x83, 0x69, 0x12, 0x33, 0xd3, 0x42, 0xef, 0x7c, 0x04, 0x1f, 0xc1, + 0x87, 0xf0, 0x21, 0x7a, 0xe9, 0xa5, 0x57, 0xab, 0x9b, 0x3b, 0xdf, 0x42, 0x32, 0x93, 0xb0, 0x7f, + 0x44, 0x5b, 0x65, 0xef, 0xce, 0xcc, 0x7c, 0xdf, 0x99, 0xdf, 0xf9, 0xc2, 0x04, 0x86, 0x41, 0x28, + 0xde, 0x4d, 0x47, 0xcc, 0x4f, 0x26, 0xb6, 0x9f, 0xc4, 0xc2, 0x0b, 0x63, 0xcc, 0xc6, 0xe7, 0x4b, + 0x2f, 0x0d, 0x6d, 0x8e, 0xd9, 0x2c, 0xf4, 0x91, 0xdb, 0x11, 0x7a, 0x1c, 0xb9, 0x3d, 0xdb, 0x2e, + 0x2b, 0x96, 0x66, 0x89, 0x48, 0xe8, 0xed, 0x33, 0x3d, 0xab, 0xb4, 0xac, 0x54, 0xcc, 0xb6, 0x8d, + 0xcd, 0x20, 0x09, 0x12, 0xa9, 0xb4, 0x8b, 0x4a, 0x99, 0x8c, 0x5b, 0x41, 0x92, 0x04, 0x11, 0xda, + 0x72, 0x35, 0x9a, 0x1e, 0xdb, 0x38, 0x49, 0xc5, 0xbc, 0x3c, 0xec, 0x5c, 0x3e, 0x14, 0xe1, 0x04, + 0xb9, 0xf0, 0x26, 0xa9, 0x12, 0x58, 0x3f, 0x09, 0x34, 0x9c, 0xe2, 0x06, 0xba, 0x05, 0x5a, 0x38, + 0x6e, 0x93, 0x2e, 0xe9, 0x35, 0x07, 0x7a, 0x7e, 0xd2, 0xd1, 0x5e, 0x0e, 0x5d, 0x2d, 0x1c, 0xd3, + 0x7d, 0x00, 0x3f, 0x43, 0x4f, 0xe0, 0xf8, 0xc8, 0x13, 0x6d, 0xad, 0x4b, 0x7a, 0xad, 0xbe, 0xc1, + 0x54, 0x5f, 0x56, 0xf5, 0x65, 0x6f, 0xaa, 0xbe, 0x83, 0xf5, 0xc5, 0x49, 0xa7, 0xf6, 0xe9, 0x7b, + 0x87, 0xb8, 0xcd, 0xd2, 0xf7, 0x5c, 0xd0, 0x17, 0xa0, 0x47, 0xde, 0x08, 0x23, 0xde, 0xae, 0x77, + 0xeb, 0xbd, 0x56, 0xff, 0x11, 0xfb, 0xeb, 0xa8, 0x4c, 0x22, 0x31, 0x47, 0x5a, 0x0e, 0x62, 0x91, + 0xcd, 0xdd, 0xd2, 0x6f, 0x3c, 0x81, 0xd6, 0xb9, 0x6d, 0x7a, 0x13, 0xea, 0xef, 0x71, 0xae, 0xb0, + 0xdd, 0xa2, 0xa4, 0x9b, 0xd0, 0x98, 0x79, 0xd1, 0x14, 0x25, 0x6a, 0xd3, 0x55, 0x8b, 0x5d, 0x6d, + 0x87, 0x58, 0x5f, 0x08, 0x6c, 0xec, 0x4b, 0x24, 0x17, 0x3f, 0x4c, 0x91, 0x8b, 0x3f, 0xce, 0xfc, + 0xfa, 0x12, 0xee, 0xce, 0x12, 0xdc, 0x0b, 0x5d, 0xaf, 0x1a, 0xdb, 0x81, 0x1b, 0x55, 0x7f, 0x9e, + 0x26, 0x31, 0x47, 0xba, 0x0b, 0x0d, 0x79, 0xb7, 0xf4, 0xb7, 0xfa, 0x77, 0x56, 0x09, 0xd3, 0x55, + 0x16, 0x6b, 0x0f, 0x36, 0x86, 0x18, 0xe1, 0xf2, 0x0c, 0x28, 0xac, 0xf1, 0x79, 0xec, 0x4b, 0x9e, + 0x75, 0x57, 0xd6, 0xd6, 0x5d, 0x68, 0x39, 0x21, 0x17, 0x95, 0xb5, 0x0d, 0xd7, 0x8e, 0xc3, 0x48, + 0x60, 0xc6, 0xdb, 0xa4, 0x5b, 0xef, 0x35, 0xdd, 0x6a, 0x69, 0x39, 0x70, 0x5d, 0x09, 0x4b, 0xe2, + 0xa7, 0xa0, 0x2b, 0x1e, 0x29, 0x5c, 0x15, 0xb9, 0xf4, 0xf4, 0x3f, 0x6b, 0xa0, 0xcb, 0x1d, 0x4e, + 0x11, 0x74, 0x15, 0x06, 0x7d, 0xf0, 0x2f, 0xdf, 0xc4, 0x78, 0xb8, 0xa2, 0xba, 0xe4, 0x7d, 0x05, + 0xba, 0x4a, 0x69, 0xe9, 0x35, 0x17, 0xc2, 0x34, 0xb6, 0x7e, 0x7b, 0x18, 0x07, 0xc5, 0x6b, 0xa4, + 0x47, 0xb0, 0x56, 0xe4, 0x41, 0xef, 0x2d, 0x9b, 0xfb, 0x2c, 0x5d, 0xe3, 0xfe, 0x4a, 0x5a, 0x05, + 0x3c, 0x38, 0x5c, 0x9c, 0x9a, 0xb5, 0x6f, 0xa7, 0x66, 0xed, 0x63, 0x6e, 0x92, 0x45, 0x6e, 0x92, + 0xaf, 0xb9, 0x49, 0x7e, 0xe4, 0x26, 0x79, 0xfb, 0xec, 0x3f, 0x7f, 0x4d, 0x7b, 0xaa, 0x3a, 0xac, + 0x8d, 0x74, 0x39, 0xcc, 0xe3, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x14, 0x74, 0xdd, 0x12, 0xe5, + 0x04, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/api/services/leases/v1/leases.proto b/vendor/github.com/containerd/containerd/api/services/leases/v1/leases.proto index 1002a2d6ed..2df4b06239 100644 --- a/vendor/github.com/containerd/containerd/api/services/leases/v1/leases.proto +++ b/vendor/github.com/containerd/containerd/api/services/leases/v1/leases.proto @@ -47,6 +47,12 @@ message CreateResponse { message DeleteRequest { string id = 1; + + // Sync indicates that the delete and cleanup should be done + // synchronously before returning to the caller + // + // Default is false + bool sync = 2; } message ListRequest { diff --git a/vendor/github.com/containerd/containerd/archive/compression/compression.go b/vendor/github.com/containerd/containerd/archive/compression/compression.go new file mode 100644 index 0000000000..bd50f083b2 --- /dev/null +++ b/vendor/github.com/containerd/containerd/archive/compression/compression.go @@ -0,0 +1,153 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package compression + +import ( + "bufio" + "bytes" + "compress/gzip" + "fmt" + "io" + "sync" +) + +type ( + // Compression is the state represents if compressed or not. + Compression int +) + +const ( + // Uncompressed represents the uncompressed. + Uncompressed Compression = iota + // Gzip is gzip compression algorithm. + Gzip +) + +var ( + bufioReader32KPool = &sync.Pool{ + New: func() interface{} { return bufio.NewReaderSize(nil, 32*1024) }, + } +) + +// DecompressReadCloser include the stream after decompress and the compress method detected. +type DecompressReadCloser interface { + io.ReadCloser + // GetCompression returns the compress method which is used before decompressing + GetCompression() Compression +} + +type readCloserWrapper struct { + io.Reader + compression Compression + closer func() error +} + +func (r *readCloserWrapper) Close() error { + if r.closer != nil { + return r.closer() + } + return nil +} + +func (r *readCloserWrapper) GetCompression() Compression { + return r.compression +} + +type writeCloserWrapper struct { + io.Writer + closer func() error +} + +func (w *writeCloserWrapper) Close() error { + if w.closer != nil { + w.closer() + } + return nil +} + +// DetectCompression detects the compression algorithm of the source. +func DetectCompression(source []byte) Compression { + for compression, m := range map[Compression][]byte{ + Gzip: {0x1F, 0x8B, 0x08}, + } { + if len(source) < len(m) { + // Len too short + continue + } + if bytes.Equal(m, source[:len(m)]) { + return compression + } + } + return Uncompressed +} + +// DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive. +func DecompressStream(archive io.Reader) (DecompressReadCloser, error) { + buf := bufioReader32KPool.Get().(*bufio.Reader) + buf.Reset(archive) + bs, err := buf.Peek(10) + if err != nil && err != io.EOF { + // Note: we'll ignore any io.EOF error because there are some odd + // cases where the layer.tar file will be empty (zero bytes) and + // that results in an io.EOF from the Peek() call. So, in those + // cases we'll just treat it as a non-compressed stream and + // that means just create an empty layer. + // See Issue docker/docker#18170 + return nil, err + } + + closer := func() error { + buf.Reset(nil) + bufioReader32KPool.Put(buf) + return nil + } + switch compression := DetectCompression(bs); compression { + case Uncompressed: + readBufWrapper := &readCloserWrapper{buf, compression, closer} + return readBufWrapper, nil + case Gzip: + gzReader, err := gzip.NewReader(buf) + if err != nil { + return nil, err + } + readBufWrapper := &readCloserWrapper{gzReader, compression, closer} + return readBufWrapper, nil + default: + return nil, fmt.Errorf("unsupported compression format %s", (&compression).Extension()) + } +} + +// CompressStream compresseses the dest with specified compression algorithm. +func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, error) { + switch compression { + case Uncompressed: + return &writeCloserWrapper{dest, nil}, nil + case Gzip: + return gzip.NewWriter(dest), nil + default: + return nil, fmt.Errorf("unsupported compression format %s", (&compression).Extension()) + } +} + +// Extension returns the extension of a file that uses the specified compression algorithm. +func (compression *Compression) Extension() string { + switch *compression { + case Gzip: + return "gz" + } + return "" +} diff --git a/vendor/github.com/containerd/containerd/archive/tar.go b/vendor/github.com/containerd/containerd/archive/tar.go index 7d7702beec..ac04e3e023 100644 --- a/vendor/github.com/containerd/containerd/archive/tar.go +++ b/vendor/github.com/containerd/containerd/archive/tar.go @@ -114,6 +114,9 @@ func Apply(ctx context.Context, root string, r io.Reader, opts ...ApplyOpt) (int return 0, errors.Wrap(err, "failed to apply option") } } + if options.Filter == nil { + options.Filter = all + } return apply(ctx, root, tar.NewReader(r), options) } @@ -155,6 +158,14 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO // Normalize name, for safety and for a simple is-root check hdr.Name = filepath.Clean(hdr.Name) + accept, err := options.Filter(hdr) + if err != nil { + return 0, err + } + if !accept { + continue + } + if skipFile(hdr) { log.G(ctx).Warnf("file %q ignored: archive may not be supported on system", hdr.Name) continue @@ -366,10 +377,11 @@ func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header } case tar.TypeLink: - targetPath, err := fs.RootPath(extractDir, hdr.Linkname) + targetPath, err := hardlinkRootPath(extractDir, hdr.Linkname) if err != nil { return err } + if err := os.Link(targetPath, path); err != nil { return err } @@ -648,3 +660,27 @@ func copyBuffered(ctx context.Context, dst io.Writer, src io.Reader) (written in return written, err } + +// hardlinkRootPath returns target linkname, evaluating and bounding any +// symlink to the parent directory. +// +// NOTE: Allow hardlink to the softlink, not the real one. For example, +// +// touch /tmp/zzz +// ln -s /tmp/zzz /tmp/xxx +// ln /tmp/xxx /tmp/yyy +// +// /tmp/yyy should be softlink which be same of /tmp/xxx, not /tmp/zzz. +func hardlinkRootPath(root, linkname string) (string, error) { + ppath, base := filepath.Split(linkname) + ppath, err := fs.RootPath(root, ppath) + if err != nil { + return "", err + } + + targetPath := filepath.Join(ppath, base) + if !strings.HasPrefix(targetPath, root) { + targetPath = root + } + return targetPath, nil +} diff --git a/vendor/github.com/containerd/containerd/archive/tar_opts.go b/vendor/github.com/containerd/containerd/archive/tar_opts.go index b0f86abdff..a08bc102a7 100644 --- a/vendor/github.com/containerd/containerd/archive/tar_opts.go +++ b/vendor/github.com/containerd/containerd/archive/tar_opts.go @@ -16,5 +16,23 @@ package archive +import "archive/tar" + // ApplyOpt allows setting mutable archive apply properties on creation type ApplyOpt func(options *ApplyOptions) error + +// Filter specific files from the archive +type Filter func(*tar.Header) (bool, error) + +// all allows all files +func all(_ *tar.Header) (bool, error) { + return true, nil +} + +// WithFilter uses the filter to select which files are to be extracted. +func WithFilter(f Filter) ApplyOpt { + return func(options *ApplyOptions) error { + options.Filter = f + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/archive/tar_opts_unix.go b/vendor/github.com/containerd/containerd/archive/tar_opts_unix.go index e19afddd25..1738269679 100644 --- a/vendor/github.com/containerd/containerd/archive/tar_opts_unix.go +++ b/vendor/github.com/containerd/containerd/archive/tar_opts_unix.go @@ -20,4 +20,5 @@ package archive // ApplyOptions provides additional options for an Apply operation type ApplyOptions struct { + Filter Filter // Filter tar headers } diff --git a/vendor/github.com/containerd/containerd/archive/tar_opts_windows.go b/vendor/github.com/containerd/containerd/archive/tar_opts_windows.go index 0991ab0945..e4b15a1634 100644 --- a/vendor/github.com/containerd/containerd/archive/tar_opts_windows.go +++ b/vendor/github.com/containerd/containerd/archive/tar_opts_windows.go @@ -22,6 +22,7 @@ package archive type ApplyOptions struct { ParentLayerPaths []string // Parent layer paths used for Windows layer apply IsWindowsContainerLayer bool // True if the tar stream to be applied is a Windows Container Layer + Filter Filter // Filter tar headers } // WithParentLayers adds parent layers to the apply process this is required diff --git a/vendor/github.com/containerd/containerd/cio/io_windows.go b/vendor/github.com/containerd/containerd/cio/io_windows.go index fa9532a3bd..a751f7d7a0 100644 --- a/vendor/github.com/containerd/containerd/cio/io_windows.go +++ b/vendor/github.com/containerd/containerd/cio/io_windows.go @@ -20,7 +20,6 @@ import ( "fmt" "io" "net" - "sync" winio "github.com/Microsoft/go-winio" "github.com/containerd/containerd/log" @@ -41,7 +40,6 @@ func NewFIFOSetInDir(_, id string, terminal bool) (*FIFOSet, error) { func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { var ( - wg sync.WaitGroup set []io.Closer ) @@ -85,9 +83,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { }(l) set = append(set, l) - wg.Add(1) go func() { - defer wg.Done() c, err := l.Accept() if err != nil { log.L.WithError(err).Errorf("failed to accept stdout connection on %s", fifos.Stdout) @@ -115,9 +111,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { }(l) set = append(set, l) - wg.Add(1) go func() { - defer wg.Done() c, err := l.Accept() if err != nil { log.L.WithError(err).Errorf("failed to accept stderr connection on %s", fifos.Stderr) diff --git a/vendor/github.com/containerd/containerd/client.go b/vendor/github.com/containerd/containerd/client.go index 55c1a36fd8..788a381d69 100644 --- a/vendor/github.com/containerd/containerd/client.go +++ b/vendor/github.com/containerd/containerd/client.go @@ -43,8 +43,11 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/events" "github.com/containerd/containerd/images" + "github.com/containerd/containerd/leases" + leasesproxy "github.com/containerd/containerd/leases/proxy" "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/pkg/dialer" + "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/plugin" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" @@ -79,8 +82,12 @@ func New(address string, opts ...ClientOpt) (*Client, error) { return nil, err } } + rt := fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS) + if copts.defaultRuntime != "" { + rt = copts.defaultRuntime + } c := &Client{ - runtime: fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS), + runtime: rt, } if copts.services != nil { c.services = *copts.services @@ -284,7 +291,31 @@ func defaultRemoteContext() *RemoteContext { } } +// Fetch downloads the provided content into containerd's content store +// and returns a non-platform specific image reference +func (c *Client) Fetch(ctx context.Context, ref string, opts ...RemoteOpt) (images.Image, error) { + fetchCtx := defaultRemoteContext() + for _, o := range opts { + if err := o(c, fetchCtx); err != nil { + return images.Image{}, err + } + } + + if fetchCtx.Unpack { + return images.Image{}, errors.New("unpack on fetch not supported, try pull") + } + + ctx, done, err := c.WithLease(ctx) + if err != nil { + return images.Image{}, err + } + defer done(ctx) + + return c.fetch(ctx, fetchCtx, ref) +} + // Pull downloads the provided content into containerd's content store +// and returns a platform specific image object func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image, error) { pullCtx := defaultRemoteContext() for _, o := range opts { @@ -292,7 +323,12 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image return nil, err } } - store := c.ContentStore() + + if len(pullCtx.Platforms) > 1 { + return nil, errors.New("cannot pull multiplatform image locally, try Fetch") + } else if len(pullCtx.Platforms) == 0 { + pullCtx.Platforms = []string{platforms.Default()} + } ctx, done, err := c.WithLease(ctx) if err != nil { @@ -300,82 +336,92 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image } defer done(ctx) - name, desc, err := pullCtx.Resolver.Resolve(ctx, ref) + img, err := c.fetch(ctx, pullCtx, ref) if err != nil { - return nil, errors.Wrapf(err, "failed to resolve reference %q", ref) + return nil, err } - fetcher, err := pullCtx.Resolver.Fetcher(ctx, name) + i := NewImageWithPlatform(c, img, pullCtx.Platforms[0]) + + if pullCtx.Unpack { + if err := i.Unpack(ctx, pullCtx.Snapshotter); err != nil { + return nil, errors.Wrapf(err, "failed to unpack image on snapshotter %s", pullCtx.Snapshotter) + } + } + + return i, nil +} + +func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string) (images.Image, error) { + store := c.ContentStore() + name, desc, err := rCtx.Resolver.Resolve(ctx, ref) if err != nil { - return nil, errors.Wrapf(err, "failed to get fetcher for %q", name) + return images.Image{}, errors.Wrapf(err, "failed to resolve reference %q", ref) + } + + fetcher, err := rCtx.Resolver.Fetcher(ctx, name) + if err != nil { + return images.Image{}, errors.Wrapf(err, "failed to get fetcher for %q", name) } var ( schema1Converter *schema1.Converter handler images.Handler ) - if desc.MediaType == images.MediaTypeDockerSchema1Manifest && pullCtx.ConvertSchema1 { + if desc.MediaType == images.MediaTypeDockerSchema1Manifest && rCtx.ConvertSchema1 { schema1Converter = schema1.NewConverter(store, fetcher) - handler = images.Handlers(append(pullCtx.BaseHandlers, schema1Converter)...) + handler = images.Handlers(append(rCtx.BaseHandlers, schema1Converter)...) } else { // Get all the children for a descriptor childrenHandler := images.ChildrenHandler(store) // Set any children labels for that content childrenHandler = images.SetChildrenLabels(store, childrenHandler) // Filter children by platforms - childrenHandler = images.FilterPlatforms(childrenHandler, pullCtx.Platforms...) + childrenHandler = images.FilterPlatforms(childrenHandler, rCtx.Platforms...) - handler = images.Handlers(append(pullCtx.BaseHandlers, + handler = images.Handlers(append(rCtx.BaseHandlers, remotes.FetchHandler(store, fetcher), childrenHandler, )...) } if err := images.Dispatch(ctx, handler, desc); err != nil { - return nil, err + return images.Image{}, err } if schema1Converter != nil { desc, err = schema1Converter.Convert(ctx) if err != nil { - return nil, err + return images.Image{}, err } } - img := &image{ - client: c, - i: images.Image{ - Name: name, - Target: desc, - Labels: pullCtx.Labels, - }, - } - - if pullCtx.Unpack { - if err := img.Unpack(ctx, pullCtx.Snapshotter); err != nil { - return nil, errors.Wrapf(err, "failed to unpack image on snapshotter %s", pullCtx.Snapshotter) - } + img := images.Image{ + Name: name, + Target: desc, + Labels: rCtx.Labels, } is := c.ImageService() for { - if created, err := is.Create(ctx, img.i); err != nil { + if created, err := is.Create(ctx, img); err != nil { if !errdefs.IsAlreadyExists(err) { - return nil, err + return images.Image{}, err } - updated, err := is.Update(ctx, img.i) + updated, err := is.Update(ctx, img) if err != nil { // if image was removed, try create again if errdefs.IsNotFound(err) { continue } - return nil, err + return images.Image{}, err } - img.i = updated + img = updated } else { - img.i = created + img = created } + return img, nil } } @@ -403,10 +449,7 @@ func (c *Client) GetImage(ctx context.Context, ref string) (Image, error) { if err != nil { return nil, err } - return &image{ - client: c, - i: i, - }, nil + return NewImage(c, i), nil } // ListImages returns all existing images @@ -417,10 +460,7 @@ func (c *Client) ListImages(ctx context.Context, filters ...string) ([]Image, er } images := make([]Image, len(imgs)) for i, img := range imgs { - images[i] = &image{ - client: c, - i: img, - } + images[i] = NewImage(c, img) } return images, nil } @@ -451,6 +491,8 @@ func (c *Client) NamespaceService() namespaces.Store { if c.namespaceStore != nil { return c.namespaceStore } + c.connMu.Lock() + defer c.connMu.Unlock() return NewNamespaceStoreFromClient(namespacesapi.NewNamespacesClient(c.conn)) } @@ -459,6 +501,8 @@ func (c *Client) ContainerService() containers.Store { if c.containerStore != nil { return c.containerStore } + c.connMu.Lock() + defer c.connMu.Unlock() return NewRemoteContainerStore(containersapi.NewContainersClient(c.conn)) } @@ -467,6 +511,8 @@ func (c *Client) ContentStore() content.Store { if c.contentStore != nil { return c.contentStore } + c.connMu.Lock() + defer c.connMu.Unlock() return contentproxy.NewContentStore(contentapi.NewContentClient(c.conn)) } @@ -475,6 +521,8 @@ func (c *Client) SnapshotService(snapshotterName string) snapshots.Snapshotter { if c.snapshotters != nil { return c.snapshotters[snapshotterName] } + c.connMu.Lock() + defer c.connMu.Unlock() return snproxy.NewSnapshotter(snapshotsapi.NewSnapshotsClient(c.conn), snapshotterName) } @@ -483,6 +531,8 @@ func (c *Client) TaskService() tasks.TasksClient { if c.taskService != nil { return c.taskService } + c.connMu.Lock() + defer c.connMu.Unlock() return tasks.NewTasksClient(c.conn) } @@ -491,6 +541,8 @@ func (c *Client) ImageService() images.Store { if c.imageStore != nil { return c.imageStore } + c.connMu.Lock() + defer c.connMu.Unlock() return NewImageStoreFromClient(imagesapi.NewImagesClient(c.conn)) } @@ -499,24 +551,32 @@ func (c *Client) DiffService() DiffService { if c.diffService != nil { return c.diffService } + c.connMu.Lock() + defer c.connMu.Unlock() return NewDiffServiceFromClient(diffapi.NewDiffClient(c.conn)) } // IntrospectionService returns the underlying Introspection Client func (c *Client) IntrospectionService() introspectionapi.IntrospectionClient { + c.connMu.Lock() + defer c.connMu.Unlock() return introspectionapi.NewIntrospectionClient(c.conn) } // LeasesService returns the underlying Leases Client -func (c *Client) LeasesService() leasesapi.LeasesClient { +func (c *Client) LeasesService() leases.Manager { if c.leasesService != nil { return c.leasesService } - return leasesapi.NewLeasesClient(c.conn) + c.connMu.Lock() + defer c.connMu.Unlock() + return leasesproxy.NewLeaseManager(leasesapi.NewLeasesClient(c.conn)) } // HealthService returns the underlying GRPC HealthClient func (c *Client) HealthService() grpc_health_v1.HealthClient { + c.connMu.Lock() + defer c.connMu.Unlock() return grpc_health_v1.NewHealthClient(c.conn) } @@ -525,11 +585,15 @@ func (c *Client) EventService() EventService { if c.eventService != nil { return c.eventService } + c.connMu.Lock() + defer c.connMu.Unlock() return NewEventServiceFromClient(eventsapi.NewEventsClient(c.conn)) } // VersionService returns the underlying VersionClient func (c *Client) VersionService() versionservice.VersionClient { + c.connMu.Lock() + defer c.connMu.Unlock() return versionservice.NewVersionClient(c.conn) } diff --git a/vendor/github.com/containerd/containerd/client_opts.go b/vendor/github.com/containerd/containerd/client_opts.go index 52f670d75e..6e6198739a 100644 --- a/vendor/github.com/containerd/containerd/client_opts.go +++ b/vendor/github.com/containerd/containerd/client_opts.go @@ -18,14 +18,16 @@ package containerd import ( "github.com/containerd/containerd/images" + "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/remotes" "google.golang.org/grpc" ) type clientOpts struct { - defaultns string - services *services - dialOptions []grpc.DialOption + defaultns string + defaultRuntime string + services *services + dialOptions []grpc.DialOption } // ClientOpt allows callers to set options on the containerd client @@ -42,6 +44,14 @@ func WithDefaultNamespace(ns string) ClientOpt { } } +// WithDefaultRuntime sets the default runtime on the client +func WithDefaultRuntime(rt string) ClientOpt { + return func(c *clientOpts) error { + c.defaultRuntime = rt + return nil + } +} + // WithDialOpts allows grpc.DialOptions to be set on the connection func WithDialOpts(opts []grpc.DialOption) ClientOpt { return func(c *clientOpts) error { @@ -67,6 +77,9 @@ type RemoteOpt func(*Client, *RemoteContext) error // WithPlatform allows the caller to specify a platform to retrieve // content for func WithPlatform(platform string) RemoteOpt { + if platform == "" { + platform = platforms.Default() + } return func(_ *Client, c *RemoteContext) error { for _, p := range c.Platforms { if p == platform { diff --git a/vendor/github.com/containerd/containerd/container.go b/vendor/github.com/containerd/containerd/container.go index 23f6d4db61..3c09b2dbc6 100644 --- a/vendor/github.com/containerd/containerd/container.go +++ b/vendor/github.com/containerd/containerd/container.go @@ -173,10 +173,7 @@ func (c *container) Image(ctx context.Context) (Image, error) { if err != nil { return nil, errors.Wrapf(err, "failed to get image %s for container", r.Image) } - return &image{ - client: c.client, - i: i, - }, nil + return NewImage(c.client, i), nil } func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...NewTaskOpts) (_ Task, err error) { diff --git a/vendor/github.com/containerd/containerd/container_opts.go b/vendor/github.com/containerd/containerd/container_opts.go index df12cafd5f..580715feeb 100644 --- a/vendor/github.com/containerd/containerd/container_opts.go +++ b/vendor/github.com/containerd/containerd/container_opts.go @@ -197,11 +197,10 @@ func WithNewSpec(opts ...oci.SpecOpts) NewContainerOpts { // WithSpec sets the provided spec on the container func WithSpec(s *oci.Spec, opts ...oci.SpecOpts) NewContainerOpts { return func(ctx context.Context, client *Client, c *containers.Container) error { - for _, o := range opts { - if err := o(ctx, client, c, s); err != nil { - return err - } + if err := oci.ApplyOpts(ctx, client, c, s, opts...); err != nil { + return err } + var err error c.Spec, err = typeurl.MarshalAny(s) return err diff --git a/vendor/github.com/containerd/containerd/containers/containers.go b/vendor/github.com/containerd/containerd/containers/containers.go index c624164e80..e6a562730e 100644 --- a/vendor/github.com/containerd/containerd/containers/containers.go +++ b/vendor/github.com/containerd/containerd/containers/containers.go @@ -40,7 +40,7 @@ type Container struct { // Image specifies the image reference used for a container. // - // This property is optional but immutable. + // This property is optional and mutable. Image string // Runtime specifies which runtime should be used when launching container @@ -60,7 +60,7 @@ type Container struct { // look up the mounts from the snapshot service and include those on the // task create request. // - // This field is not required but immutable. + // This field is not required but mutable. SnapshotKey string // Snapshotter specifies the snapshotter name used for rootfs diff --git a/vendor/github.com/containerd/containerd/containerstore.go b/vendor/github.com/containerd/containerd/containerstore.go index ee3d8c7278..2756e2a68b 100644 --- a/vendor/github.com/containerd/containerd/containerstore.go +++ b/vendor/github.com/containerd/containerd/containerstore.go @@ -18,11 +18,15 @@ package containerd import ( "context" + "errors" + "io" containersapi "github.com/containerd/containerd/api/services/containers/v1" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" ptypes "github.com/gogo/protobuf/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) type remoteContainers struct { @@ -50,15 +54,56 @@ func (r *remoteContainers) Get(ctx context.Context, id string) (containers.Conta } func (r *remoteContainers) List(ctx context.Context, filters ...string) ([]containers.Container, error) { + containers, err := r.stream(ctx, filters...) + if err != nil { + if err == errStreamNotAvailable { + return r.list(ctx, filters...) + } + return nil, err + } + return containers, nil +} + +func (r *remoteContainers) list(ctx context.Context, filters ...string) ([]containers.Container, error) { resp, err := r.client.List(ctx, &containersapi.ListContainersRequest{ Filters: filters, }) if err != nil { return nil, errdefs.FromGRPC(err) } - return containersFromProto(resp.Containers), nil +} +var errStreamNotAvailable = errors.New("streaming api not available") + +func (r *remoteContainers) stream(ctx context.Context, filters ...string) ([]containers.Container, error) { + session, err := r.client.ListStream(ctx, &containersapi.ListContainersRequest{ + Filters: filters, + }) + if err != nil { + return nil, errdefs.FromGRPC(err) + } + var containers []containers.Container + for { + c, err := session.Recv() + if err != nil { + if err == io.EOF { + return containers, nil + } + if s, ok := status.FromError(err); ok { + if s.Code() == codes.Unimplemented { + return nil, errStreamNotAvailable + } + } + return nil, errdefs.FromGRPC(err) + } + select { + case <-ctx.Done(): + return containers, ctx.Err() + default: + containers = append(containers, containerFromProto(c.Container)) + } + } } func (r *remoteContainers) Create(ctx context.Context, container containers.Container) (containers.Container, error) { diff --git a/vendor/github.com/containerd/containerd/content/local/store.go b/vendor/github.com/containerd/containerd/content/local/store.go index 11dfd61a3b..6df3df6184 100644 --- a/vendor/github.com/containerd/containerd/content/local/store.go +++ b/vendor/github.com/containerd/containerd/content/local/store.go @@ -322,6 +322,40 @@ func (s *store) ListStatuses(ctx context.Context, fs ...string) ([]content.Statu return active, nil } +// WalkStatusRefs is used to walk all status references +// Failed status reads will be logged and ignored, if +// this function is called while references are being altered, +// these error messages may be produced. +func (s *store) WalkStatusRefs(ctx context.Context, fn func(string) error) error { + fp, err := os.Open(filepath.Join(s.root, "ingest")) + if err != nil { + return err + } + + defer fp.Close() + + fis, err := fp.Readdir(-1) + if err != nil { + return err + } + + for _, fi := range fis { + rf := filepath.Join(s.root, "ingest", fi.Name(), "ref") + + ref, err := readFileString(rf) + if err != nil { + log.G(ctx).WithError(err).WithField("path", rf).Error("failed to read ingest ref") + continue + } + + if err := fn(ref); err != nil { + return err + } + } + + return nil +} + // status works like stat above except uses the path to the ingest. func (s *store) status(ingestPath string) (content.Status, error) { dp := filepath.Join(ingestPath, "data") diff --git a/vendor/github.com/containerd/containerd/image.go b/vendor/github.com/containerd/containerd/image.go index 0f2bb0da9d..6e286fcafa 100644 --- a/vendor/github.com/containerd/containerd/image.go +++ b/vendor/github.com/containerd/containerd/image.go @@ -56,15 +56,26 @@ var _ = (Image)(&image{}) // NewImage returns a client image object from the metadata image func NewImage(client *Client, i images.Image) Image { return &image{ - client: client, - i: i, + client: client, + i: i, + platform: platforms.Default(), + } +} + +// NewImageWithPlatform returns a client image object from the metadata image +func NewImageWithPlatform(client *Client, i images.Image, platform string) Image { + return &image{ + client: client, + i: i, + platform: platform, } } type image struct { client *Client - i images.Image + i images.Image + platform string } func (i *image) Name() string { @@ -77,24 +88,24 @@ func (i *image) Target() ocispec.Descriptor { func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) { provider := i.client.ContentStore() - return i.i.RootFS(ctx, provider, platforms.Default()) + return i.i.RootFS(ctx, provider, i.platform) } func (i *image) Size(ctx context.Context) (int64, error) { provider := i.client.ContentStore() - return i.i.Size(ctx, provider, platforms.Default()) + return i.i.Size(ctx, provider, i.platform) } func (i *image) Config(ctx context.Context) (ocispec.Descriptor, error) { provider := i.client.ContentStore() - return i.i.Config(ctx, provider, platforms.Default()) + return i.i.Config(ctx, provider, i.platform) } func (i *image) IsUnpacked(ctx context.Context, snapshotterName string) (bool, error) { sn := i.client.SnapshotService(snapshotterName) cs := i.client.ContentStore() - diffs, err := i.i.RootFS(ctx, cs, platforms.Default()) + diffs, err := i.i.RootFS(ctx, cs, i.platform) if err != nil { return false, err } @@ -117,7 +128,7 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string) error { } defer done(ctx) - layers, err := i.getLayers(ctx, platforms.Default()) + layers, err := i.getLayers(ctx, i.platform) if err != nil { return err } @@ -154,7 +165,7 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string) error { } if unpacked { - desc, err := i.i.Config(ctx, cs, platforms.Default()) + desc, err := i.i.Config(ctx, cs, i.platform) if err != nil { return err } diff --git a/vendor/github.com/containerd/containerd/import.go b/vendor/github.com/containerd/containerd/import.go index 3148d240b9..e4ac00cee3 100644 --- a/vendor/github.com/containerd/containerd/import.go +++ b/vendor/github.com/containerd/containerd/import.go @@ -80,10 +80,7 @@ func (c *Client) Import(ctx context.Context, importer images.Importer, reader io imgrec = updated } - images = append(images, &image{ - client: c, - i: imgrec, - }) + images = append(images, NewImage(c, imgrec)) } return images, nil } diff --git a/vendor/github.com/containerd/containerd/install.go b/vendor/github.com/containerd/containerd/install.go new file mode 100644 index 0000000000..2aa8b03946 --- /dev/null +++ b/vendor/github.com/containerd/containerd/install.go @@ -0,0 +1,91 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package containerd + +import ( + "archive/tar" + "context" + "os" + "path/filepath" + + introspectionapi "github.com/containerd/containerd/api/services/introspection/v1" + "github.com/containerd/containerd/archive" + "github.com/containerd/containerd/archive/compression" + "github.com/containerd/containerd/content" + "github.com/containerd/containerd/images" + "github.com/containerd/containerd/platforms" + "github.com/pkg/errors" +) + +// Install a binary image into the opt service +func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts) error { + resp, err := c.IntrospectionService().Plugins(ctx, &introspectionapi.PluginsRequest{ + Filters: []string{ + "id==opt", + }, + }) + if err != nil { + return err + } + if len(resp.Plugins) != 1 { + return errors.New("opt service not enabled") + } + path := resp.Plugins[0].Exports["path"] + if path == "" { + return errors.New("opt path not exported") + } + var config InstallConfig + for _, o := range opts { + o(&config) + } + var ( + cs = image.ContentStore() + platform = platforms.Default() + ) + manifest, err := images.Manifest(ctx, cs, image.Target(), platform) + if err != nil { + return err + } + for _, layer := range manifest.Layers { + ra, err := cs.ReaderAt(ctx, layer) + if err != nil { + return err + } + cr := content.NewReader(ra) + r, err := compression.DecompressStream(cr) + if err != nil { + return err + } + defer r.Close() + if _, err := archive.Apply(ctx, path, r, archive.WithFilter(func(hdr *tar.Header) (bool, error) { + d := filepath.Dir(hdr.Name) + result := d == "bin" + if config.Libs { + result = result || d == "lib" + } + if result && !config.Replace { + if _, err := os.Lstat(filepath.Join(path, hdr.Name)); err == nil { + return false, errors.Errorf("cannot replace %s in %s", hdr.Name, path) + } + } + return result, nil + })); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/containerd/containerd/install_opts.go b/vendor/github.com/containerd/containerd/install_opts.go new file mode 100644 index 0000000000..b11e7f3d6d --- /dev/null +++ b/vendor/github.com/containerd/containerd/install_opts.go @@ -0,0 +1,38 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package containerd + +// InstallOpts configures binary installs +type InstallOpts func(*InstallConfig) + +// InstallConfig sets the binary install configuration +type InstallConfig struct { + // Libs installs libs from the image + Libs bool + // Replace will overwrite existing binaries or libs in the opt directory + Replace bool +} + +// WithInstallLibs installs libs from the image +func WithInstallLibs(c *InstallConfig) { + c.Libs = true +} + +// WithInstallReplace will replace existing files +func WithInstallReplace(c *InstallConfig) { + c.Replace = true +} diff --git a/vendor/github.com/containerd/containerd/lease.go b/vendor/github.com/containerd/containerd/lease.go index 8cf3e5879d..d46b79d9f1 100644 --- a/vendor/github.com/containerd/containerd/lease.go +++ b/vendor/github.com/containerd/containerd/lease.go @@ -20,89 +20,27 @@ import ( "context" "time" - leasesapi "github.com/containerd/containerd/api/services/leases/v1" "github.com/containerd/containerd/leases" ) -// Lease is used to hold a reference to active resources which have not been -// referenced by a root resource. This is useful for preventing garbage -// collection of resources while they are actively being updated. -type Lease struct { - id string - createdAt time.Time - - client *Client -} - -// CreateLease creates a new lease -func (c *Client) CreateLease(ctx context.Context) (Lease, error) { - lapi := c.LeasesService() - resp, err := lapi.Create(ctx, &leasesapi.CreateRequest{}) - if err != nil { - return Lease{}, err - } - - return Lease{ - id: resp.Lease.ID, - client: c, - }, nil -} - -// ListLeases lists active leases -func (c *Client) ListLeases(ctx context.Context) ([]Lease, error) { - lapi := c.LeasesService() - resp, err := lapi.List(ctx, &leasesapi.ListRequest{}) - if err != nil { - return nil, err - } - leases := make([]Lease, len(resp.Leases)) - for i := range resp.Leases { - leases[i] = Lease{ - id: resp.Leases[i].ID, - createdAt: resp.Leases[i].CreatedAt, - client: c, - } - } - - return leases, nil -} - // WithLease attaches a lease on the context func (c *Client) WithLease(ctx context.Context) (context.Context, func(context.Context) error, error) { - _, ok := leases.Lease(ctx) + _, ok := leases.FromContext(ctx) if ok { return ctx, func(context.Context) error { return nil }, nil } - l, err := c.CreateLease(ctx) + ls := c.LeasesService() + + l, err := ls.Create(ctx, leases.WithRandomID(), leases.WithExpiration(24*time.Hour)) if err != nil { return nil, nil, err } - ctx = leases.WithLease(ctx, l.ID()) + ctx = leases.WithLease(ctx, l.ID) return ctx, func(ctx context.Context) error { - return l.Delete(ctx) + return ls.Delete(ctx, l) }, nil } - -// ID returns the lease ID -func (l Lease) ID() string { - return l.id -} - -// CreatedAt returns the time at which the lease was created -func (l Lease) CreatedAt() time.Time { - return l.createdAt -} - -// Delete deletes the lease, removing the reference to all resources created -// during the lease. -func (l Lease) Delete(ctx context.Context) error { - lapi := l.client.LeasesService() - _, err := lapi.Delete(ctx, &leasesapi.DeleteRequest{ - ID: l.id, - }) - return err -} diff --git a/vendor/github.com/containerd/containerd/leases/context.go b/vendor/github.com/containerd/containerd/leases/context.go index b66b154ce4..599c549d31 100644 --- a/vendor/github.com/containerd/containerd/leases/context.go +++ b/vendor/github.com/containerd/containerd/leases/context.go @@ -29,8 +29,8 @@ func WithLease(ctx context.Context, lid string) context.Context { return withGRPCLeaseHeader(ctx, lid) } -// Lease returns the lease from the context. -func Lease(ctx context.Context) (string, bool) { +// FromContext returns the lease from the context. +func FromContext(ctx context.Context) (string, bool) { lid, ok := ctx.Value(leaseKey{}).(string) if !ok { return fromGRPCHeader(ctx) diff --git a/vendor/github.com/containerd/containerd/leases/id.go b/vendor/github.com/containerd/containerd/leases/id.go new file mode 100644 index 0000000000..8781a1d72a --- /dev/null +++ b/vendor/github.com/containerd/containerd/leases/id.go @@ -0,0 +1,43 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package leases + +import ( + "encoding/base64" + "fmt" + "math/rand" + "time" +) + +// WithRandomID sets the lease ID to a random unique value +func WithRandomID() Opt { + return func(l *Lease) error { + t := time.Now() + var b [3]byte + rand.Read(b[:]) + l.ID = fmt.Sprintf("%d-%s", t.Nanosecond(), base64.URLEncoding.EncodeToString(b[:])) + return nil + } +} + +// WithID sets the ID for the lease +func WithID(id string) Opt { + return func(l *Lease) error { + l.ID = id + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/leases/lease.go b/vendor/github.com/containerd/containerd/leases/lease.go new file mode 100644 index 0000000000..909b4ea0bb --- /dev/null +++ b/vendor/github.com/containerd/containerd/leases/lease.go @@ -0,0 +1,76 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package leases + +import ( + "context" + "time" +) + +// Opt is used to set options on a lease +type Opt func(*Lease) error + +// DeleteOpt allows configuring a delete operation +type DeleteOpt func(context.Context, *DeleteOptions) error + +// Manager is used to create, list, and remove leases +type Manager interface { + Create(context.Context, ...Opt) (Lease, error) + Delete(context.Context, Lease, ...DeleteOpt) error + List(context.Context, ...string) ([]Lease, error) +} + +// Lease retains resources to prevent cleanup before +// the resources can be fully referenced. +type Lease struct { + ID string + CreatedAt time.Time + Labels map[string]string +} + +// DeleteOptions provide options on image delete +type DeleteOptions struct { + Synchronous bool +} + +// SynchronousDelete is used to indicate that a lease deletion and removal of +// any unreferenced resources should occur synchronously before returning the +// result. +func SynchronousDelete(ctx context.Context, o *DeleteOptions) error { + o.Synchronous = true + return nil +} + +// WithLabels sets labels on a lease +func WithLabels(labels map[string]string) Opt { + return func(l *Lease) error { + l.Labels = labels + return nil + } +} + +// WithExpiration sets an expiration on the lease +func WithExpiration(d time.Duration) Opt { + return func(l *Lease) error { + if l.Labels == nil { + l.Labels = map[string]string{} + } + l.Labels["containerd.io/gc.expire"] = time.Now().Add(d).Format(time.RFC3339) + + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/leases/proxy/manager.go b/vendor/github.com/containerd/containerd/leases/proxy/manager.go new file mode 100644 index 0000000000..30afe5368e --- /dev/null +++ b/vendor/github.com/containerd/containerd/leases/proxy/manager.go @@ -0,0 +1,93 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package proxy + +import ( + "context" + + leasesapi "github.com/containerd/containerd/api/services/leases/v1" + "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/leases" +) + +type proxyManager struct { + client leasesapi.LeasesClient +} + +// NewLeaseManager returns a lease manager which communicates +// through a grpc lease service. +func NewLeaseManager(client leasesapi.LeasesClient) leases.Manager { + return &proxyManager{ + client: client, + } +} + +func (pm *proxyManager) Create(ctx context.Context, opts ...leases.Opt) (leases.Lease, error) { + l := leases.Lease{} + for _, opt := range opts { + if err := opt(&l); err != nil { + return leases.Lease{}, err + } + } + resp, err := pm.client.Create(ctx, &leasesapi.CreateRequest{ + ID: l.ID, + Labels: l.Labels, + }) + if err != nil { + return leases.Lease{}, errdefs.FromGRPC(err) + } + + return leases.Lease{ + ID: resp.Lease.ID, + CreatedAt: resp.Lease.CreatedAt, + Labels: resp.Lease.Labels, + }, nil +} + +func (pm *proxyManager) Delete(ctx context.Context, l leases.Lease, opts ...leases.DeleteOpt) error { + var do leases.DeleteOptions + for _, opt := range opts { + if err := opt(ctx, &do); err != nil { + return err + } + } + + _, err := pm.client.Delete(ctx, &leasesapi.DeleteRequest{ + ID: l.ID, + Sync: do.Synchronous, + }) + return errdefs.FromGRPC(err) +} + +func (pm *proxyManager) List(ctx context.Context, filters ...string) ([]leases.Lease, error) { + resp, err := pm.client.List(ctx, &leasesapi.ListRequest{ + Filters: filters, + }) + if err != nil { + return nil, errdefs.FromGRPC(err) + } + l := make([]leases.Lease, len(resp.Leases)) + for i := range resp.Leases { + l[i] = leases.Lease{ + ID: resp.Leases[i].ID, + CreatedAt: resp.Leases[i].CreatedAt, + Labels: resp.Leases[i].Labels, + } + } + + return l, nil +} diff --git a/vendor/github.com/containerd/containerd/log/context.go b/vendor/github.com/containerd/containerd/log/context.go index f40603b17b..3fab96b858 100644 --- a/vendor/github.com/containerd/containerd/log/context.go +++ b/vendor/github.com/containerd/containerd/log/context.go @@ -42,6 +42,10 @@ type ( // and is usually used to trace detailed behavior of the program. const TraceLevel = logrus.Level(uint32(logrus.DebugLevel + 1)) +// RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to +// ensure the formatted time is always the same number of characters. +const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00" + // ParseLevel takes a string level and returns the Logrus log level constant. // It supports trace level. func ParseLevel(lvl string) (logrus.Level, error) { diff --git a/vendor/github.com/containerd/containerd/metadata/adaptors.go b/vendor/github.com/containerd/containerd/metadata/adaptors.go index 8145f9acee..38539fdc12 100644 --- a/vendor/github.com/containerd/containerd/metadata/adaptors.go +++ b/vendor/github.com/containerd/containerd/metadata/adaptors.go @@ -23,6 +23,7 @@ import ( "github.com/containerd/containerd/content" "github.com/containerd/containerd/filters" "github.com/containerd/containerd/images" + "github.com/containerd/containerd/leases" ) func adaptImage(o interface{}) filters.Adaptor { @@ -119,6 +120,23 @@ func adaptContentStatus(status content.Status) filters.Adaptor { }) } +func adaptLease(lease leases.Lease) filters.Adaptor { + return filters.AdapterFunc(func(fieldpath []string) (string, bool) { + if len(fieldpath) == 0 { + return "", false + } + + switch fieldpath[0] { + case "id": + return lease.ID, len(lease.ID) > 0 + case "labels": + return checkMap(fieldpath[1:], lease.Labels) + } + + return "", false + }) +} + func checkMap(fieldpath []string, m map[string]string) (string, bool) { if len(m) == 0 { return "", false diff --git a/vendor/github.com/containerd/containerd/metadata/buckets.go b/vendor/github.com/containerd/containerd/metadata/buckets.go index a82c32fd00..fcf4c29597 100644 --- a/vendor/github.com/containerd/containerd/metadata/buckets.go +++ b/vendor/github.com/containerd/containerd/metadata/buckets.go @@ -72,6 +72,7 @@ var ( bucketKeyCreatedAt = []byte("createdat") bucketKeyExpected = []byte("expected") bucketKeyRef = []byte("ref") + bucketKeyExpireAt = []byte("expireat") deprecatedBucketKeyObjectIngest = []byte("ingest") // stores ingest links, deprecated in v1.2 ) diff --git a/vendor/github.com/containerd/containerd/metadata/content.go b/vendor/github.com/containerd/containerd/metadata/content.go index b8f0ae15d1..7293f1bfae 100644 --- a/vendor/github.com/containerd/containerd/metadata/content.go +++ b/vendor/github.com/containerd/containerd/metadata/content.go @@ -328,6 +328,10 @@ func (cs *contentStore) Abort(ctx context.Context, ref string) error { return err } + if err := removeIngestLease(ctx, tx, ref); err != nil { + return err + } + // if not shared content, delete active ingest on backend if expected == "" { return cs.Store.Abort(ctx, bref) @@ -395,6 +399,11 @@ func (cs *contentStore) Writer(ctx context.Context, opts ...content.WriterOpt) ( return err } + leased, err := addIngestLease(ctx, tx, wOpts.Ref) + if err != nil { + return err + } + brefb := bkt.Get(bucketKeyRef) if brefb == nil { sid, err := bkt.NextSequence() @@ -409,6 +418,18 @@ func (cs *contentStore) Writer(ctx context.Context, opts ...content.WriterOpt) ( } else { bref = string(brefb) } + if !leased { + // Add timestamp to allow aborting once stale + // When lease is set the ingest should be aborted + // after lease it belonged to is deleted. + // Expiration can be configurable in the future to + // give more control to the daemon, however leases + // already give users more control of expiration. + expireAt := time.Now().UTC().Add(24 * time.Hour) + if err := writeExpireAt(expireAt, bkt); err != nil { + return err + } + } if shared { if err := bkt.Put(bucketKeyExpected, []byte(wOpts.Desc.Digest)); err != nil { @@ -543,6 +564,9 @@ func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected dig if err != nil { return err } + if err := removeIngestLease(ctx, tx, nw.ref); err != nil { + return err + } return addContentLease(ctx, tx, dgst) }) } @@ -697,6 +721,30 @@ func writeInfo(info *content.Info, bkt *bolt.Bucket) error { return bkt.Put(bucketKeySize, sizeEncoded) } +func readExpireAt(bkt *bolt.Bucket) (*time.Time, error) { + v := bkt.Get(bucketKeyExpireAt) + if v == nil { + return nil, nil + } + t := &time.Time{} + if err := t.UnmarshalBinary(v); err != nil { + return nil, err + } + return t, nil +} + +func writeExpireAt(expire time.Time, bkt *bolt.Bucket) error { + expireAt, err := expire.MarshalBinary() + if err != nil { + return err + } + if err := bkt.Put(bucketKeyExpireAt, expireAt); err != nil { + return err + } + + return nil +} + func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, err error) { cs.l.Lock() t1 := time.Now() @@ -707,7 +755,8 @@ func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, er cs.l.Unlock() }() - seen := map[string]struct{}{} + contentSeen := map[string]struct{}{} + ingestSeen := map[string]struct{}{} if err := cs.db.View(func(tx *bolt.Tx) error { v1bkt := tx.Bucket(bucketKeyVersion) if v1bkt == nil { @@ -730,7 +779,7 @@ func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, er if bbkt != nil { if err := bbkt.ForEach(func(ck, cv []byte) error { if cv == nil { - seen[string(ck)] = struct{}{} + contentSeen[string(ck)] = struct{}{} } return nil }); err != nil { @@ -742,9 +791,17 @@ func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, er if ibkt != nil { if err := ibkt.ForEach(func(ref, v []byte) error { if v == nil { - expected := ibkt.Bucket(ref).Get(bucketKeyExpected) + bkt := ibkt.Bucket(ref) + // expected here may be from a different namespace + // so much be explicitly retained from the ingest + // in case it was removed from the other namespace + expected := bkt.Get(bucketKeyExpected) if len(expected) > 0 { - seen[string(expected)] = struct{}{} + contentSeen[string(expected)] = struct{}{} + } + bref := bkt.Get(bucketKeyRef) + if len(bref) > 0 { + ingestSeen[string(bref)] = struct{}{} } } return nil @@ -760,7 +817,7 @@ func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, er } err = cs.Store.Walk(ctx, func(info content.Info) error { - if _, ok := seen[info.Digest.String()]; !ok { + if _, ok := contentSeen[info.Digest.String()]; !ok { if err := cs.Store.Delete(ctx, info.Digest); err != nil { return err } @@ -768,5 +825,40 @@ func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, er } return nil }) + if err != nil { + return + } + + // If the content store has implemented a more efficient walk function + // then use that else fallback to reading all statuses which may + // cause reading of unneeded metadata. + type statusWalker interface { + WalkStatusRefs(context.Context, func(string) error) error + } + if w, ok := cs.Store.(statusWalker); ok { + err = w.WalkStatusRefs(ctx, func(ref string) error { + if _, ok := ingestSeen[ref]; !ok { + if err := cs.Store.Abort(ctx, ref); err != nil { + return err + } + log.G(ctx).WithField("ref", ref).Debug("cleanup aborting ingest") + } + return nil + }) + } else { + var statuses []content.Status + statuses, err = cs.Store.ListStatuses(ctx) + if err != nil { + return 0, err + } + for _, status := range statuses { + if _, ok := ingestSeen[status.Ref]; !ok { + if err = cs.Store.Abort(ctx, status.Ref); err != nil { + return + } + log.G(ctx).WithField("ref", status.Ref).Debug("cleanup aborting ingest") + } + } + } return } diff --git a/vendor/github.com/containerd/containerd/metadata/db.go b/vendor/github.com/containerd/containerd/metadata/db.go index 4398fc20f5..0ea8ad78ff 100644 --- a/vendor/github.com/containerd/containerd/metadata/db.go +++ b/vendor/github.com/containerd/containerd/metadata/db.go @@ -275,7 +275,7 @@ func (m *DB) GarbageCollect(ctx context.Context) (gc.Stats, error) { if idx := strings.IndexRune(n.Key, '/'); idx > 0 { m.dirtySS[n.Key[:idx]] = struct{}{} } - } else if n.Type == ResourceContent { + } else if n.Type == ResourceContent || n.Type == ResourceIngest { m.dirtyCS = true } return remove(ctx, tx, n) diff --git a/vendor/github.com/containerd/containerd/metadata/gc.go b/vendor/github.com/containerd/containerd/metadata/gc.go index ab75e36fb5..eb4d0c7c33 100644 --- a/vendor/github.com/containerd/containerd/metadata/gc.go +++ b/vendor/github.com/containerd/containerd/metadata/gc.go @@ -21,6 +21,7 @@ import ( "context" "fmt" "strings" + "time" "github.com/boltdb/bolt" "github.com/containerd/containerd/gc" @@ -39,12 +40,17 @@ const ( ResourceContainer // ResourceTask specifies a task resource ResourceTask + // ResourceLease specifies a lease + ResourceLease + // ResourceIngest specifies a content ingest + ResourceIngest ) var ( labelGCRoot = []byte("containerd.io/gc.root") labelGCSnapRef = []byte("containerd.io/gc.ref.snapshot.") labelGCContentRef = []byte("containerd.io/gc.ref.content") + labelGCExpire = []byte("containerd.io/gc.expire") ) func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error { @@ -53,6 +59,8 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error { return nil } + expThreshold := time.Now() + // iterate through each namespace v1c := v1bkt.Cursor() @@ -71,6 +79,30 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error { } libkt := lbkt.Bucket(k) + if lblbkt := libkt.Bucket(bucketKeyObjectLabels); lblbkt != nil { + if expV := lblbkt.Get(labelGCExpire); expV != nil { + exp, err := time.Parse(time.RFC3339, string(expV)) + if err != nil { + // label not used, log and continue to use lease + log.G(ctx).WithError(err).WithField("lease", string(k)).Infof("ignoring invalid expiration value %q", string(expV)) + } else if expThreshold.After(exp) { + // lease has expired, skip + return nil + } + } + } + + select { + case nc <- gcnode(ResourceLease, ns, string(k)): + case <-ctx.Done(): + return ctx.Err() + } + + // Emit content and snapshots as roots instead of implementing + // in references. Since leases cannot be referenced there is + // no need to allow the lookup to be recursive, handling here + // therefore reduces the number of database seeks. + cbkt := libkt.Bucket(bucketKeyObjectContent) if cbkt != nil { if err := cbkt.ForEach(func(k, v []byte) error { @@ -106,6 +138,20 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error { } } + ibkt := libkt.Bucket(bucketKeyObjectIngests) + if ibkt != nil { + if err := ibkt.ForEach(func(k, v []byte) error { + select { + case nc <- gcnode(ResourceIngest, ns, string(k)): + case <-ctx.Done(): + return ctx.Err() + } + return nil + }); err != nil { + return err + } + } + return nil }); err != nil { return err @@ -141,16 +187,39 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error { cbkt := nbkt.Bucket(bucketKeyObjectContent) if cbkt != nil { - cbkt = cbkt.Bucket(bucketKeyObjectBlob) - } - if cbkt != nil { - if err := cbkt.ForEach(func(k, v []byte) error { - if v != nil { + ibkt := cbkt.Bucket(bucketKeyObjectIngests) + if ibkt != nil { + if err := ibkt.ForEach(func(k, v []byte) error { + if v != nil { + return nil + } + ea, err := readExpireAt(ibkt.Bucket(k)) + if err != nil { + return err + } + if ea == nil || expThreshold.After(*ea) { + return nil + } + select { + case nc <- gcnode(ResourceIngest, ns, string(k)): + case <-ctx.Done(): + return ctx.Err() + } return nil + }); err != nil { + return err + } + } + cbkt = cbkt.Bucket(bucketKeyObjectBlob) + if cbkt != nil { + if err := cbkt.ForEach(func(k, v []byte) error { + if v != nil { + return nil + } + return sendRootRef(ctx, nc, gcnode(ResourceContent, ns, string(k)), cbkt.Bucket(k)) + }); err != nil { + return err } - return sendRootRef(ctx, nc, gcnode(ResourceContent, ns, string(k)), cbkt.Bucket(k)) - }); err != nil { - return err } } @@ -240,6 +309,19 @@ func references(ctx context.Context, tx *bolt.Tx, node gc.Node, fn func(gc.Node) } return sendSnapshotRefs(node.Namespace, bkt, fn) + } else if node.Type == ResourceIngest { + // Send expected value + bkt := getBucket(tx, bucketKeyVersion, []byte(node.Namespace), bucketKeyObjectContent, bucketKeyObjectIngests, []byte(node.Key)) + if bkt == nil { + // Node may be created from dead edge + return nil + } + // Load expected + expected := bkt.Get(bucketKeyExpected) + if len(expected) > 0 { + fn(gcnode(ResourceContent, node.Namespace, string(expected))) + } + return nil } return nil @@ -261,6 +343,18 @@ func scanAll(ctx context.Context, tx *bolt.Tx, fn func(ctx context.Context, n gc nbkt := v1bkt.Bucket(k) ns := string(k) + lbkt := nbkt.Bucket(bucketKeyObjectLeases) + if lbkt != nil { + if err := lbkt.ForEach(func(k, v []byte) error { + if v != nil { + return nil + } + return fn(ctx, gcnode(ResourceLease, ns, string(k))) + }); err != nil { + return err + } + } + sbkt := nbkt.Bucket(bucketKeyObjectSnapshots) if sbkt != nil { if err := sbkt.ForEach(func(sk, sv []byte) error { @@ -282,17 +376,30 @@ func scanAll(ctx context.Context, tx *bolt.Tx, fn func(ctx context.Context, n gc cbkt := nbkt.Bucket(bucketKeyObjectContent) if cbkt != nil { - cbkt = cbkt.Bucket(bucketKeyObjectBlob) - } - if cbkt != nil { - if err := cbkt.ForEach(func(k, v []byte) error { - if v != nil { - return nil + ibkt := cbkt.Bucket(bucketKeyObjectIngests) + if ibkt != nil { + if err := ibkt.ForEach(func(k, v []byte) error { + if v != nil { + return nil + } + node := gcnode(ResourceIngest, ns, string(k)) + return fn(ctx, node) + }); err != nil { + return err + } + } + + cbkt = cbkt.Bucket(bucketKeyObjectBlob) + if cbkt != nil { + if err := cbkt.ForEach(func(k, v []byte) error { + if v != nil { + return nil + } + node := gcnode(ResourceContent, ns, string(k)) + return fn(ctx, node) + }); err != nil { + return err } - node := gcnode(ResourceContent, ns, string(k)) - return fn(ctx, node) - }); err != nil { - return err } } } @@ -334,6 +441,20 @@ func remove(ctx context.Context, tx *bolt.Tx, node gc.Node) error { return ssbkt.DeleteBucket([]byte(parts[1])) } } + case ResourceLease: + lbkt := nsbkt.Bucket(bucketKeyObjectLeases) + if lbkt != nil { + return lbkt.DeleteBucket([]byte(node.Key)) + } + case ResourceIngest: + ibkt := nsbkt.Bucket(bucketKeyObjectContent) + if ibkt != nil { + ibkt = ibkt.Bucket(bucketKeyObjectIngests) + } + if ibkt != nil { + log.G(ctx).WithField("ref", node.Key).Debug("remove ingest") + return ibkt.DeleteBucket([]byte(node.Key)) + } } return nil diff --git a/vendor/github.com/containerd/containerd/metadata/leases.go b/vendor/github.com/containerd/containerd/metadata/leases.go index 317f000ce1..8835065d1e 100644 --- a/vendor/github.com/containerd/containerd/metadata/leases.go +++ b/vendor/github.com/containerd/containerd/metadata/leases.go @@ -22,6 +22,7 @@ import ( "github.com/boltdb/bolt" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/filters" "github.com/containerd/containerd/leases" "github.com/containerd/containerd/metadata/boltutil" "github.com/containerd/containerd/namespaces" @@ -29,17 +30,6 @@ import ( "github.com/pkg/errors" ) -// Lease retains resources to prevent garbage collection before -// the resources can be fully referenced. -type Lease struct { - ID string - CreatedAt time.Time - Labels map[string]string - - Content []string - Snapshots map[string][]string -} - // LeaseManager manages the create/delete lifecyle of leases // and also returns existing leases type LeaseManager struct { @@ -55,49 +45,56 @@ func NewLeaseManager(tx *bolt.Tx) *LeaseManager { } // Create creates a new lease using the provided lease -func (lm *LeaseManager) Create(ctx context.Context, lid string, labels map[string]string) (Lease, error) { +func (lm *LeaseManager) Create(ctx context.Context, opts ...leases.Opt) (leases.Lease, error) { + var l leases.Lease + for _, opt := range opts { + if err := opt(&l); err != nil { + return leases.Lease{}, err + } + } + if l.ID == "" { + return leases.Lease{}, errors.New("lease id must be provided") + } + namespace, err := namespaces.NamespaceRequired(ctx) if err != nil { - return Lease{}, err + return leases.Lease{}, err } topbkt, err := createBucketIfNotExists(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases) if err != nil { - return Lease{}, err + return leases.Lease{}, err } - txbkt, err := topbkt.CreateBucket([]byte(lid)) + txbkt, err := topbkt.CreateBucket([]byte(l.ID)) if err != nil { if err == bolt.ErrBucketExists { err = errdefs.ErrAlreadyExists } - return Lease{}, errors.Wrapf(err, "lease %q", lid) + return leases.Lease{}, errors.Wrapf(err, "lease %q", l.ID) } t := time.Now().UTC() createdAt, err := t.MarshalBinary() if err != nil { - return Lease{}, err + return leases.Lease{}, err } if err := txbkt.Put(bucketKeyCreatedAt, createdAt); err != nil { - return Lease{}, err + return leases.Lease{}, err } - if labels != nil { - if err := boltutil.WriteLabels(txbkt, labels); err != nil { - return Lease{}, err + if l.Labels != nil { + if err := boltutil.WriteLabels(txbkt, l.Labels); err != nil { + return leases.Lease{}, err } } + l.CreatedAt = t - return Lease{ - ID: lid, - CreatedAt: t, - Labels: labels, - }, nil + return l, nil } // Delete delets the lease with the provided lease ID -func (lm *LeaseManager) Delete(ctx context.Context, lid string) error { +func (lm *LeaseManager) Delete(ctx context.Context, lease leases.Lease, _ ...leases.DeleteOpt) error { namespace, err := namespaces.NamespaceRequired(ctx) if err != nil { return err @@ -105,26 +102,34 @@ func (lm *LeaseManager) Delete(ctx context.Context, lid string) error { topbkt := getBucket(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases) if topbkt == nil { - return nil + return errors.Wrapf(errdefs.ErrNotFound, "lease %q", lease.ID) } - if err := topbkt.DeleteBucket([]byte(lid)); err != nil && err != bolt.ErrBucketNotFound { + if err := topbkt.DeleteBucket([]byte(lease.ID)); err != nil { + if err == bolt.ErrBucketNotFound { + err = errors.Wrapf(errdefs.ErrNotFound, "lease %q", lease.ID) + } return err } return nil } // List lists all active leases -func (lm *LeaseManager) List(ctx context.Context, includeResources bool, filter ...string) ([]Lease, error) { +func (lm *LeaseManager) List(ctx context.Context, fs ...string) ([]leases.Lease, error) { namespace, err := namespaces.NamespaceRequired(ctx) if err != nil { return nil, err } - var leases []Lease + filter, err := filters.ParseAll(fs...) + if err != nil { + return nil, errors.Wrapf(errdefs.ErrInvalidArgument, err.Error()) + } + + var ll []leases.Lease topbkt := getBucket(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases) if topbkt == nil { - return leases, nil + return ll, nil } if err := topbkt.ForEach(func(k, v []byte) error { @@ -133,7 +138,7 @@ func (lm *LeaseManager) List(ctx context.Context, includeResources bool, filter } txbkt := topbkt.Bucket(k) - l := Lease{ + l := leases.Lease{ ID: string(k), } @@ -150,21 +155,20 @@ func (lm *LeaseManager) List(ctx context.Context, includeResources bool, filter } l.Labels = labels - // TODO: Read Snapshots - // TODO: Read Content - - leases = append(leases, l) + if filter.Match(adaptLease(l)) { + ll = append(ll, l) + } return nil }); err != nil { return nil, err } - return leases, nil + return ll, nil } func addSnapshotLease(ctx context.Context, tx *bolt.Tx, snapshotter, key string) error { - lid, ok := leases.Lease(ctx) + lid, ok := leases.FromContext(ctx) if !ok { return nil } @@ -193,7 +197,7 @@ func addSnapshotLease(ctx context.Context, tx *bolt.Tx, snapshotter, key string) } func removeSnapshotLease(ctx context.Context, tx *bolt.Tx, snapshotter, key string) error { - lid, ok := leases.Lease(ctx) + lid, ok := leases.FromContext(ctx) if !ok { return nil } @@ -213,7 +217,7 @@ func removeSnapshotLease(ctx context.Context, tx *bolt.Tx, snapshotter, key stri } func addContentLease(ctx context.Context, tx *bolt.Tx, dgst digest.Digest) error { - lid, ok := leases.Lease(ctx) + lid, ok := leases.FromContext(ctx) if !ok { return nil } @@ -237,7 +241,7 @@ func addContentLease(ctx context.Context, tx *bolt.Tx, dgst digest.Digest) error } func removeContentLease(ctx context.Context, tx *bolt.Tx, dgst digest.Digest) error { - lid, ok := leases.Lease(ctx) + lid, ok := leases.FromContext(ctx) if !ok { return nil } @@ -255,3 +259,51 @@ func removeContentLease(ctx context.Context, tx *bolt.Tx, dgst digest.Digest) er return bkt.Delete([]byte(dgst.String())) } + +func addIngestLease(ctx context.Context, tx *bolt.Tx, ref string) (bool, error) { + lid, ok := leases.FromContext(ctx) + if !ok { + return false, nil + } + + namespace, ok := namespaces.Namespace(ctx) + if !ok { + panic("namespace must already be required") + } + + bkt := getBucket(tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases, []byte(lid)) + if bkt == nil { + return false, errors.Wrap(errdefs.ErrNotFound, "lease does not exist") + } + + bkt, err := bkt.CreateBucketIfNotExists(bucketKeyObjectIngests) + if err != nil { + return false, err + } + + if err := bkt.Put([]byte(ref), nil); err != nil { + return false, err + } + + return true, nil +} + +func removeIngestLease(ctx context.Context, tx *bolt.Tx, ref string) error { + lid, ok := leases.FromContext(ctx) + if !ok { + return nil + } + + namespace, ok := namespaces.Namespace(ctx) + if !ok { + panic("namespace must already be checked") + } + + bkt := getBucket(tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases, []byte(lid), bucketKeyObjectIngests) + if bkt == nil { + // Key does not exist so we return nil + return nil + } + + return bkt.Delete([]byte(ref)) +} diff --git a/vendor/github.com/containerd/containerd/mount/mount_linux.go b/vendor/github.com/containerd/containerd/mount/mount_linux.go index 82fc0b279e..b5a16148ac 100644 --- a/vendor/github.com/containerd/containerd/mount/mount_linux.go +++ b/vendor/github.com/containerd/containerd/mount/mount_linux.go @@ -17,16 +17,41 @@ package mount import ( + "fmt" + "os" + "path" "strings" "time" + "github.com/containerd/containerd/sys" "github.com/pkg/errors" "golang.org/x/sys/unix" ) +var pagesize = 4096 + +func init() { + pagesize = os.Getpagesize() +} + // Mount to the provided target path func (m *Mount) Mount(target string) error { - flags, data := parseMountOptions(m.Options) + var ( + chdir string + options = m.Options + ) + + // avoid hitting one page limit of mount argument buffer + // + // NOTE: 512 is a buffer during pagesize check. + if m.Type == "overlay" && optionsSize(options) >= pagesize-512 { + chdir, options = compactLowerdirOption(options) + } + + flags, data := parseMountOptions(options) + if len(data) > pagesize { + return errors.Errorf("mount options is too long") + } // propagation types. const ptypes = unix.MS_SHARED | unix.MS_PRIVATE | unix.MS_SLAVE | unix.MS_UNBINDABLE @@ -38,7 +63,7 @@ func (m *Mount) Mount(target string) error { if flags&unix.MS_REMOUNT == 0 || data != "" { // Initial call applying all non-propagation flags for mount // or remount with changed data - if err := unix.Mount(m.Source, target, m.Type, uintptr(oflags), data); err != nil { + if err := mountAt(chdir, m.Source, target, m.Type, uintptr(oflags), data); err != nil { return err } } @@ -155,3 +180,129 @@ func parseMountOptions(options []string) (int, string) { } return flag, strings.Join(data, ",") } + +// compactLowerdirOption updates overlay lowdir option and returns the common +// dir among all the lowdirs. +func compactLowerdirOption(opts []string) (string, []string) { + idx, dirs := findOverlayLowerdirs(opts) + if idx == -1 || len(dirs) == 1 { + // no need to compact if there is only one lowerdir + return "", opts + } + + // find out common dir + commondir := longestCommonPrefix(dirs) + if commondir == "" { + return "", opts + } + + // NOTE: the snapshot id is based on digits. + // in order to avoid to get snapshots/x, should be back to parent dir. + // however, there is assumption that the common dir is ${root}/io.containerd.v1.overlayfs/snapshots. + commondir = path.Dir(commondir) + if commondir == "/" { + return "", opts + } + commondir = commondir + "/" + + newdirs := make([]string, 0, len(dirs)) + for _, dir := range dirs { + newdirs = append(newdirs, dir[len(commondir):]) + } + + newopts := copyOptions(opts) + newopts = append(newopts[:idx], newopts[idx+1:]...) + newopts = append(newopts, fmt.Sprintf("lowerdir=%s", strings.Join(newdirs, ":"))) + return commondir, newopts +} + +// findOverlayLowerdirs returns the index of lowerdir in mount's options and +// all the lowerdir target. +func findOverlayLowerdirs(opts []string) (int, []string) { + var ( + idx = -1 + prefix = "lowerdir=" + ) + + for i, opt := range opts { + if strings.HasPrefix(opt, prefix) { + idx = i + break + } + } + + if idx == -1 { + return -1, nil + } + return idx, strings.Split(opts[idx][len(prefix):], ":") +} + +// longestCommonPrefix finds the longest common prefix in the string slice. +func longestCommonPrefix(strs []string) string { + if len(strs) == 0 { + return "" + } else if len(strs) == 1 { + return strs[0] + } + + // find out the min/max value by alphabetical order + min, max := strs[0], strs[0] + for _, str := range strs[1:] { + if min > str { + min = str + } + if max < str { + max = str + } + } + + // find out the common part between min and max + for i := 0; i < len(min) && i < len(max); i++ { + if min[i] != max[i] { + return min[:i] + } + } + return min +} + +// copyOptions copies the options. +func copyOptions(opts []string) []string { + if len(opts) == 0 { + return nil + } + + acopy := make([]string, len(opts)) + copy(acopy, opts) + return acopy +} + +// optionsSize returns the byte size of options of mount. +func optionsSize(opts []string) int { + size := 0 + for _, opt := range opts { + size += len(opt) + } + return size +} + +func mountAt(chdir string, source, target, fstype string, flags uintptr, data string) error { + if chdir == "" { + return unix.Mount(source, target, fstype, flags, data) + } + + f, err := os.Open(chdir) + if err != nil { + return errors.Wrap(err, "failed to mountat") + } + defer f.Close() + + fs, err := f.Stat() + if err != nil { + return errors.Wrap(err, "failed to mountat") + } + + if !fs.IsDir() { + return errors.Wrap(errors.Errorf("%s is not dir", chdir), "failed to mountat") + } + return errors.Wrap(sys.FMountat(f.Fd(), source, target, fstype, flags, data), "failed to mountat") +} diff --git a/vendor/github.com/containerd/containerd/mount/temp_unix.go b/vendor/github.com/containerd/containerd/mount/temp_unix.go index fcf90d6fbd..3d490e8a70 100644 --- a/vendor/github.com/containerd/containerd/mount/temp_unix.go +++ b/vendor/github.com/containerd/containerd/mount/temp_unix.go @@ -39,10 +39,10 @@ func SetTempMountLocation(root string) error { } // CleanupTempMounts all temp mounts and remove the directories -func CleanupTempMounts(flags int) error { +func CleanupTempMounts(flags int) (warnings []error, err error) { mounts, err := Self() if err != nil { - return err + return nil, err } var toUnmount []string for _, m := range mounts { @@ -53,11 +53,12 @@ func CleanupTempMounts(flags int) error { sort.Sort(sort.Reverse(sort.StringSlice(toUnmount))) for _, path := range toUnmount { if err := UnmountAll(path, flags); err != nil { - return err + warnings = append(warnings, err) + continue } if err := os.Remove(path); err != nil { - return err + warnings = append(warnings, err) } } - return nil + return warnings, nil } diff --git a/vendor/github.com/containerd/containerd/mount/temp_unsupported.go b/vendor/github.com/containerd/containerd/mount/temp_unsupported.go index de3f4163a1..942be4128a 100644 --- a/vendor/github.com/containerd/containerd/mount/temp_unsupported.go +++ b/vendor/github.com/containerd/containerd/mount/temp_unsupported.go @@ -24,6 +24,6 @@ func SetTempMountLocation(root string) error { } // CleanupTempMounts all temp mounts and remove the directories -func CleanupTempMounts(flags int) error { - return nil +func CleanupTempMounts(flags int) ([]error, error) { + return nil, nil } diff --git a/vendor/github.com/containerd/containerd/oci/spec.go b/vendor/github.com/containerd/containerd/oci/spec.go index 23f9315a41..ffd0bffca0 100644 --- a/vendor/github.com/containerd/containerd/oci/spec.go +++ b/vendor/github.com/containerd/containerd/oci/spec.go @@ -34,10 +34,23 @@ func GenerateSpec(ctx context.Context, client Client, c *containers.Container, o if err != nil { return nil, err } + + return s, ApplyOpts(ctx, client, c, s, opts...) +} + +// ApplyOpts applys the options to the given spec, injecting data from the +// context, client and container instance. +func ApplyOpts(ctx context.Context, client Client, c *containers.Container, s *Spec, opts ...SpecOpts) error { for _, o := range opts { if err := o(ctx, client, c, s); err != nil { - return nil, err + return err } } - return s, nil + + return nil +} + +func createDefaultSpec(ctx context.Context, id string) (*Spec, error) { + var s Spec + return &s, populateDefaultSpec(ctx, &s, id) } diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts.go b/vendor/github.com/containerd/containerd/oci/spec_opts.go index 57d95306c5..fd2cfb0392 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_opts.go +++ b/vendor/github.com/containerd/containerd/oci/spec_opts.go @@ -18,10 +18,13 @@ package oci import ( "context" + "encoding/json" + "io/ioutil" "strings" "github.com/containerd/containerd/containers" specs "github.com/opencontainers/runtime-spec/specs-go" + "github.com/pkg/errors" ) // SpecOpts sets spec specific information to a newly generated OCI spec @@ -46,6 +49,38 @@ func setProcess(s *Spec) { } } +// WithDefaultSpec returns a SpecOpts that will populate the spec with default +// values. +// +// Use as the first option to clear the spec, then apply options afterwards. +func WithDefaultSpec() SpecOpts { + return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error { + return populateDefaultSpec(ctx, s, c.ID) + } +} + +// WithSpecFromBytes loads the the spec from the provided byte slice. +func WithSpecFromBytes(p []byte) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + *s = Spec{} // make sure spec is cleared. + if err := json.Unmarshal(p, s); err != nil { + return errors.Wrapf(err, "decoding spec config file failed, current supported OCI runtime-spec : v%s", specs.Version) + } + return nil + } +} + +// WithSpecFromFile loads the specification from the provided filename. +func WithSpecFromFile(filename string) SpecOpts { + return func(ctx context.Context, c Client, container *containers.Container, s *Spec) error { + p, err := ioutil.ReadFile(filename) + if err != nil { + return errors.Wrap(err, "cannot load spec config file") + } + return WithSpecFromBytes(p)(ctx, c, container, s) + } +} + // WithProcessArgs replaces the args on the generated spec func WithProcessArgs(args ...string) SpecOpts { return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go b/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go index 27be93a209..80ffd165c1 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go +++ b/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go @@ -106,6 +106,12 @@ func WithLinuxNamespace(ns specs.LinuxNamespace) SpecOpts { // WithImageConfig configures the spec to from the configuration of an Image func WithImageConfig(image Image) SpecOpts { + return WithImageConfigArgs(image, nil) +} + +// WithImageConfigArgs configures the spec to from the configuration of an Image with additional args that +// replaces the CMD of the image +func WithImageConfigArgs(image Image, args []string) SpecOpts { return func(ctx context.Context, client Client, c *containers.Container, s *Spec) error { ic, err := image.Config(ctx) if err != nil { @@ -133,6 +139,9 @@ func WithImageConfig(image Image) SpecOpts { setProcess(s) s.Process.Env = append(s.Process.Env, config.Env...) cmd := config.Cmd + if len(args) > 0 { + cmd = args + } s.Process.Args = append(config.Entrypoint, cmd...) cwd := config.WorkingDir if cwd == "" { @@ -348,8 +357,8 @@ func WithUIDGID(uid, gid uint32) SpecOpts { // WithUserID sets the correct UID and GID for the container based // on the image's /etc/passwd contents. If /etc/passwd does not exist, -// or uid is not found in /etc/passwd, it sets gid to be the same with -// uid, and not returns error. +// or uid is not found in /etc/passwd, it sets the requested uid, +// additionally sets the gid to 0, and does not return an error. func WithUserID(uid uint32) SpecOpts { return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) { setProcess(s) @@ -362,7 +371,7 @@ func WithUserID(uid uint32) SpecOpts { }) if err != nil { if os.IsNotExist(err) || err == errNoUsersFound { - s.Process.User.UID, s.Process.User.GID = uid, uid + s.Process.User.UID, s.Process.User.GID = uid, 0 return nil } return err @@ -388,7 +397,7 @@ func WithUserID(uid uint32) SpecOpts { }) if err != nil { if os.IsNotExist(err) || err == errNoUsersFound { - s.Process.User.UID, s.Process.User.GID = uid, uid + s.Process.User.UID, s.Process.User.GID = uid, 0 return nil } return err @@ -593,6 +602,110 @@ func WithSeccompUnconfined(_ context.Context, _ Client, _ *containers.Container, return nil } +// WithParentCgroupDevices uses the default cgroup setup to inherit the container's parent cgroup's +// allowed and denied devices +func WithParentCgroupDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setLinux(s) + if s.Linux.Resources == nil { + s.Linux.Resources = &specs.LinuxResources{} + } + s.Linux.Resources.Devices = nil + return nil +} + +// WithDefaultUnixDevices adds the default devices for unix such as /dev/null, /dev/random to +// the container's resource cgroup spec +func WithDefaultUnixDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setLinux(s) + if s.Linux.Resources == nil { + s.Linux.Resources = &specs.LinuxResources{} + } + intptr := func(i int64) *int64 { + return &i + } + s.Linux.Resources.Devices = append(s.Linux.Resources.Devices, []specs.LinuxDeviceCgroup{ + { + // "/dev/null", + Type: "c", + Major: intptr(1), + Minor: intptr(3), + Access: rwm, + Allow: true, + }, + { + // "/dev/random", + Type: "c", + Major: intptr(1), + Minor: intptr(8), + Access: rwm, + Allow: true, + }, + { + // "/dev/full", + Type: "c", + Major: intptr(1), + Minor: intptr(7), + Access: rwm, + Allow: true, + }, + { + // "/dev/tty", + Type: "c", + Major: intptr(5), + Minor: intptr(0), + Access: rwm, + Allow: true, + }, + { + // "/dev/zero", + Type: "c", + Major: intptr(1), + Minor: intptr(5), + Access: rwm, + Allow: true, + }, + { + // "/dev/urandom", + Type: "c", + Major: intptr(1), + Minor: intptr(9), + Access: rwm, + Allow: true, + }, + { + // "/dev/console", + Type: "c", + Major: intptr(5), + Minor: intptr(1), + Access: rwm, + Allow: true, + }, + // /dev/pts/ - pts namespaces are "coming soon" + { + Type: "c", + Major: intptr(136), + Access: rwm, + Allow: true, + }, + { + Type: "c", + Major: intptr(5), + Minor: intptr(2), + Access: rwm, + Allow: true, + }, + { + // tuntap + Type: "c", + Major: intptr(10), + Minor: intptr(200), + Access: rwm, + Allow: true, + }, + }...) + return nil +} + // WithPrivileged sets up options for a privileged container // TODO(justincormack) device handling var WithPrivileged = Compose( diff --git a/vendor/github.com/containerd/containerd/oci/spec_unix.go b/vendor/github.com/containerd/containerd/oci/spec_unix.go index f8d8524ddb..cb69434cba 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_unix.go +++ b/vendor/github.com/containerd/containerd/oci/spec_unix.go @@ -76,12 +76,13 @@ func defaultNamespaces() []specs.LinuxNamespace { } } -func createDefaultSpec(ctx context.Context, id string) (*Spec, error) { +func populateDefaultSpec(ctx context.Context, s *Spec, id string) error { ns, err := namespaces.NamespaceRequired(ctx) if err != nil { - return nil, err + return err } - s := &Spec{ + + *s = Spec{ Version: specs.Version, Root: &specs.Root{ Path: defaultRootfsPath, @@ -183,5 +184,5 @@ func createDefaultSpec(ctx context.Context, id string) (*Spec, error) { Namespaces: defaultNamespaces(), }, } - return s, nil + return nil } diff --git a/vendor/github.com/containerd/containerd/oci/spec_windows.go b/vendor/github.com/containerd/containerd/oci/spec_windows.go index 82d7ef158a..d0236585dc 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_windows.go +++ b/vendor/github.com/containerd/containerd/oci/spec_windows.go @@ -22,8 +22,8 @@ import ( specs "github.com/opencontainers/runtime-spec/specs-go" ) -func createDefaultSpec(ctx context.Context, id string) (*Spec, error) { - return &Spec{ +func populateDefaultSpec(ctx context.Context, s *Spec, id string) error { + *s = Spec{ Version: specs.Version, Root: &specs.Root{}, Process: &specs.Process{ @@ -39,5 +39,6 @@ func createDefaultSpec(ctx context.Context, id string) (*Spec, error) { AllowUnqualifiedDNSQuery: true, }, }, - }, nil + } + return nil } diff --git a/vendor/github.com/containerd/containerd/platforms/platforms.go b/vendor/github.com/containerd/containerd/platforms/platforms.go index 29b7ad6b5e..2c2cc1102e 100644 --- a/vendor/github.com/containerd/containerd/platforms/platforms.go +++ b/vendor/github.com/containerd/containerd/platforms/platforms.go @@ -109,6 +109,7 @@ package platforms import ( "regexp" "runtime" + "strconv" "strings" "github.com/containerd/containerd/errdefs" @@ -230,6 +231,16 @@ func Parse(specifier string) (specs.Platform, error) { return specs.Platform{}, errors.Wrapf(errdefs.ErrInvalidArgument, "%q: cannot parse platform specifier", specifier) } +// MustParse is like Parses but panics if the specifier cannot be parsed. +// Simplifies initialization of global variables. +func MustParse(specifier string) specs.Platform { + p, err := Parse(specifier) + if err != nil { + panic("platform: Parse(" + strconv.Quote(specifier) + "): " + err.Error()) + } + return p +} + // Format returns a string specifier from the provided platform specification. func Format(platform specs.Platform) string { if platform.OS == "" { diff --git a/vendor/github.com/containerd/containerd/plugin/plugin.go b/vendor/github.com/containerd/containerd/plugin/plugin.go index 81318ed6ab..0847ae7f28 100644 --- a/vendor/github.com/containerd/containerd/plugin/plugin.go +++ b/vendor/github.com/containerd/containerd/plugin/plugin.go @@ -58,6 +58,8 @@ const ( InternalPlugin Type = "io.containerd.internal.v1" // RuntimePlugin implements a runtime RuntimePlugin Type = "io.containerd.runtime.v1" + // RuntimePluginV2 implements a runtime v2 + RuntimePluginV2 Type = "io.containerd.runtime.v2" // ServicePlugin implements a internal service ServicePlugin Type = "io.containerd.service.v1" // GRPCPlugin implements a grpc service diff --git a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go b/vendor/github.com/containerd/containerd/remotes/docker/resolver.go index eca02d532c..f0a677c839 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/resolver.go @@ -53,6 +53,7 @@ var ( type dockerResolver struct { credentials func(string) (string, string, error) + host func(string) (string, error) plainHTTP bool client *http.Client tracker StatusTracker @@ -65,6 +66,9 @@ type ResolverOptions struct { // is interpretted as a long lived token. Credentials func(string) (string, string, error) + // Host provides the hostname given a namespace. + Host func(string) (string, error) + // PlainHTTP specifies to use plain http and not https PlainHTTP bool @@ -77,14 +81,27 @@ type ResolverOptions struct { Tracker StatusTracker } +// DefaultHost is the default host function. +func DefaultHost(ns string) (string, error) { + if ns == "docker.io" { + return "registry-1.docker.io", nil + } + return ns, nil +} + // NewResolver returns a new resolver to a Docker registry func NewResolver(options ResolverOptions) remotes.Resolver { tracker := options.Tracker if tracker == nil { tracker = NewInMemoryTracker() } + host := options.Host + if host == nil { + host = DefaultHost + } return &dockerResolver{ credentials: options.Credentials, + host: host, plainHTTP: options.PlainHTTP, client: options.Client, tracker: tracker, @@ -270,18 +287,19 @@ func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) { ) host := refspec.Hostname() - base.Scheme = "https" - - if host == "docker.io" { - base.Host = "registry-1.docker.io" - } else { - base.Host = host - - if r.plainHTTP || strings.HasPrefix(host, "localhost:") { - base.Scheme = "http" + base.Host = host + if r.host != nil { + base.Host, err = r.host(host) + if err != nil { + return nil, err } } + base.Scheme = "https" + if r.plainHTTP || strings.HasPrefix(base.Host, "localhost:") { + base.Scheme = "http" + } + if r.credentials != nil { username, secret, err = r.credentials(base.Host) if err != nil { diff --git a/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go b/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go index cf1137fc30..3155d6ec35 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go @@ -18,7 +18,6 @@ package schema1 import ( "bytes" - "compress/gzip" "context" "encoding/base64" "encoding/json" @@ -31,6 +30,7 @@ import ( "golang.org/x/sync/errgroup" + "github.com/containerd/containerd/archive/compression" "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" @@ -255,8 +255,9 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro log.G(ctx).Debug("fetch blob") var ( - ref = remotes.MakeRefKey(ctx, desc) - calc = newBlobStateCalculator() + ref = remotes.MakeRefKey(ctx, desc) + calc = newBlobStateCalculator() + compressMethod = compression.Gzip ) // size may be unknown, set to zero for content ingest @@ -280,13 +281,14 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro } defer ra.Close() - gr, err := gzip.NewReader(content.NewReader(ra)) + r, err := compression.DecompressStream(content.NewReader(ra)) if err != nil { return err } - defer gr.Close() - _, err = io.Copy(calc, gr) + compressMethod = r.GetCompression() + _, err = io.Copy(calc, r) + r.Close() if err != nil { return err } @@ -303,13 +305,14 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro pr, pw := io.Pipe() eg.Go(func() error { - gr, err := gzip.NewReader(pr) + r, err := compression.DecompressStream(pr) if err != nil { return err } - defer gr.Close() - _, err = io.Copy(calc, gr) + compressMethod = r.GetCompression() + _, err = io.Copy(calc, r) + r.Close() pr.CloseWithError(err) return err }) @@ -333,6 +336,11 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro desc.Size = info.Size } + if compressMethod == compression.Uncompressed { + log.G(ctx).WithField("id", desc.Digest).Debugf("changed media type for uncompressed schema1 layer blob") + desc.MediaType = images.MediaTypeDockerSchema2Layer + } + state := calc.State() c.mu.Lock() @@ -342,6 +350,7 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro return nil } + func (c *Converter) schema1ManifestHistory() ([]ocispec.History, []digest.Digest, error) { if c.pulledManifest == nil { return nil, nil, errors.New("missing schema 1 manifest for conversion") diff --git a/vendor/github.com/containerd/containerd/rootfs/apply.go b/vendor/github.com/containerd/containerd/rootfs/apply.go index a1a2db9383..3ea830f6b4 100644 --- a/vendor/github.com/containerd/containerd/rootfs/apply.go +++ b/vendor/github.com/containerd/containerd/rootfs/apply.go @@ -18,9 +18,9 @@ package rootfs import ( "context" - "crypto/rand" "encoding/base64" "fmt" + "math/rand" "time" "github.com/containerd/containerd/diff" diff --git a/vendor/github.com/containerd/containerd/runtime/runtime.go b/vendor/github.com/containerd/containerd/runtime/runtime.go index 0057c1a4ec..1b3f87c152 100644 --- a/vendor/github.com/containerd/containerd/runtime/runtime.go +++ b/vendor/github.com/containerd/containerd/runtime/runtime.go @@ -42,8 +42,12 @@ type CreateOpts struct { IO IO // Checkpoint digest to restore container state Checkpoint string - // Options for the runtime and container - Options *types.Any + // RuntimeOptions for the runtime + RuntimeOptions *types.Any + // TaskOptions received for the task + TaskOptions *types.Any + // Runtime to use + Runtime string } // Exit information for a process @@ -64,7 +68,5 @@ type PlatformRuntime interface { Get(context.Context, string) (Task, error) // Tasks returns all the current tasks for the runtime. // Any container runs at most one task at a time. - Tasks(context.Context) ([]Task, error) - // Delete removes the task in the runtime. - Delete(context.Context, Task) (*Exit, error) + Tasks(context.Context, bool) ([]Task, error) } diff --git a/vendor/github.com/containerd/containerd/runtime/task.go b/vendor/github.com/containerd/containerd/runtime/task.go index f8a67cfaee..981e290c68 100644 --- a/vendor/github.com/containerd/containerd/runtime/task.go +++ b/vendor/github.com/containerd/containerd/runtime/task.go @@ -46,14 +46,16 @@ type Process interface { Start(context.Context) error // Wait for the process to exit Wait(context.Context) (*Exit, error) + // Delete deletes the process + Delete(context.Context) (*Exit, error) } // Task is the runtime object for an executing container type Task interface { Process - // Information of the container - Info() TaskInfo + // Namespace that the task exists in + Namespace() string // Pause pauses the container process Pause(context.Context) error // Resume unpauses the container process @@ -64,14 +66,12 @@ type Task interface { Pids(context.Context) ([]ProcessInfo, error) // Checkpoint checkpoints a container to an image with live system data Checkpoint(context.Context, string, *types.Any) error - // DeleteProcess deletes a specific exec process via its id - DeleteProcess(context.Context, string) (*Exit, error) // Update sets the provided resources to a running task Update(context.Context, *types.Any) error // Process returns a process within the task for the provided id Process(context.Context, string) (Process, error) - // Metrics returns runtime specific metrics for a task - Metrics(context.Context) (interface{}, error) + // Stats returns runtime specific metrics for a task + Stats(context.Context) (*types.Any, error) } // ExecOpts provides additional options for additional processes running in a task diff --git a/vendor/github.com/containerd/containerd/runtime/task_list.go b/vendor/github.com/containerd/containerd/runtime/task_list.go index 92f25715c8..b92c6e01cd 100644 --- a/vendor/github.com/containerd/containerd/runtime/task_list.go +++ b/vendor/github.com/containerd/containerd/runtime/task_list.go @@ -64,14 +64,22 @@ func (l *TaskList) Get(ctx context.Context, id string) (Task, error) { } // GetAll tasks under a namespace -func (l *TaskList) GetAll(ctx context.Context) ([]Task, error) { +func (l *TaskList) GetAll(ctx context.Context, noNS bool) ([]Task, error) { l.mu.Lock() defer l.mu.Unlock() + var o []Task + if noNS { + for ns := range l.tasks { + for _, t := range l.tasks[ns] { + o = append(o, t) + } + } + return o, nil + } namespace, err := namespaces.NamespaceRequired(ctx) if err != nil { return nil, err } - var o []Task tasks, ok := l.tasks[namespace] if !ok { return o, nil diff --git a/vendor/github.com/containerd/containerd/runtime/linux/bundle.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go similarity index 97% rename from vendor/github.com/containerd/containerd/runtime/linux/bundle.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go index 990309280b..37a567e282 100644 --- a/vendor/github.com/containerd/containerd/runtime/linux/bundle.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go @@ -26,8 +26,8 @@ import ( "github.com/containerd/containerd/events/exchange" "github.com/containerd/containerd/runtime/linux/runctypes" - "github.com/containerd/containerd/runtime/shim" - "github.com/containerd/containerd/runtime/shim/client" + "github.com/containerd/containerd/runtime/v1/shim" + "github.com/containerd/containerd/runtime/v1/shim/client" "github.com/pkg/errors" ) diff --git a/vendor/github.com/containerd/containerd/runtime/linux/proc/deleted_state.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/deleted_state.go similarity index 100% rename from vendor/github.com/containerd/containerd/runtime/linux/proc/deleted_state.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/proc/deleted_state.go diff --git a/vendor/github.com/containerd/containerd/runtime/linux/proc/exec.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go similarity index 97% rename from vendor/github.com/containerd/containerd/runtime/linux/proc/exec.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go index 337db1b74c..4a3fefddcc 100644 --- a/vendor/github.com/containerd/containerd/runtime/linux/proc/exec.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go @@ -89,7 +89,7 @@ func (e *execProcess) ExitedAt() time.Time { func (e *execProcess) setExited(status int) { e.status = status e.exited = time.Now() - e.parent.platform.ShutdownConsole(context.Background(), e.console) + e.parent.Platform.ShutdownConsole(context.Background(), e.console) close(e.waitBlock) } @@ -180,7 +180,7 @@ func (e *execProcess) start(ctx context.Context) (err error) { if err != nil { return errors.Wrap(err, "failed to retrieve console master") } - if e.console, err = e.parent.platform.CopyConsole(ctx, console, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg, ©WaitGroup); err != nil { + if e.console, err = e.parent.Platform.CopyConsole(ctx, console, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg, ©WaitGroup); err != nil { return errors.Wrap(err, "failed to start console copy") } } else if !e.stdio.IsNull() { diff --git a/vendor/github.com/containerd/containerd/runtime/linux/proc/exec_state.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go similarity index 100% rename from vendor/github.com/containerd/containerd/runtime/linux/proc/exec_state.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go diff --git a/vendor/github.com/containerd/containerd/runtime/linux/proc/init.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go similarity index 67% rename from vendor/github.com/containerd/containerd/runtime/linux/proc/init.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go index c538b79379..fe11285c7a 100644 --- a/vendor/github.com/containerd/containerd/runtime/linux/proc/init.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go @@ -33,11 +33,9 @@ import ( "github.com/containerd/console" "github.com/containerd/containerd/log" "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/runtime/linux/runctypes" "github.com/containerd/containerd/runtime/proc" "github.com/containerd/fifo" runc "github.com/containerd/go-runc" - "github.com/containerd/typeurl" google_protobuf "github.com/gogo/protobuf/types" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -59,23 +57,25 @@ type Init struct { waitBlock chan struct{} - workDir string + WorkDir string - id string - bundle string - console console.Console - platform proc.Platform - io runc.IO - runtime *runc.Runc - status int - exited time.Time - pid int - closers []io.Closer - stdin io.Closer - stdio proc.Stdio - rootfs string - IoUID int - IoGID int + id string + Bundle string + console console.Console + Platform proc.Platform + io runc.IO + runtime *runc.Runc + status int + exited time.Time + pid int + closers []io.Closer + stdin io.Closer + stdio proc.Stdio + Rootfs string + IoUID int + IoGID int + NoPivotRoot bool + NoNewKeyring bool } // NewRunc returns a new runc instance for a process @@ -94,90 +94,50 @@ func NewRunc(root, path, namespace, runtime, criu string, systemd bool) *runc.Ru } } -// New returns a new init process -func New(context context.Context, path, workDir, runtimeRoot, namespace, criu string, systemdCgroup bool, platform proc.Platform, r *CreateConfig) (*Init, error) { - var success bool - - var options runctypes.CreateOptions - if r.Options != nil { - v, err := typeurl.UnmarshalAny(r.Options) - if err != nil { - return nil, err - } - options = *v.(*runctypes.CreateOptions) - } - - rootfs := filepath.Join(path, "rootfs") - // count the number of successful mounts so we can undo - // what was actually done rather than what should have been - // done. - defer func() { - if success { - return - } - if err2 := mount.UnmountAll(rootfs, 0); err2 != nil { - log.G(context).WithError(err2).Warn("Failed to cleanup rootfs mount") - } - }() - for _, rm := range r.Rootfs { - m := &mount.Mount{ - Type: rm.Type, - Source: rm.Source, - Options: rm.Options, - } - if err := m.Mount(rootfs); err != nil { - return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m) - } - } - runtime := NewRunc(runtimeRoot, path, namespace, r.Runtime, criu, systemdCgroup) +// New returns a new process +func New(id string, runtime *runc.Runc, stdio proc.Stdio) *Init { p := &Init{ - id: r.ID, - bundle: r.Bundle, - runtime: runtime, - platform: platform, - stdio: proc.Stdio{ - Stdin: r.Stdin, - Stdout: r.Stdout, - Stderr: r.Stderr, - Terminal: r.Terminal, - }, - rootfs: rootfs, - workDir: workDir, + id: id, + runtime: runtime, + stdio: stdio, status: 0, waitBlock: make(chan struct{}), - IoUID: int(options.IoUid), - IoGID: int(options.IoGid), } p.initState = &createdState{p: p} + return p +} + +// Create the process with the provided config +func (p *Init) Create(ctx context.Context, r *CreateConfig) error { var ( err error socket *runc.Socket ) if r.Terminal { if socket, err = runc.NewTempConsoleSocket(); err != nil { - return nil, errors.Wrap(err, "failed to create OCI runtime console socket") + return errors.Wrap(err, "failed to create OCI runtime console socket") } defer socket.Close() } else if hasNoIO(r) { if p.io, err = runc.NewNullIO(); err != nil { - return nil, errors.Wrap(err, "creating new NULL IO") + return errors.Wrap(err, "creating new NULL IO") } } else { - if p.io, err = runc.NewPipeIO(int(options.IoUid), int(options.IoGid)); err != nil { - return nil, errors.Wrap(err, "failed to create OCI runtime io pipes") + if p.io, err = runc.NewPipeIO(p.IoUID, p.IoGID); err != nil { + return errors.Wrap(err, "failed to create OCI runtime io pipes") } } - pidFile := filepath.Join(path, InitPidFile) + pidFile := filepath.Join(p.Bundle, InitPidFile) if r.Checkpoint != "" { opts := &runc.RestoreOpts{ CheckpointOpts: runc.CheckpointOpts{ ImagePath: r.Checkpoint, - WorkDir: p.workDir, + WorkDir: p.WorkDir, ParentPath: r.ParentCheckpoint, }, PidFile: pidFile, IO: p.io, - NoPivot: options.NoPivotRoot, + NoPivot: p.NoPivotRoot, Detach: true, NoSubreaper: true, } @@ -185,25 +145,24 @@ func New(context context.Context, path, workDir, runtimeRoot, namespace, criu st p: p, opts: opts, } - success = true - return p, nil + return nil } opts := &runc.CreateOpts{ PidFile: pidFile, IO: p.io, - NoPivot: options.NoPivotRoot, - NoNewKeyring: options.NoNewKeyring, + NoPivot: p.NoPivotRoot, + NoNewKeyring: p.NoNewKeyring, } if socket != nil { opts.ConsoleSocket = socket } - if err := p.runtime.Create(context, r.ID, r.Bundle, opts); err != nil { - return nil, p.runtimeError(err, "OCI runtime create failed") + if err := p.runtime.Create(ctx, r.ID, r.Bundle, opts); err != nil { + return p.runtimeError(err, "OCI runtime create failed") } if r.Stdin != "" { - sc, err := fifo.OpenFifo(context, r.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) + sc, err := fifo.OpenFifo(ctx, r.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) if err != nil { - return nil, errors.Wrapf(err, "failed to open stdin fifo %s", r.Stdin) + return errors.Wrapf(err, "failed to open stdin fifo %s", r.Stdin) } p.stdin = sc p.closers = append(p.closers, sc) @@ -212,27 +171,26 @@ func New(context context.Context, path, workDir, runtimeRoot, namespace, criu st if socket != nil { console, err := socket.ReceiveMaster() if err != nil { - return nil, errors.Wrap(err, "failed to retrieve console master") + return errors.Wrap(err, "failed to retrieve console master") } - console, err = platform.CopyConsole(context, console, r.Stdin, r.Stdout, r.Stderr, &p.wg, ©WaitGroup) + console, err = p.Platform.CopyConsole(ctx, console, r.Stdin, r.Stdout, r.Stderr, &p.wg, ©WaitGroup) if err != nil { - return nil, errors.Wrap(err, "failed to start console copy") + return errors.Wrap(err, "failed to start console copy") } p.console = console } else if !hasNoIO(r) { - if err := copyPipes(context, p.io, r.Stdin, r.Stdout, r.Stderr, &p.wg, ©WaitGroup); err != nil { - return nil, errors.Wrap(err, "failed to start io pipe copy") + if err := copyPipes(ctx, p.io, r.Stdin, r.Stdout, r.Stderr, &p.wg, ©WaitGroup); err != nil { + return errors.Wrap(err, "failed to start io pipe copy") } } copyWaitGroup.Wait() pid, err := runc.ReadPidFile(pidFile) if err != nil { - return nil, errors.Wrap(err, "failed to retrieve OCI runtime container pid") + return errors.Wrap(err, "failed to retrieve OCI runtime container pid") } p.pid = pid - success = true - return p, nil + return nil } // Wait for the process to exit @@ -286,7 +244,7 @@ func (p *Init) start(context context.Context) error { func (p *Init) setExited(status int) { p.exited = time.Now() p.status = status - p.platform.ShutdownConsole(context.Background(), p.console) + p.Platform.ShutdownConsole(context.Background(), p.console) close(p.waitBlock) } @@ -312,7 +270,7 @@ func (p *Init) delete(context context.Context) error { } p.io.Close() } - if err2 := mount.UnmountAll(p.rootfs, 0); err2 != nil { + if err2 := mount.UnmountAll(p.Rootfs, 0); err2 != nil { log.G(context).WithError(err2).Warn("failed to cleanup rootfs mount") if err == nil { err = errors.Wrap(err2, "failed rootfs umount") @@ -390,30 +348,22 @@ func (p *Init) exec(context context.Context, path string, r *ExecConfig) (proc.P } func (p *Init) checkpoint(context context.Context, r *CheckpointConfig) error { - var options runctypes.CheckpointOptions - if r.Options != nil { - v, err := typeurl.UnmarshalAny(r.Options) - if err != nil { - return err - } - options = *v.(*runctypes.CheckpointOptions) - } var actions []runc.CheckpointAction - if !options.Exit { + if !r.Exit { actions = append(actions, runc.LeaveRunning) } - work := filepath.Join(p.workDir, "criu-work") + work := filepath.Join(p.WorkDir, "criu-work") defer os.RemoveAll(work) if err := p.runtime.Checkpoint(context, p.id, &runc.CheckpointOpts{ WorkDir: work, ImagePath: r.Path, - AllowOpenTCP: options.OpenTcp, - AllowExternalUnixSockets: options.ExternalUnixSockets, - AllowTerminal: options.Terminal, - FileLocks: options.FileLocks, - EmptyNamespaces: options.EmptyNamespaces, + AllowOpenTCP: r.AllowOpenTCP, + AllowExternalUnixSockets: r.AllowExternalUnixSockets, + AllowTerminal: r.AllowTerminal, + FileLocks: r.FileLocks, + EmptyNamespaces: r.EmptyNamespaces, }, actions...); err != nil { - dumpLog := filepath.Join(p.bundle, "criu-dump.log") + dumpLog := filepath.Join(p.Bundle, "criu-dump.log") if cerr := copyFile(dumpLog, filepath.Join(work, "dump.log")); cerr != nil { log.G(context).Error(err) } diff --git a/vendor/github.com/containerd/containerd/runtime/linux/proc/init_state.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init_state.go similarity index 98% rename from vendor/github.com/containerd/containerd/runtime/linux/proc/init_state.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init_state.go index 55c0f05591..6a6b448d3a 100644 --- a/vendor/github.com/containerd/containerd/runtime/linux/proc/init_state.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init_state.go @@ -209,7 +209,7 @@ func (s *createdCheckpointState) Start(ctx context.Context) error { s.opts.ConsoleSocket = socket } - if _, err := s.p.runtime.Restore(ctx, p.id, p.bundle, s.opts); err != nil { + if _, err := s.p.runtime.Restore(ctx, p.id, p.Bundle, s.opts); err != nil { return p.runtimeError(err, "OCI runtime restore failed") } if sio.Stdin != "" { @@ -226,7 +226,7 @@ func (s *createdCheckpointState) Start(ctx context.Context) error { if err != nil { return errors.Wrap(err, "failed to retrieve console master") } - console, err = p.platform.CopyConsole(ctx, console, sio.Stdin, sio.Stdout, sio.Stderr, &p.wg, ©WaitGroup) + console, err = p.Platform.CopyConsole(ctx, console, sio.Stdin, sio.Stdout, sio.Stderr, &p.wg, ©WaitGroup) if err != nil { return errors.Wrap(err, "failed to start console copy") } diff --git a/vendor/github.com/containerd/containerd/runtime/linux/proc/io.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go similarity index 100% rename from vendor/github.com/containerd/containerd/runtime/linux/proc/io.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go diff --git a/vendor/github.com/containerd/containerd/runtime/linux/proc/process.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/process.go similarity index 100% rename from vendor/github.com/containerd/containerd/runtime/linux/proc/process.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/proc/process.go diff --git a/vendor/github.com/containerd/containerd/runtime/linux/proc/types.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/types.go similarity index 86% rename from vendor/github.com/containerd/containerd/runtime/linux/proc/types.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/proc/types.go index 0cc123fd81..2bea98dc8e 100644 --- a/vendor/github.com/containerd/containerd/runtime/linux/proc/types.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/types.go @@ -55,6 +55,11 @@ type ExecConfig struct { // CheckpointConfig holds task checkpoint configuration type CheckpointConfig struct { - Path string - Options *google_protobuf.Any + Path string + Exit bool + AllowOpenTCP bool + AllowExternalUnixSockets bool + AllowTerminal bool + FileLocks bool + EmptyNamespaces []string } diff --git a/vendor/github.com/containerd/containerd/runtime/linux/proc/utils.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/utils.go similarity index 100% rename from vendor/github.com/containerd/containerd/runtime/linux/proc/utils.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/proc/utils.go diff --git a/vendor/github.com/containerd/containerd/runtime/linux/process.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/process.go similarity index 90% rename from vendor/github.com/containerd/containerd/runtime/linux/process.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/process.go index 02cccd206b..2c60b674a9 100644 --- a/vendor/github.com/containerd/containerd/runtime/linux/process.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/process.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd/api/types/task" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/runtime" - shim "github.com/containerd/containerd/runtime/shim/v1" + shim "github.com/containerd/containerd/runtime/v1/shim/v1" "github.com/containerd/ttrpc" "github.com/pkg/errors" ) @@ -149,3 +149,18 @@ func (p *Process) Wait(ctx context.Context) (*runtime.Exit, error) { Status: r.ExitStatus, }, nil } + +// Delete the process and return the exit status +func (p *Process) Delete(ctx context.Context) (*runtime.Exit, error) { + r, err := p.t.shim.DeleteProcess(ctx, &shim.DeleteProcessRequest{ + ID: p.id, + }) + if err != nil { + return nil, errdefs.FromGRPC(err) + } + return &runtime.Exit{ + Status: r.ExitStatus, + Timestamp: r.ExitedAt, + Pid: r.Pid, + }, nil +} diff --git a/vendor/github.com/containerd/containerd/runtime/linux/runtime.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go similarity index 81% rename from vendor/github.com/containerd/containerd/runtime/linux/runtime.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go index 5dcbca56e7..6c08fe9781 100644 --- a/vendor/github.com/containerd/containerd/runtime/linux/runtime.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go @@ -40,9 +40,9 @@ import ( "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/plugin" "github.com/containerd/containerd/runtime" - "github.com/containerd/containerd/runtime/linux/proc" "github.com/containerd/containerd/runtime/linux/runctypes" - shim "github.com/containerd/containerd/runtime/shim/v1" + "github.com/containerd/containerd/runtime/v1/linux/proc" + shim "github.com/containerd/containerd/runtime/v1/shim/v1" runc "github.com/containerd/go-runc" "github.com/containerd/typeurl" ptypes "github.com/gogo/protobuf/types" @@ -69,7 +69,6 @@ func init() { ID: "linux", InitFn: New, Requires: []plugin.Type{ - plugin.TaskMonitorPlugin, plugin.MetadataPlugin, }, Config: &Config{ @@ -105,10 +104,6 @@ func New(ic *plugin.InitContext) (interface{}, error) { if err := os.MkdirAll(ic.State, 0711); err != nil { return nil, err } - monitor, err := ic.Get(plugin.TaskMonitorPlugin) - if err != nil { - return nil, err - } m, err := ic.Get(plugin.MetadataPlugin) if err != nil { return nil, err @@ -117,7 +112,6 @@ func New(ic *plugin.InitContext) (interface{}, error) { r := &Runtime{ root: ic.Root, state: ic.State, - monitor: monitor.(runtime.TaskMonitor), tasks: runtime.NewTaskList(), db: m.(*metadata.DB), address: ic.Address, @@ -128,8 +122,6 @@ func New(ic *plugin.InitContext) (interface{}, error) { if err != nil { return nil, err } - - // TODO: need to add the tasks to the monitor for _, t := range tasks { if err := r.tasks.AddWithNamespace(t.namespace, t); err != nil { return nil, err @@ -144,10 +136,9 @@ type Runtime struct { state string address string - monitor runtime.TaskMonitor - tasks *runtime.TaskList - db *metadata.DB - events *exchange.Exchange + tasks *runtime.TaskList + db *metadata.DB + events *exchange.Exchange config *Config } @@ -189,8 +180,8 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts shimopt := ShimLocal(r.config, r.events) if !r.config.NoShim { var cgroup string - if opts.Options != nil { - v, err := typeurl.UnmarshalAny(opts.Options) + if opts.TaskOptions != nil { + v, err := typeurl.UnmarshalAny(opts.TaskOptions) if err != nil { return nil, err } @@ -205,14 +196,6 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts } lc := t.(*Task) - // Stop the monitor - if err := r.monitor.Stop(lc); err != nil { - log.G(ctx).WithError(err).WithFields(logrus.Fields{ - "id": id, - "namespace": namespace, - }).Warn("failed to stop monitor") - } - log.G(ctx).WithFields(logrus.Fields{ "id": id, "namespace": namespace, @@ -252,7 +235,7 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts Stderr: opts.IO.Stderr, Terminal: opts.IO.Terminal, Checkpoint: opts.Checkpoint, - Options: opts.Options, + Options: opts.TaskOptions, } for _, m := range opts.Rootfs { sopts.Rootfs = append(sopts.Rootfs, &types.Mount{ @@ -265,24 +248,14 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts if err != nil { return nil, errdefs.FromGRPC(err) } - t, err := newTask(id, namespace, int(cr.Pid), s, r.monitor, r.events, - proc.NewRunc(ropts.RuntimeRoot, sopts.Bundle, namespace, rt, ropts.CriuPath, ropts.SystemdCgroup)) + t, err := newTask(id, namespace, int(cr.Pid), s, r.events, + proc.NewRunc(ropts.RuntimeRoot, sopts.Bundle, namespace, rt, ropts.CriuPath, ropts.SystemdCgroup), r.tasks, bundle) if err != nil { return nil, err } if err := r.tasks.Add(ctx, t); err != nil { return nil, err } - // after the task is created, add it to the monitor if it has a cgroup - // this can be different on a checkpoint/restore - if t.cg != nil { - if err = r.monitor.Monitor(t); err != nil { - if _, err := r.Delete(ctx, t); err != nil { - log.G(ctx).WithError(err).Error("deleting task after failed monitor") - } - return nil, err - } - } r.events.Publish(ctx, runtime.TaskCreateEventTopic, &eventstypes.TaskCreate{ ContainerID: sopts.ID, Bundle: sopts.Bundle, @@ -300,56 +273,9 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts return t, nil } -// Delete a task removing all on disk state -func (r *Runtime) Delete(ctx context.Context, c runtime.Task) (*runtime.Exit, error) { - namespace, err := namespaces.NamespaceRequired(ctx) - if err != nil { - return nil, err - } - lc, ok := c.(*Task) - if !ok { - return nil, fmt.Errorf("task cannot be cast as *linux.Task") - } - if err := r.monitor.Stop(lc); err != nil { - return nil, err - } - bundle := loadBundle( - lc.id, - filepath.Join(r.state, namespace, lc.id), - filepath.Join(r.root, namespace, lc.id), - ) - - rsp, err := lc.shim.Delete(ctx, empty) - if err != nil { - if cerr := r.cleanupAfterDeadShim(ctx, bundle, namespace, c.ID(), lc.pid); cerr != nil { - log.G(ctx).WithError(err).Error("unable to cleanup task") - } - return nil, errdefs.FromGRPC(err) - } - r.tasks.Delete(ctx, lc.id) - if err := lc.shim.KillShim(ctx); err != nil { - log.G(ctx).WithError(err).Error("failed to kill shim") - } - - if err := bundle.Delete(); err != nil { - log.G(ctx).WithError(err).Error("failed to delete bundle") - } - r.events.Publish(ctx, runtime.TaskDeleteEventTopic, &eventstypes.TaskDelete{ - ContainerID: lc.id, - ExitStatus: rsp.ExitStatus, - ExitedAt: rsp.ExitedAt, - Pid: rsp.Pid, - }) - return &runtime.Exit{ - Status: rsp.ExitStatus, - Timestamp: rsp.ExitedAt, - Pid: rsp.Pid, - }, nil -} - // Tasks returns all tasks known to the runtime -func (r *Runtime) Tasks(ctx context.Context) ([]runtime.Task, error) { - return r.tasks.GetAll(ctx) +func (r *Runtime) Tasks(ctx context.Context, all bool) ([]runtime.Task, error) { + return r.tasks.GetAll(ctx, all) } func (r *Runtime) restoreTasks(ctx context.Context) ([]*Task, error) { @@ -422,8 +348,8 @@ func (r *Runtime) loadTasks(ctx context.Context, ns string) ([]*Task, error) { continue } - t, err := newTask(id, ns, pid, s, r.monitor, r.events, - proc.NewRunc(ropts.RuntimeRoot, bundle.path, ns, ropts.Runtime, ropts.CriuPath, ropts.SystemdCgroup)) + t, err := newTask(id, ns, pid, s, r.events, + proc.NewRunc(ropts.RuntimeRoot, bundle.path, ns, ropts.Runtime, ropts.CriuPath, ropts.SystemdCgroup), r.tasks, bundle) if err != nil { log.G(ctx).WithError(err).Error("loading task type") continue diff --git a/vendor/github.com/containerd/containerd/runtime/linux/task.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/task.go similarity index 85% rename from vendor/github.com/containerd/containerd/runtime/linux/task.go rename to vendor/github.com/containerd/containerd/runtime/v1/linux/task.go index 43c93eaba8..e90110997e 100644 --- a/vendor/github.com/containerd/containerd/runtime/linux/task.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/task.go @@ -28,11 +28,13 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/events/exchange" "github.com/containerd/containerd/identifiers" + "github.com/containerd/containerd/log" "github.com/containerd/containerd/runtime" - "github.com/containerd/containerd/runtime/shim/client" - shim "github.com/containerd/containerd/runtime/shim/v1" + "github.com/containerd/containerd/runtime/v1/shim/client" + shim "github.com/containerd/containerd/runtime/v1/shim/v1" runc "github.com/containerd/go-runc" "github.com/containerd/ttrpc" + "github.com/containerd/typeurl" "github.com/gogo/protobuf/types" "github.com/pkg/errors" ) @@ -45,12 +47,12 @@ type Task struct { shim *client.Client namespace string cg cgroups.Cgroup - monitor runtime.TaskMonitor events *exchange.Exchange - runtime *runc.Runc + tasks *runtime.TaskList + bundle *bundle } -func newTask(id, namespace string, pid int, shim *client.Client, monitor runtime.TaskMonitor, events *exchange.Exchange, runtime *runc.Runc) (*Task, error) { +func newTask(id, namespace string, pid int, shim *client.Client, events *exchange.Exchange, runtime *runc.Runc, list *runtime.TaskList, bundle *bundle) (*Task, error) { var ( err error cg cgroups.Cgroup @@ -67,9 +69,9 @@ func newTask(id, namespace string, pid int, shim *client.Client, monitor runtime shim: shim, namespace: namespace, cg: cg, - monitor: monitor, events: events, - runtime: runtime, + tasks: list, + bundle: bundle, }, nil } @@ -78,13 +80,35 @@ func (t *Task) ID() string { return t.id } -// Info returns task information about the runtime and namespace -func (t *Task) Info() runtime.TaskInfo { - return runtime.TaskInfo{ - ID: t.id, - Runtime: pluginID, - Namespace: t.namespace, +// Namespace of the task +func (t *Task) Namespace() string { + return t.namespace +} + +// Delete the task and return the exit status +func (t *Task) Delete(ctx context.Context) (*runtime.Exit, error) { + rsp, err := t.shim.Delete(ctx, empty) + if err != nil { + return nil, errdefs.FromGRPC(err) } + t.tasks.Delete(ctx, t.id) + if err := t.shim.KillShim(ctx); err != nil { + log.G(ctx).WithError(err).Error("failed to kill shim") + } + if err := t.bundle.Delete(); err != nil { + log.G(ctx).WithError(err).Error("failed to delete bundle") + } + t.events.Publish(ctx, runtime.TaskDeleteEventTopic, &eventstypes.TaskDelete{ + ContainerID: t.id, + ExitStatus: rsp.ExitStatus, + ExitedAt: rsp.ExitedAt, + Pid: rsp.Pid, + }) + return &runtime.Exit{ + Status: rsp.ExitStatus, + Timestamp: rsp.ExitedAt, + Pid: rsp.Pid, + }, nil } // Start the task @@ -107,9 +131,6 @@ func (t *Task) Start(ctx context.Context) error { t.mu.Lock() t.cg = cg t.mu.Unlock() - if err := t.monitor.Monitor(t); err != nil { - return err - } } t.events.Publish(ctx, runtime.TaskStartEventTopic, &eventstypes.TaskStart{ ContainerID: t.id, @@ -270,21 +291,6 @@ func (t *Task) Checkpoint(ctx context.Context, path string, options *types.Any) return nil } -// DeleteProcess removes the provided process from the task and deletes all on disk state -func (t *Task) DeleteProcess(ctx context.Context, id string) (*runtime.Exit, error) { - r, err := t.shim.DeleteProcess(ctx, &shim.DeleteProcessRequest{ - ID: id, - }) - if err != nil { - return nil, errdefs.FromGRPC(err) - } - return &runtime.Exit{ - Status: r.ExitStatus, - Timestamp: r.ExitedAt, - Pid: r.Pid, - }, nil -} - // Update changes runtime information of a running task func (t *Task) Update(ctx context.Context, resources *types.Any) error { if _, err := t.shim.Update(ctx, &shim.UpdateTaskRequest{ @@ -307,8 +313,8 @@ func (t *Task) Process(ctx context.Context, id string) (runtime.Process, error) return p, nil } -// Metrics returns runtime specific system level metric information for the task -func (t *Task) Metrics(ctx context.Context) (interface{}, error) { +// Stats returns runtime specific system level metric information for the task +func (t *Task) Stats(ctx context.Context) (*types.Any, error) { t.mu.Lock() defer t.mu.Unlock() if t.cg == nil { @@ -318,7 +324,7 @@ func (t *Task) Metrics(ctx context.Context) (interface{}, error) { if err != nil { return nil, err } - return stats, nil + return typeurl.MarshalAny(stats) } // Cgroup returns the underlying cgroup for a linux task diff --git a/vendor/github.com/containerd/containerd/runtime/shim/client/client.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/client/client.go similarity index 98% rename from vendor/github.com/containerd/containerd/runtime/shim/client/client.go rename to vendor/github.com/containerd/containerd/runtime/v1/shim/client/client.go index 009ccc9398..015d88c2dc 100644 --- a/vendor/github.com/containerd/containerd/runtime/shim/client/client.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/shim/client/client.go @@ -37,8 +37,8 @@ import ( "github.com/containerd/containerd/events" "github.com/containerd/containerd/log" - "github.com/containerd/containerd/runtime/shim" - shimapi "github.com/containerd/containerd/runtime/shim/v1" + "github.com/containerd/containerd/runtime/v1/shim" + shimapi "github.com/containerd/containerd/runtime/v1/shim/v1" "github.com/containerd/containerd/sys" ptypes "github.com/gogo/protobuf/types" ) diff --git a/vendor/github.com/containerd/containerd/runtime/shim/client/client_linux.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/client/client_linux.go similarity index 100% rename from vendor/github.com/containerd/containerd/runtime/shim/client/client_linux.go rename to vendor/github.com/containerd/containerd/runtime/v1/shim/client/client_linux.go diff --git a/vendor/github.com/containerd/containerd/runtime/shim/client/client_unix.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/client/client_unix.go similarity index 100% rename from vendor/github.com/containerd/containerd/runtime/shim/client/client_unix.go rename to vendor/github.com/containerd/containerd/runtime/v1/shim/client/client_unix.go diff --git a/vendor/github.com/containerd/containerd/runtime/shim/local.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/local.go similarity index 98% rename from vendor/github.com/containerd/containerd/runtime/shim/local.go rename to vendor/github.com/containerd/containerd/runtime/v1/shim/local.go index 8206b869c3..97f652c775 100644 --- a/vendor/github.com/containerd/containerd/runtime/shim/local.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/shim/local.go @@ -23,7 +23,7 @@ import ( "path/filepath" "github.com/containerd/containerd/mount" - shimapi "github.com/containerd/containerd/runtime/shim/v1" + shimapi "github.com/containerd/containerd/runtime/v1/shim/v1" ptypes "github.com/gogo/protobuf/types" ) diff --git a/vendor/github.com/containerd/containerd/runtime/shim/reaper.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/reaper.go similarity index 100% rename from vendor/github.com/containerd/containerd/runtime/shim/reaper.go rename to vendor/github.com/containerd/containerd/runtime/v1/shim/reaper.go diff --git a/vendor/github.com/containerd/containerd/runtime/shim/service.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/service.go similarity index 84% rename from vendor/github.com/containerd/containerd/runtime/shim/service.go rename to vendor/github.com/containerd/containerd/runtime/v1/shim/service.go index 379e5cf5bc..c0e7c868a6 100644 --- a/vendor/github.com/containerd/containerd/runtime/shim/service.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/shim/service.go @@ -22,6 +22,7 @@ import ( "context" "fmt" "os" + "path/filepath" "sync" "github.com/containerd/console" @@ -30,12 +31,13 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/events" "github.com/containerd/containerd/log" + "github.com/containerd/containerd/mount" "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/runtime" - "github.com/containerd/containerd/runtime/linux/proc" "github.com/containerd/containerd/runtime/linux/runctypes" rproc "github.com/containerd/containerd/runtime/proc" - shimapi "github.com/containerd/containerd/runtime/shim/v1" + "github.com/containerd/containerd/runtime/v1/linux/proc" + shimapi "github.com/containerd/containerd/runtime/v1/shim/v1" runc "github.com/containerd/go-runc" "github.com/containerd/typeurl" ptypes "github.com/gogo/protobuf/types" @@ -108,7 +110,7 @@ type Service struct { } // Create a new initial process and container with the underlying OCI runtime -func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (*shimapi.CreateTaskResponse, error) { +func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (_ *shimapi.CreateTaskResponse, err error) { s.mu.Lock() defer s.mu.Unlock() @@ -121,7 +123,39 @@ func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (*sh Options: m.Options, }) } - process, err := proc.New( + + config := &proc.CreateConfig{ + ID: r.ID, + Bundle: r.Bundle, + Runtime: r.Runtime, + Rootfs: mounts, + Terminal: r.Terminal, + Stdin: r.Stdin, + Stdout: r.Stdout, + Stderr: r.Stderr, + Checkpoint: r.Checkpoint, + ParentCheckpoint: r.ParentCheckpoint, + Options: r.Options, + } + rootfs := filepath.Join(r.Bundle, "rootfs") + defer func() { + if err != nil { + if err2 := mount.UnmountAll(rootfs, 0); err2 != nil { + log.G(ctx).WithError(err2).Warn("Failed to cleanup rootfs mount") + } + } + }() + for _, rm := range mounts { + m := &mount.Mount{ + Type: rm.Type, + Source: rm.Source, + Options: rm.Options, + } + if err := m.Mount(rootfs); err != nil { + return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m) + } + } + process, err := newInit( ctx, s.config.Path, s.config.WorkDir, @@ -130,23 +164,14 @@ func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (*sh s.config.Criu, s.config.SystemdCgroup, s.platform, - &proc.CreateConfig{ - ID: r.ID, - Bundle: r.Bundle, - Runtime: r.Runtime, - Rootfs: mounts, - Terminal: r.Terminal, - Stdin: r.Stdin, - Stdout: r.Stdout, - Stderr: r.Stderr, - Checkpoint: r.Checkpoint, - ParentCheckpoint: r.ParentCheckpoint, - Options: r.Options, - }, + config, ) if err != nil { return nil, errdefs.ToGRPC(err) } + if err := process.Create(ctx, config); err != nil { + return nil, errdefs.ToGRPC(err) + } // save the main task id and bundle to the shim for additional requests s.id = r.ID s.bundle = r.Bundle @@ -414,9 +439,22 @@ func (s *Service) Checkpoint(ctx context.Context, r *shimapi.CheckpointTaskReque if p == nil { return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "container must be created") } + var options runctypes.CheckpointOptions + if r.Options != nil { + v, err := typeurl.UnmarshalAny(r.Options) + if err != nil { + return nil, err + } + options = *v.(*runctypes.CheckpointOptions) + } if err := p.(*proc.Init).Checkpoint(ctx, &proc.CheckpointConfig{ - Path: r.Path, - Options: r.Options, + Path: r.Path, + Exit: options.Exit, + AllowOpenTCP: options.OpenTcp, + AllowExternalUnixSockets: options.ExternalUnixSockets, + AllowTerminal: options.Terminal, + FileLocks: options.FileLocks, + EmptyNamespaces: options.EmptyNamespaces, }); err != nil { return nil, errdefs.ToGRPC(err) } @@ -545,3 +583,32 @@ func getTopic(ctx context.Context, e interface{}) string { } return runtime.TaskUnknownTopic } + +func newInit(ctx context.Context, path, workDir, runtimeRoot, namespace, criu string, systemdCgroup bool, platform rproc.Platform, r *proc.CreateConfig) (*proc.Init, error) { + var options runctypes.CreateOptions + if r.Options != nil { + v, err := typeurl.UnmarshalAny(r.Options) + if err != nil { + return nil, err + } + options = *v.(*runctypes.CreateOptions) + } + + rootfs := filepath.Join(path, "rootfs") + runtime := proc.NewRunc(runtimeRoot, path, namespace, r.Runtime, criu, systemdCgroup) + p := proc.New(r.ID, runtime, rproc.Stdio{ + Stdin: r.Stdin, + Stdout: r.Stdout, + Stderr: r.Stderr, + Terminal: r.Terminal, + }) + p.Bundle = r.Bundle + p.Platform = platform + p.Rootfs = rootfs + p.WorkDir = workDir + p.IoUID = int(options.IoUid) + p.IoGID = int(options.IoGid) + p.NoPivotRoot = options.NoPivotRoot + p.NoNewKeyring = options.NoNewKeyring + return p, nil +} diff --git a/vendor/github.com/containerd/containerd/runtime/shim/service_linux.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go similarity index 100% rename from vendor/github.com/containerd/containerd/runtime/shim/service_linux.go rename to vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go diff --git a/vendor/github.com/containerd/containerd/runtime/shim/service_unix.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/service_unix.go similarity index 100% rename from vendor/github.com/containerd/containerd/runtime/shim/service_unix.go rename to vendor/github.com/containerd/containerd/runtime/v1/shim/service_unix.go diff --git a/vendor/github.com/containerd/containerd/runtime/shim/v1/doc.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/v1/doc.go similarity index 100% rename from vendor/github.com/containerd/containerd/runtime/shim/v1/doc.go rename to vendor/github.com/containerd/containerd/runtime/v1/shim/v1/doc.go diff --git a/vendor/github.com/containerd/containerd/runtime/shim/v1/shim.pb.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/v1/shim.pb.go similarity index 93% rename from vendor/github.com/containerd/containerd/runtime/shim/v1/shim.pb.go rename to vendor/github.com/containerd/containerd/runtime/v1/shim/v1/shim.pb.go index e4dae343d5..9bd2889ba7 100644 --- a/vendor/github.com/containerd/containerd/runtime/shim/v1/shim.pb.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/shim/v1/shim.pb.go @@ -1,11 +1,11 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: github.com/containerd/containerd/runtime/shim/v1/shim.proto +// source: github.com/containerd/containerd/runtime/v1/shim/v1/shim.proto /* Package shim is a generated protocol buffer package. It is generated from these files: - github.com/containerd/containerd/runtime/shim/v1/shim.proto + github.com/containerd/containerd/runtime/v1/shim/v1/shim.proto It has these top-level messages: CreateTaskRequest @@ -4352,80 +4352,80 @@ var ( ) func init() { - proto.RegisterFile("github.com/containerd/containerd/runtime/shim/v1/shim.proto", fileDescriptorShim) + proto.RegisterFile("github.com/containerd/containerd/runtime/v1/shim/v1/shim.proto", fileDescriptorShim) } var fileDescriptorShim = []byte{ - // 1135 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x4d, 0x6f, 0xdb, 0x46, - 0x13, 0x36, 0x69, 0x7d, 0x8e, 0x22, 0xbf, 0xf6, 0xbe, 0x8e, 0xcb, 0x28, 0x80, 0x2c, 0x10, 0x68, - 0xe0, 0xa2, 0x08, 0x55, 0xcb, 0x6d, 0xd2, 0x36, 0x40, 0x00, 0xdb, 0x09, 0x0a, 0xa3, 0x0d, 0x6c, - 0xd0, 0x4e, 0x13, 0xb4, 0x28, 0x0c, 0x5a, 0x5c, 0x4b, 0x0b, 0x4b, 0x24, 0xc3, 0x5d, 0xba, 0x76, - 0x4f, 0x3d, 0xf5, 0xdc, 0x9f, 0xd3, 0x9f, 0xe0, 0x43, 0x0e, 0x3d, 0xf6, 0x94, 0x36, 0xba, 0xf7, - 0x3f, 0x14, 0xfb, 0x21, 0x93, 0x92, 0xcc, 0x90, 0xf2, 0xc5, 0xe2, 0xec, 0x3e, 0xb3, 0x3b, 0x3b, - 0xcf, 0xb3, 0x33, 0x6b, 0x78, 0xd2, 0x23, 0xac, 0x1f, 0x9d, 0x58, 0x5d, 0x7f, 0xd8, 0xee, 0xfa, - 0x1e, 0x73, 0x88, 0x87, 0x43, 0x37, 0xf9, 0x19, 0x46, 0x1e, 0x23, 0x43, 0xdc, 0xa6, 0x7d, 0x32, - 0x6c, 0x9f, 0x6f, 0x8a, 0x5f, 0x2b, 0x08, 0x7d, 0xe6, 0xa3, 0x56, 0x0c, 0xb3, 0x14, 0xcc, 0x1a, - 0x10, 0x2f, 0xba, 0xb0, 0x04, 0xe8, 0x7c, 0xb3, 0x71, 0xaf, 0xe7, 0xfb, 0xbd, 0x01, 0x6e, 0x0b, - 0xfc, 0x49, 0x74, 0xda, 0x76, 0xbc, 0x4b, 0xe9, 0xdc, 0xb8, 0x3f, 0x3d, 0x85, 0x87, 0x01, 0x1b, - 0x4f, 0xae, 0xf6, 0xfc, 0x9e, 0x2f, 0x3e, 0xdb, 0xfc, 0x4b, 0x8d, 0xae, 0x4f, 0xbb, 0xf0, 0x1d, - 0x29, 0x73, 0x86, 0x81, 0x02, 0x3c, 0xca, 0x3c, 0x8d, 0x13, 0x90, 0x36, 0xbb, 0x0c, 0x30, 0x6d, - 0x0f, 0xfd, 0xc8, 0x63, 0xca, 0xef, 0xeb, 0x39, 0xfc, 0x98, 0x43, 0xcf, 0xc4, 0x1f, 0xe9, 0x6b, - 0xfe, 0xab, 0xc3, 0xca, 0x6e, 0x88, 0x1d, 0x86, 0x8f, 0x1c, 0x7a, 0x66, 0xe3, 0x37, 0x11, 0xa6, - 0x0c, 0xad, 0x81, 0x4e, 0x5c, 0x43, 0x6b, 0x69, 0x1b, 0xd5, 0x9d, 0xd2, 0xe8, 0xdd, 0xba, 0xbe, - 0xf7, 0xcc, 0xd6, 0x89, 0x8b, 0xd6, 0xa0, 0x74, 0x12, 0x79, 0xee, 0x00, 0x1b, 0x3a, 0x9f, 0xb3, - 0x95, 0x85, 0x0c, 0x28, 0xab, 0x0c, 0x1a, 0x8b, 0x62, 0x62, 0x6c, 0xa2, 0x36, 0x94, 0x42, 0xdf, - 0x67, 0xa7, 0xd4, 0x28, 0xb4, 0x16, 0x37, 0x6a, 0x9d, 0x8f, 0xac, 0x44, 0xd6, 0x45, 0x48, 0xd6, - 0x0b, 0x7e, 0x14, 0x5b, 0xc1, 0x50, 0x03, 0x2a, 0x0c, 0x87, 0x43, 0xe2, 0x39, 0x03, 0xa3, 0xd8, - 0xd2, 0x36, 0x2a, 0xf6, 0xb5, 0x8d, 0x56, 0xa1, 0x48, 0x99, 0x4b, 0x3c, 0xa3, 0x24, 0x36, 0x91, - 0x06, 0x0f, 0x8a, 0x32, 0xd7, 0x8f, 0x98, 0x51, 0x96, 0x41, 0x49, 0x4b, 0x8d, 0xe3, 0x30, 0x34, - 0x2a, 0xd7, 0xe3, 0x38, 0x0c, 0x51, 0x13, 0xa0, 0xdb, 0xc7, 0xdd, 0xb3, 0xc0, 0x27, 0x1e, 0x33, - 0xaa, 0x62, 0x2e, 0x31, 0x82, 0x3e, 0x85, 0x95, 0xc0, 0x09, 0xb1, 0xc7, 0x8e, 0x13, 0x30, 0x10, - 0xb0, 0x65, 0x39, 0xb1, 0x1b, 0x83, 0x2d, 0x28, 0xfb, 0x01, 0x23, 0xbe, 0x47, 0x8d, 0x5a, 0x4b, - 0xdb, 0xa8, 0x75, 0x56, 0x2d, 0x49, 0xb3, 0x35, 0xa6, 0xd9, 0xda, 0xf6, 0x2e, 0xed, 0x31, 0xc8, - 0x7c, 0x00, 0x28, 0x99, 0x6e, 0x1a, 0xf8, 0x1e, 0xc5, 0x68, 0x19, 0x16, 0x03, 0x95, 0xf0, 0xba, - 0xcd, 0x3f, 0xcd, 0xdf, 0x34, 0x58, 0x7a, 0x86, 0x07, 0x98, 0xe1, 0x74, 0x10, 0x5a, 0x87, 0x1a, - 0xbe, 0x20, 0xec, 0x98, 0x32, 0x87, 0x45, 0x54, 0x70, 0x52, 0xb7, 0x81, 0x0f, 0x1d, 0x8a, 0x11, - 0xb4, 0x0d, 0x55, 0x6e, 0x61, 0xf7, 0xd8, 0x61, 0x82, 0x99, 0x5a, 0xa7, 0x31, 0x13, 0xdf, 0xd1, - 0x58, 0x86, 0x3b, 0x95, 0xab, 0x77, 0xeb, 0x0b, 0xbf, 0xff, 0xbd, 0xae, 0xd9, 0x15, 0xe9, 0xb6, - 0xcd, 0x4c, 0x0b, 0x56, 0x65, 0x1c, 0x07, 0xa1, 0xdf, 0xc5, 0x94, 0x66, 0x48, 0xc4, 0xfc, 0x43, - 0x03, 0xf4, 0xfc, 0x02, 0x77, 0xf3, 0xc1, 0x27, 0xe8, 0xd6, 0xd3, 0xe8, 0x5e, 0xbc, 0x99, 0xee, - 0x42, 0x0a, 0xdd, 0xc5, 0x09, 0xba, 0x37, 0xa0, 0x40, 0x03, 0xdc, 0x15, 0x9a, 0x49, 0xa3, 0x47, - 0x20, 0xcc, 0xbb, 0xf0, 0xff, 0x89, 0xc8, 0x65, 0xde, 0xcd, 0xd7, 0xb0, 0x6c, 0x63, 0x4a, 0x7e, - 0xc1, 0x07, 0xec, 0x32, 0xeb, 0x38, 0xab, 0x50, 0xfc, 0x99, 0xb8, 0xac, 0xaf, 0xb8, 0x90, 0x06, - 0x0f, 0xad, 0x8f, 0x49, 0xaf, 0x2f, 0x39, 0xa8, 0xdb, 0xca, 0x32, 0x1f, 0xc0, 0x1d, 0x4e, 0x14, - 0xce, 0xca, 0xe9, 0x5b, 0x1d, 0xea, 0x0a, 0xa8, 0xb4, 0x30, 0xef, 0x05, 0x55, 0xda, 0x59, 0x8c, - 0xb5, 0xb3, 0xc5, 0xd3, 0x25, 0x64, 0xc3, 0xd3, 0xb8, 0xd4, 0xb9, 0x9f, 0xbc, 0x98, 0xe7, 0x9b, - 0xea, 0x6e, 0x4a, 0x1d, 0xd9, 0x0a, 0x1a, 0x33, 0x52, 0xbc, 0x99, 0x91, 0x52, 0x0a, 0x23, 0xe5, - 0x09, 0x46, 0x92, 0x9c, 0x57, 0xa6, 0x38, 0x9f, 0x92, 0x74, 0xf5, 0xc3, 0x92, 0x86, 0x5b, 0x49, - 0x7a, 0x1f, 0x6a, 0xdf, 0x92, 0xc1, 0x20, 0x47, 0xb1, 0xa3, 0xa4, 0x37, 0x16, 0x66, 0xdd, 0x56, - 0x16, 0xcf, 0xa5, 0x33, 0x18, 0x88, 0x5c, 0x56, 0x6c, 0xfe, 0x69, 0x3e, 0x85, 0xa5, 0xdd, 0x81, - 0x4f, 0xf1, 0xde, 0x7e, 0x0e, 0x7d, 0xc8, 0x04, 0x4a, 0xad, 0x4b, 0xc3, 0xfc, 0x04, 0xfe, 0xf7, - 0x1d, 0xa1, 0xec, 0x80, 0xb8, 0x99, 0xd7, 0xcb, 0x86, 0xe5, 0x18, 0xaa, 0xc4, 0xf0, 0x14, 0xaa, - 0x81, 0xd4, 0x2c, 0xa6, 0x86, 0x26, 0xca, 0x6c, 0xeb, 0x46, 0x36, 0x95, 0xb2, 0xf7, 0xbc, 0x53, - 0xdf, 0x8e, 0x5d, 0xcc, 0x1f, 0xe1, 0x6e, 0x5c, 0xd1, 0x92, 0x6d, 0x00, 0x41, 0x21, 0x70, 0x58, - 0x5f, 0x86, 0x61, 0x8b, 0xef, 0x64, 0xc1, 0xd3, 0xf3, 0x14, 0xbc, 0x87, 0xb0, 0x7c, 0xd8, 0x27, - 0x43, 0xb1, 0xe7, 0x38, 0xe0, 0x7b, 0x50, 0xe1, 0x2d, 0xf6, 0x38, 0x2e, 0x67, 0x65, 0x6e, 0x1f, - 0x10, 0xd7, 0xfc, 0x06, 0x56, 0x5e, 0x06, 0xee, 0x54, 0x3b, 0xea, 0x40, 0x35, 0xc4, 0xd4, 0x8f, - 0xc2, 0xae, 0x38, 0x60, 0xfa, 0xae, 0x31, 0x4c, 0xdd, 0xad, 0x90, 0x65, 0x25, 0xf4, 0x2b, 0x71, - 0xb5, 0x38, 0x2e, 0xe3, 0x6a, 0xa9, 0x2b, 0xa4, 0xc7, 0x35, 0xfa, 0x63, 0xa8, 0xbd, 0x72, 0x48, - 0xe6, 0x0e, 0x21, 0xdc, 0x91, 0x30, 0xb5, 0xc1, 0x94, 0xc4, 0xb5, 0x0f, 0x4b, 0x5c, 0xbf, 0x8d, - 0xc4, 0x3b, 0x6f, 0x6b, 0x50, 0xe0, 0x69, 0x47, 0x7d, 0x28, 0x8a, 0xca, 0x81, 0x2c, 0x2b, 0xeb, - 0xb9, 0x63, 0x25, 0x6b, 0x51, 0xa3, 0x9d, 0x1b, 0xaf, 0x8e, 0x45, 0xa1, 0x24, 0x3b, 0x1b, 0xda, - 0xca, 0x76, 0x9d, 0x79, 0x72, 0x34, 0x3e, 0x9f, 0xcf, 0x49, 0x6d, 0x2a, 0x8f, 0x17, 0xb2, 0x9c, - 0xc7, 0xbb, 0x96, 0x43, 0xce, 0xe3, 0x25, 0x64, 0x61, 0x43, 0x49, 0xf6, 0x41, 0xb4, 0x36, 0xc3, - 0xc5, 0x73, 0xfe, 0xf6, 0x6b, 0x7c, 0x96, 0xbd, 0xe4, 0x54, 0x47, 0xbf, 0x84, 0xfa, 0x44, 0x6f, - 0x45, 0x8f, 0xf2, 0x2e, 0x31, 0xd9, 0x5d, 0x6f, 0xb1, 0xf5, 0x1b, 0xa8, 0x8c, 0xeb, 0x08, 0xda, - 0xcc, 0xf6, 0x9e, 0x2a, 0x4f, 0x8d, 0xce, 0x3c, 0x2e, 0x6a, 0xcb, 0xc7, 0x50, 0x3c, 0x70, 0x22, - 0x9a, 0x9e, 0xc0, 0x94, 0x71, 0xf4, 0x25, 0x94, 0x6c, 0x4c, 0xa3, 0xe1, 0xfc, 0x9e, 0x3f, 0x01, - 0x24, 0xde, 0x6a, 0x8f, 0x73, 0x48, 0xec, 0xa6, 0x3a, 0x98, 0xba, 0xfc, 0x0b, 0x28, 0xf0, 0x46, - 0x82, 0x1e, 0x66, 0x2f, 0x9c, 0x68, 0x38, 0xa9, 0xcb, 0x1d, 0x41, 0x81, 0xbf, 0x3f, 0x50, 0x8e, - 0xab, 0x30, 0xfb, 0xc2, 0x4a, 0x5d, 0xf5, 0x15, 0x54, 0xaf, 0x9f, 0x2f, 0x28, 0x07, 0x6f, 0xd3, - 0x6f, 0x9d, 0xd4, 0x85, 0x0f, 0xa1, 0xac, 0xba, 0x1e, 0xca, 0xa1, 0xbf, 0xc9, 0x06, 0x99, 0xba, - 0xe8, 0xf7, 0x50, 0x19, 0xb7, 0x8b, 0x54, 0xb6, 0x73, 0x1c, 0x62, 0xa6, 0xe5, 0xbc, 0x84, 0x92, - 0xec, 0x2b, 0x79, 0xaa, 0xd3, 0x4c, 0x07, 0x4a, 0x0d, 0x17, 0x43, 0x81, 0xd7, 0xf6, 0x3c, 0x0a, - 0x48, 0xb4, 0x8a, 0x86, 0x95, 0x17, 0x2e, 0xa3, 0xdf, 0xd9, 0xbf, 0x7a, 0xdf, 0x5c, 0xf8, 0xeb, - 0x7d, 0x73, 0xe1, 0xd7, 0x51, 0x53, 0xbb, 0x1a, 0x35, 0xb5, 0x3f, 0x47, 0x4d, 0xed, 0x9f, 0x51, - 0x53, 0xfb, 0xe1, 0x8b, 0x79, 0xff, 0x03, 0x7e, 0xc2, 0x7f, 0x5f, 0xeb, 0x27, 0x25, 0x71, 0x92, - 0xad, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x5b, 0x88, 0x3a, 0x56, 0x43, 0x0f, 0x00, 0x00, + // 1133 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x4f, 0x4f, 0x1b, 0x47, + 0x14, 0x67, 0x17, 0xff, 0x7d, 0x8e, 0x29, 0x4c, 0x09, 0xdd, 0x38, 0x92, 0xb1, 0x56, 0x6a, 0x44, + 0x55, 0x65, 0x5d, 0x4c, 0x95, 0xa4, 0xad, 0x84, 0x04, 0x24, 0xaa, 0x50, 0x1b, 0x05, 0x2d, 0xa4, + 0x89, 0x5a, 0x55, 0x68, 0xf1, 0x0e, 0xf6, 0x08, 0x7b, 0x67, 0xb3, 0x33, 0x4b, 0xa1, 0xa7, 0x9e, + 0x7a, 0xee, 0xc7, 0xe9, 0x47, 0xe0, 0x90, 0x43, 0x8f, 0x3d, 0xa5, 0x0d, 0xf7, 0x7e, 0x87, 0x6a, + 0xfe, 0x18, 0xaf, 0x6d, 0x36, 0xbb, 0x70, 0xc1, 0xfb, 0x66, 0x7e, 0x6f, 0xe6, 0xcd, 0xfb, 0xfd, + 0xe6, 0xbd, 0x01, 0x36, 0x7b, 0x84, 0xf7, 0xe3, 0x23, 0xa7, 0x4b, 0x87, 0xed, 0x2e, 0x0d, 0xb8, + 0x47, 0x02, 0x1c, 0xf9, 0xc9, 0xcf, 0x28, 0x0e, 0x38, 0x19, 0xe2, 0xf6, 0xe9, 0x7a, 0x9b, 0xf5, + 0xc9, 0x70, 0xf4, 0xeb, 0x84, 0x11, 0xe5, 0x14, 0xb5, 0xc6, 0x48, 0x47, 0x23, 0x9d, 0x01, 0x09, + 0xe2, 0x33, 0x47, 0x82, 0x4e, 0xd7, 0x1b, 0xf7, 0x7a, 0x94, 0xf6, 0x06, 0xb8, 0x2d, 0xf1, 0x47, + 0xf1, 0x71, 0xdb, 0x0b, 0xce, 0x95, 0x73, 0xe3, 0xfe, 0xf4, 0x14, 0x1e, 0x86, 0x7c, 0x34, 0xb9, + 0xdc, 0xa3, 0x3d, 0x2a, 0x3f, 0xdb, 0xe2, 0x4b, 0x8f, 0xae, 0x4e, 0xbb, 0x88, 0x1d, 0x19, 0xf7, + 0x86, 0xa1, 0x06, 0x3c, 0xca, 0x3c, 0x90, 0x17, 0x92, 0x36, 0x3f, 0x0f, 0x31, 0x6b, 0x0f, 0x69, + 0x1c, 0x70, 0xed, 0xf7, 0xf5, 0x0d, 0xfc, 0xb8, 0xc7, 0x4e, 0xe4, 0x1f, 0xe5, 0x6b, 0xff, 0x67, + 0xc2, 0xd2, 0x4e, 0x84, 0x3d, 0x8e, 0x0f, 0x3c, 0x76, 0xe2, 0xe2, 0x37, 0x31, 0x66, 0x1c, 0xad, + 0x80, 0x49, 0x7c, 0xcb, 0x68, 0x19, 0x6b, 0xd5, 0xed, 0xd2, 0xe5, 0xbb, 0x55, 0x73, 0xf7, 0xa9, + 0x6b, 0x12, 0x1f, 0xad, 0x40, 0xe9, 0x28, 0x0e, 0xfc, 0x01, 0xb6, 0x4c, 0x31, 0xe7, 0x6a, 0x0b, + 0x59, 0x50, 0xd6, 0x19, 0xb4, 0xe6, 0xe5, 0xc4, 0xc8, 0x44, 0x6d, 0x28, 0x45, 0x94, 0xf2, 0x63, + 0x66, 0x15, 0x5a, 0xf3, 0x6b, 0xb5, 0xce, 0x27, 0x4e, 0x22, 0xeb, 0x32, 0x24, 0xe7, 0xb9, 0x38, + 0x8a, 0xab, 0x61, 0xa8, 0x01, 0x15, 0x8e, 0xa3, 0x21, 0x09, 0xbc, 0x81, 0x55, 0x6c, 0x19, 0x6b, + 0x15, 0xf7, 0xca, 0x46, 0xcb, 0x50, 0x64, 0xdc, 0x27, 0x81, 0x55, 0x92, 0x9b, 0x28, 0x43, 0x04, + 0xc5, 0xb8, 0x4f, 0x63, 0x6e, 0x95, 0x55, 0x50, 0xca, 0xd2, 0xe3, 0x38, 0x8a, 0xac, 0xca, 0xd5, + 0x38, 0x8e, 0x22, 0xd4, 0x04, 0xe8, 0xf6, 0x71, 0xf7, 0x24, 0xa4, 0x24, 0xe0, 0x56, 0x55, 0xce, + 0x25, 0x46, 0xd0, 0xe7, 0xb0, 0x14, 0x7a, 0x11, 0x0e, 0xf8, 0x61, 0x02, 0x06, 0x12, 0xb6, 0xa8, + 0x26, 0x76, 0xc6, 0x60, 0x07, 0xca, 0x34, 0xe4, 0x84, 0x06, 0xcc, 0xaa, 0xb5, 0x8c, 0xb5, 0x5a, + 0x67, 0xd9, 0x51, 0x34, 0x3b, 0x23, 0x9a, 0x9d, 0xad, 0xe0, 0xdc, 0x1d, 0x81, 0xec, 0x07, 0x80, + 0x92, 0xe9, 0x66, 0x21, 0x0d, 0x18, 0x46, 0x8b, 0x30, 0x1f, 0xea, 0x84, 0xd7, 0x5d, 0xf1, 0x69, + 0xff, 0x6e, 0xc0, 0xc2, 0x53, 0x3c, 0xc0, 0x1c, 0xa7, 0x83, 0xd0, 0x2a, 0xd4, 0xf0, 0x19, 0xe1, + 0x87, 0x8c, 0x7b, 0x3c, 0x66, 0x92, 0x93, 0xba, 0x0b, 0x62, 0x68, 0x5f, 0x8e, 0xa0, 0x2d, 0xa8, + 0x0a, 0x0b, 0xfb, 0x87, 0x1e, 0x97, 0xcc, 0xd4, 0x3a, 0x8d, 0x99, 0xf8, 0x0e, 0x46, 0x32, 0xdc, + 0xae, 0x5c, 0xbc, 0x5b, 0x9d, 0xfb, 0xe3, 0x9f, 0x55, 0xc3, 0xad, 0x28, 0xb7, 0x2d, 0x6e, 0x3b, + 0xb0, 0xac, 0xe2, 0xd8, 0x8b, 0x68, 0x17, 0x33, 0x96, 0x21, 0x11, 0xfb, 0x4f, 0x03, 0xd0, 0xb3, + 0x33, 0xdc, 0xcd, 0x07, 0x9f, 0xa0, 0xdb, 0x4c, 0xa3, 0x7b, 0xfe, 0x7a, 0xba, 0x0b, 0x29, 0x74, + 0x17, 0x27, 0xe8, 0x5e, 0x83, 0x02, 0x0b, 0x71, 0x57, 0x6a, 0x26, 0x8d, 0x1e, 0x89, 0xb0, 0xef, + 0xc2, 0xc7, 0x13, 0x91, 0xab, 0xbc, 0xdb, 0xaf, 0x61, 0xd1, 0xc5, 0x8c, 0xfc, 0x8a, 0xf7, 0xf8, + 0x79, 0xd6, 0x71, 0x96, 0xa1, 0xf8, 0x0b, 0xf1, 0x79, 0x5f, 0x73, 0xa1, 0x0c, 0x11, 0x5a, 0x1f, + 0x93, 0x5e, 0x5f, 0x71, 0x50, 0x77, 0xb5, 0x65, 0x3f, 0x80, 0x3b, 0x82, 0x28, 0x9c, 0x95, 0xd3, + 0xb7, 0x26, 0xd4, 0x35, 0x50, 0x6b, 0xe1, 0xa6, 0x17, 0x54, 0x6b, 0x67, 0x7e, 0xac, 0x9d, 0x0d, + 0x91, 0x2e, 0x29, 0x1b, 0x91, 0xc6, 0x85, 0xce, 0xfd, 0xe4, 0xc5, 0x3c, 0x5d, 0xd7, 0x77, 0x53, + 0xe9, 0xc8, 0xd5, 0xd0, 0x31, 0x23, 0xc5, 0xeb, 0x19, 0x29, 0xa5, 0x30, 0x52, 0x9e, 0x60, 0x24, + 0xc9, 0x79, 0x65, 0x8a, 0xf3, 0x29, 0x49, 0x57, 0x3f, 0x2c, 0x69, 0xb8, 0x95, 0xa4, 0x5f, 0x40, + 0xed, 0x3b, 0x32, 0x18, 0xe4, 0x28, 0x76, 0x8c, 0xf4, 0x46, 0xc2, 0xac, 0xbb, 0xda, 0x12, 0xb9, + 0xf4, 0x06, 0x03, 0x99, 0xcb, 0x8a, 0x2b, 0x3e, 0xed, 0x4d, 0x58, 0xd8, 0x19, 0x50, 0x86, 0x77, + 0x5f, 0xe4, 0xd0, 0x87, 0x4a, 0xa0, 0xd2, 0xba, 0x32, 0xec, 0xcf, 0xe0, 0xa3, 0xef, 0x09, 0xe3, + 0x7b, 0xc4, 0xcf, 0xbc, 0x5e, 0x2e, 0x2c, 0x8e, 0xa1, 0x5a, 0x0c, 0x9b, 0x50, 0x0d, 0x95, 0x66, + 0x31, 0xb3, 0x0c, 0x59, 0x66, 0x5b, 0xd7, 0xb2, 0xa9, 0x95, 0xbd, 0x1b, 0x1c, 0x53, 0x77, 0xec, + 0x62, 0xff, 0x04, 0x77, 0xc7, 0x15, 0x2d, 0xd9, 0x06, 0x10, 0x14, 0x42, 0x8f, 0xf7, 0x55, 0x18, + 0xae, 0xfc, 0x4e, 0x16, 0x3c, 0x33, 0x4f, 0xc1, 0x7b, 0x08, 0x8b, 0xfb, 0x7d, 0x32, 0x94, 0x7b, + 0x8e, 0x02, 0xbe, 0x07, 0x15, 0xd1, 0x62, 0x0f, 0xc7, 0xe5, 0xac, 0x2c, 0xec, 0x3d, 0xe2, 0xdb, + 0xdf, 0xc2, 0xd2, 0xcb, 0xd0, 0x9f, 0x6a, 0x47, 0x1d, 0xa8, 0x46, 0x98, 0xd1, 0x38, 0xea, 0xca, + 0x03, 0xa6, 0xef, 0x3a, 0x86, 0xe9, 0xbb, 0x15, 0xf1, 0xac, 0x84, 0x7e, 0x25, 0xaf, 0x96, 0xc0, + 0x65, 0x5c, 0x2d, 0x7d, 0x85, 0xcc, 0x71, 0x8d, 0xfe, 0x14, 0x6a, 0xaf, 0x3c, 0x92, 0xb9, 0x43, + 0x04, 0x77, 0x14, 0x4c, 0x6f, 0x30, 0x25, 0x71, 0xe3, 0xc3, 0x12, 0x37, 0x6f, 0x23, 0xf1, 0xce, + 0xdb, 0x1a, 0x14, 0x44, 0xda, 0x51, 0x1f, 0x8a, 0xb2, 0x72, 0x20, 0xc7, 0xc9, 0x7a, 0xee, 0x38, + 0xc9, 0x5a, 0xd4, 0x68, 0xe7, 0xc6, 0xeb, 0x63, 0x31, 0x28, 0xa9, 0xce, 0x86, 0x36, 0xb2, 0x5d, + 0x67, 0x9e, 0x1c, 0x8d, 0x2f, 0x6f, 0xe6, 0xa4, 0x37, 0x55, 0xc7, 0x8b, 0x78, 0xce, 0xe3, 0x5d, + 0xc9, 0x21, 0xe7, 0xf1, 0x12, 0xb2, 0x70, 0xa1, 0xa4, 0xfa, 0x20, 0x5a, 0x99, 0xe1, 0xe2, 0x99, + 0x78, 0xfb, 0x35, 0xbe, 0xc8, 0x5e, 0x72, 0xaa, 0xa3, 0x9f, 0x43, 0x7d, 0xa2, 0xb7, 0xa2, 0x47, + 0x79, 0x97, 0x98, 0xec, 0xae, 0xb7, 0xd8, 0xfa, 0x0d, 0x54, 0x46, 0x75, 0x04, 0xad, 0x67, 0x7b, + 0x4f, 0x95, 0xa7, 0x46, 0xe7, 0x26, 0x2e, 0x7a, 0xcb, 0xc7, 0x50, 0xdc, 0xf3, 0x62, 0x96, 0x9e, + 0xc0, 0x94, 0x71, 0xf4, 0x04, 0x4a, 0x2e, 0x66, 0xf1, 0xf0, 0xe6, 0x9e, 0x3f, 0x03, 0x24, 0xde, + 0x6a, 0x8f, 0x73, 0x48, 0xec, 0xba, 0x3a, 0x98, 0xba, 0xfc, 0x73, 0x28, 0x88, 0x46, 0x82, 0x1e, + 0x66, 0x2f, 0x9c, 0x68, 0x38, 0xa9, 0xcb, 0x1d, 0x40, 0x41, 0xbc, 0x3f, 0x50, 0x8e, 0xab, 0x30, + 0xfb, 0xc2, 0x4a, 0x5d, 0xf5, 0x15, 0x54, 0xaf, 0x9e, 0x2f, 0x28, 0x07, 0x6f, 0xd3, 0x6f, 0x9d, + 0xd4, 0x85, 0xf7, 0xa1, 0xac, 0xbb, 0x1e, 0xca, 0xa1, 0xbf, 0xc9, 0x06, 0x99, 0xba, 0xe8, 0x0f, + 0x50, 0x19, 0xb5, 0x8b, 0x54, 0xb6, 0x73, 0x1c, 0x62, 0xa6, 0xe5, 0xbc, 0x84, 0x92, 0xea, 0x2b, + 0x79, 0xaa, 0xd3, 0x4c, 0x07, 0x4a, 0x0d, 0x17, 0x43, 0x41, 0xd4, 0xf6, 0x3c, 0x0a, 0x48, 0xb4, + 0x8a, 0x86, 0x93, 0x17, 0xae, 0xa2, 0xdf, 0x76, 0x2f, 0xde, 0x37, 0xe7, 0xfe, 0x7e, 0xdf, 0x9c, + 0xfb, 0xed, 0xb2, 0x69, 0x5c, 0x5c, 0x36, 0x8d, 0xbf, 0x2e, 0x9b, 0xc6, 0xbf, 0x97, 0x4d, 0xe3, + 0xc7, 0x27, 0xb7, 0xf8, 0x27, 0xf8, 0x1b, 0xf1, 0xfb, 0xda, 0x3c, 0x2a, 0xc9, 0xc3, 0x6c, 0xfc, + 0x1f, 0x00, 0x00, 0xff, 0xff, 0x64, 0x52, 0x86, 0xc0, 0x49, 0x0f, 0x00, 0x00, } diff --git a/vendor/github.com/containerd/containerd/runtime/shim/v1/shim.proto b/vendor/github.com/containerd/containerd/runtime/v1/shim/v1/shim.proto similarity index 97% rename from vendor/github.com/containerd/containerd/runtime/shim/v1/shim.proto rename to vendor/github.com/containerd/containerd/runtime/v1/shim/v1/shim.proto index 8248b2aa02..516d914b9e 100644 --- a/vendor/github.com/containerd/containerd/runtime/shim/v1/shim.proto +++ b/vendor/github.com/containerd/containerd/runtime/v1/shim/v1/shim.proto @@ -9,7 +9,7 @@ import "google/protobuf/timestamp.proto"; import "github.com/containerd/containerd/api/types/mount.proto"; import "github.com/containerd/containerd/api/types/task/task.proto"; -option go_package = "github.com/containerd/containerd/runtime/shim/v1;shim"; +option go_package = "github.com/containerd/containerd/runtime/v1/shim/v1;shim"; // Shim service is launched for each container and is responsible for owning the IO // for the container and its additional processes. The shim is also the parent of diff --git a/vendor/github.com/containerd/containerd/services.go b/vendor/github.com/containerd/containerd/services.go index daa7b897ec..395fc30651 100644 --- a/vendor/github.com/containerd/containerd/services.go +++ b/vendor/github.com/containerd/containerd/services.go @@ -20,12 +20,12 @@ import ( containersapi "github.com/containerd/containerd/api/services/containers/v1" "github.com/containerd/containerd/api/services/diff/v1" imagesapi "github.com/containerd/containerd/api/services/images/v1" - "github.com/containerd/containerd/api/services/leases/v1" namespacesapi "github.com/containerd/containerd/api/services/namespaces/v1" "github.com/containerd/containerd/api/services/tasks/v1" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/content" "github.com/containerd/containerd/images" + "github.com/containerd/containerd/leases" "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/snapshots" ) @@ -39,7 +39,7 @@ type services struct { taskService tasks.TasksClient diffService DiffService eventService EventService - leasesService leases.LeasesClient + leasesService leases.Manager } // ServicesOpt allows callers to set options on the services @@ -105,7 +105,7 @@ func WithNamespaceService(namespaceService namespacesapi.NamespacesClient) Servi } // WithLeasesService sets the lease service. -func WithLeasesService(leasesService leases.LeasesClient) ServicesOpt { +func WithLeasesService(leasesService leases.Manager) ServicesOpt { return func(s *services) { s.leasesService = leasesService } diff --git a/vendor/github.com/containerd/containerd/services/server/config.go b/vendor/github.com/containerd/containerd/services/server/config.go index 41d08b43c2..a91d5fffd9 100644 --- a/vendor/github.com/containerd/containerd/services/server/config.go +++ b/vendor/github.com/containerd/containerd/services/server/config.go @@ -43,6 +43,8 @@ type Config struct { OOMScore int `toml:"oom_score"` // Cgroup specifies cgroup information for the containerd daemon process Cgroup CgroupConfig `toml:"cgroup"` + // ProxyPlugins configures plugins which are communicated to over GRPC + ProxyPlugins map[string]ProxyPlugin `toml:"proxy_plugins"` md toml.MetaData } @@ -75,6 +77,12 @@ type CgroupConfig struct { Path string `toml:"path"` } +// ProxyPlugin provides a proxy plugin configuration +type ProxyPlugin struct { + Type string `toml:"type"` + Address string `toml:"address"` +} + // Decode unmarshals a plugin specific configuration by plugin id func (c *Config) Decode(id string, v interface{}) (interface{}, error) { data, ok := c.Plugins[id] diff --git a/vendor/github.com/containerd/containerd/services/server/server.go b/vendor/github.com/containerd/containerd/services/server/server.go index 33d4b6c759..3b2852e429 100644 --- a/vendor/github.com/containerd/containerd/services/server/server.go +++ b/vendor/github.com/containerd/containerd/services/server/server.go @@ -26,19 +26,26 @@ import ( "os" "path/filepath" "strings" + "sync" + "time" "github.com/boltdb/bolt" + csapi "github.com/containerd/containerd/api/services/content/v1" + ssapi "github.com/containerd/containerd/api/services/snapshots/v1" "github.com/containerd/containerd/content" "github.com/containerd/containerd/content/local" + csproxy "github.com/containerd/containerd/content/proxy" + "github.com/containerd/containerd/defaults" "github.com/containerd/containerd/events/exchange" "github.com/containerd/containerd/log" "github.com/containerd/containerd/metadata" + "github.com/containerd/containerd/pkg/dialer" "github.com/containerd/containerd/plugin" "github.com/containerd/containerd/snapshots" + ssproxy "github.com/containerd/containerd/snapshots/proxy" metrics "github.com/docker/go-metrics" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/pkg/errors" - "google.golang.org/grpc" ) @@ -62,7 +69,7 @@ func New(ctx context.Context, config *Config) (*Server, error) { if err := apply(ctx, config); err != nil { return nil, err } - plugins, err := LoadPlugins(config) + plugins, err := LoadPlugins(ctx, config) if err != nil { return nil, err } @@ -204,7 +211,7 @@ func (s *Server) Stop() { // LoadPlugins loads all plugins into containerd and generates an ordered graph // of all plugins. -func LoadPlugins(config *Config) ([]*plugin.Registration, error) { +func LoadPlugins(ctx context.Context, config *Config) ([]*plugin.Registration, error) { // load all plugins into containerd if err := plugin.Load(filepath.Join(config.Root, "plugins")); err != nil { return nil, err @@ -265,10 +272,85 @@ func LoadPlugins(config *Config) ([]*plugin.Registration, error) { }, }) + clients := &proxyClients{} + for name, pp := range config.ProxyPlugins { + var ( + t plugin.Type + f func(*grpc.ClientConn) interface{} + + address = pp.Address + ) + + switch pp.Type { + case string(plugin.SnapshotPlugin), "snapshot": + t = plugin.SnapshotPlugin + ssname := name + f = func(conn *grpc.ClientConn) interface{} { + return ssproxy.NewSnapshotter(ssapi.NewSnapshotsClient(conn), ssname) + } + + case string(plugin.ContentPlugin), "content": + t = plugin.ContentPlugin + f = func(conn *grpc.ClientConn) interface{} { + return csproxy.NewContentStore(csapi.NewContentClient(conn)) + } + default: + log.G(ctx).WithField("type", pp.Type).Warn("unknown proxy plugin type") + } + + plugin.Register(&plugin.Registration{ + Type: t, + ID: name, + InitFn: func(ic *plugin.InitContext) (interface{}, error) { + ic.Meta.Exports["address"] = address + conn, err := clients.getClient(address) + if err != nil { + return nil, err + } + return f(conn), nil + }, + }) + + } + // return the ordered graph for plugins return plugin.Graph(config.DisabledPlugins), nil } +type proxyClients struct { + m sync.Mutex + clients map[string]*grpc.ClientConn +} + +func (pc *proxyClients) getClient(address string) (*grpc.ClientConn, error) { + pc.m.Lock() + defer pc.m.Unlock() + if pc.clients == nil { + pc.clients = map[string]*grpc.ClientConn{} + } else if c, ok := pc.clients[address]; ok { + return c, nil + } + + gopts := []grpc.DialOption{ + grpc.WithInsecure(), + grpc.WithBackoffMaxDelay(3 * time.Second), + grpc.WithDialer(dialer.Dialer), + + // TODO(stevvooe): We may need to allow configuration of this on the client. + grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)), + grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)), + } + + conn, err := grpc.Dial(dialer.DialAddress(address), gopts...) + if err != nil { + return nil, errors.Wrapf(err, "failed to dial %q", address) + } + + pc.clients[address] = conn + + return conn, nil +} + func trapClosedConnErr(err error) error { if err == nil { return nil diff --git a/vendor/github.com/containerd/containerd/sys/mount_linux.go b/vendor/github.com/containerd/containerd/sys/mount_linux.go new file mode 100644 index 0000000000..a9eee9b73a --- /dev/null +++ b/vendor/github.com/containerd/containerd/sys/mount_linux.go @@ -0,0 +1,119 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package sys + +import ( + "runtime" + "syscall" + "unsafe" + + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +// FMountat performs mount from the provided directory. +func FMountat(dirfd uintptr, source, target, fstype string, flags uintptr, data string) error { + var ( + sourceP, targetP, fstypeP, dataP *byte + pid uintptr + ws unix.WaitStatus + err error + errno syscall.Errno + ) + + sourceP, err = syscall.BytePtrFromString(source) + if err != nil { + return err + } + + targetP, err = syscall.BytePtrFromString(target) + if err != nil { + return err + } + + fstypeP, err = syscall.BytePtrFromString(fstype) + if err != nil { + return err + } + + if data != "" { + dataP, err = syscall.BytePtrFromString(data) + if err != nil { + return err + } + } + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + pid, errno = forkAndMountat(dirfd, + uintptr(unsafe.Pointer(sourceP)), + uintptr(unsafe.Pointer(targetP)), + uintptr(unsafe.Pointer(fstypeP)), + flags, + uintptr(unsafe.Pointer(dataP))) + + if errno != 0 { + return errors.Wrap(errno, "failed to fork thread") + } + + _, err = unix.Wait4(int(pid), &ws, 0, nil) + for err == syscall.EINTR { + _, err = unix.Wait4(int(pid), &ws, 0, nil) + } + + if err != nil { + return errors.Wrapf(err, "failed to find pid=%d process", pid) + } + + errno = syscall.Errno(ws.ExitStatus()) + if errno != 0 { + return errors.Wrap(errno, "failed to mount") + } + return nil +} + +// forkAndMountat will fork thread, change working dir and mount. +// +// precondition: the runtime OS thread must be locked. +func forkAndMountat(dirfd uintptr, source, target, fstype, flags, data uintptr) (pid uintptr, errno syscall.Errno) { + // block signal during clone + beforeFork() + + // the cloned thread shares the open file descriptor, but the thread + // never be reused by runtime. + pid, _, errno = syscall.RawSyscall6(syscall.SYS_CLONE, uintptr(syscall.SIGCHLD)|syscall.CLONE_FILES, 0, 0, 0, 0, 0) + if errno != 0 || pid != 0 { + // restore all signals + afterFork() + return + } + + // restore all signals + afterForkInChild() + + // change working dir + _, _, errno = syscall.RawSyscall(syscall.SYS_FCHDIR, dirfd, 0, 0) + if errno != 0 { + goto childerr + } + _, _, errno = syscall.RawSyscall6(syscall.SYS_MOUNT, source, target, fstype, flags, data, 0) + +childerr: + syscall.RawSyscall(syscall.SYS_EXIT, uintptr(errno), 0, 0) + panic("unreachable") +} diff --git a/vendor/github.com/containerd/containerd/sys/reaper.go b/vendor/github.com/containerd/containerd/sys/reaper.go index 23cb040b80..d08ccccfbc 100644 --- a/vendor/github.com/containerd/containerd/sys/reaper.go +++ b/vendor/github.com/containerd/containerd/sys/reaper.go @@ -18,7 +18,9 @@ package sys -import "golang.org/x/sys/unix" +import ( + "golang.org/x/sys/unix" +) // Exit is the wait4 information from an exited process type Exit struct { diff --git a/vendor/github.com/containerd/containerd/sys/reaper_linux.go b/vendor/github.com/containerd/containerd/sys/reaper_linux.go new file mode 100644 index 0000000000..ecb0bd031e --- /dev/null +++ b/vendor/github.com/containerd/containerd/sys/reaper_linux.go @@ -0,0 +1,52 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package sys + +import ( + "unsafe" + + "golang.org/x/sys/unix" +) + +// If arg2 is nonzero, set the "child subreaper" attribute of the +// calling process; if arg2 is zero, unset the attribute. When a +// process is marked as a child subreaper, all of the children +// that it creates, and their descendants, will be marked as +// having a subreaper. In effect, a subreaper fulfills the role +// of init(1) for its descendant processes. Upon termination of +// a process that is orphaned (i.e., its immediate parent has +// already terminated) and marked as having a subreaper, the +// nearest still living ancestor subreaper will receive a SIGCHLD +// signal and be able to wait(2) on the process to discover its +// termination status. +const setChildSubreaper = 36 + +// SetSubreaper sets the value i as the subreaper setting for the calling process +func SetSubreaper(i int) error { + return unix.Prctl(setChildSubreaper, uintptr(i), 0, 0, 0) +} + +// GetSubreaper returns the subreaper setting for the calling process +func GetSubreaper() (int, error) { + var i uintptr + + if err := unix.Prctl(unix.PR_GET_CHILD_SUBREAPER, uintptr(unsafe.Pointer(&i)), 0, 0, 0); err != nil { + return -1, err + } + + return int(i), nil +} diff --git a/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.go b/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.go new file mode 100644 index 0000000000..6e40a9c7d7 --- /dev/null +++ b/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.go @@ -0,0 +1,30 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package sys + +import ( + _ "unsafe" // required for go:linkname. +) + +//go:linkname beforeFork syscall.runtime_BeforeFork +func beforeFork() + +//go:linkname afterFork syscall.runtime_AfterFork +func afterFork() + +//go:linkname afterForkInChild syscall.runtime_AfterForkInChild +func afterForkInChild() diff --git a/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.s b/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.s new file mode 100644 index 0000000000..c073fa4ad7 --- /dev/null +++ b/vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.s @@ -0,0 +1,15 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ diff --git a/vendor/github.com/containerd/containerd/task.go b/vendor/github.com/containerd/containerd/task.go index 2ea53ed02d..750075f8db 100644 --- a/vendor/github.com/containerd/containerd/task.go +++ b/vendor/github.com/containerd/containerd/task.go @@ -40,6 +40,7 @@ import ( "github.com/containerd/typeurl" google_protobuf "github.com/gogo/protobuf/types" digest "github.com/opencontainers/go-digest" + is "github.com/opencontainers/image-spec/specs-go" "github.com/opencontainers/image-spec/specs-go/v1" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -424,6 +425,9 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag return nil, err } index := v1.Index{ + Versioned: is.Versioned{ + SchemaVersion: 2, + }, Annotations: make(map[string]string), } if err := t.checkpointTask(ctx, &index, request); err != nil { @@ -454,10 +458,7 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag if im, err = t.client.ImageService().Create(ctx, im); err != nil { return nil, err } - return &image{ - client: t.client, - i: im, - }, nil + return NewImage(t.client, im), nil } // UpdateTaskInfo allows updated specific settings to be changed on a task diff --git a/vendor/github.com/containerd/containerd/task_opts.go b/vendor/github.com/containerd/containerd/task_opts.go index 6f2897726b..9e998a3498 100644 --- a/vendor/github.com/containerd/containerd/task_opts.go +++ b/vendor/github.com/containerd/containerd/task_opts.go @@ -22,7 +22,6 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/runtime/linux/runctypes" ) // NewTaskOpts allows the caller to set options on a new task @@ -36,14 +35,6 @@ func WithRootFS(mounts []mount.Mount) NewTaskOpts { } } -// WithExit causes the task to exit after a successful checkpoint -func WithExit(r *CheckpointTaskInfo) error { - r.Options = &runctypes.CheckpointOptions{ - Exit: true, - } - return nil -} - // WithCheckpointName sets the image name for the checkpoint func WithCheckpointName(name string) CheckpointTaskOpts { return func(r *CheckpointTaskInfo) error { diff --git a/vendor/github.com/containerd/containerd/vendor.conf b/vendor/github.com/containerd/containerd/vendor.conf index b9e98a85e2..84db92d032 100644 --- a/vendor/github.com/containerd/containerd/vendor.conf +++ b/vendor/github.com/containerd/containerd/vendor.conf @@ -1,6 +1,6 @@ -github.com/containerd/go-runc f271fa2021de855d4d918dbef83c5fe19db1bdd5 -github.com/containerd/console 5d1b48d6114b8c9666f0c8b916f871af97b0a761 -github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130 +github.com/containerd/go-runc edcf3de1f4971445c42d61f20d506b30612aa031 +github.com/containerd/console 4d8a41f4ce5b9bae77c41786ea2458330f43f081 +github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244 @@ -19,7 +19,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.0 github.com/gogo/protobuf v1.0.0 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef github.com/golang/protobuf v1.1.0 -github.com/opencontainers/runtime-spec v1.0.1 +github.com/opencontainers/runtime-spec d810dbc60d8c5aeeb3d054bd1132fab2121968ce # v1.0.1-43-gd810dbc github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340 github.com/sirupsen/logrus v1.0.0 github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c @@ -27,7 +27,7 @@ golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac google.golang.org/grpc v1.12.0 github.com/pkg/errors v0.8.0 github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7 -golang.org/x/sys 314a259e304ff91bd6985da2a7149bbf91237993 https://github.com/golang/sys +golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2 https://github.com/golang/sys github.com/opencontainers/image-spec v1.0.1 golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 @@ -43,7 +43,7 @@ gotest.tools v2.1.0 github.com/google/go-cmp v0.1.0 # cri dependencies -github.com/containerd/cri v1.11.0 +github.com/containerd/cri v1.11.1 github.com/containerd/go-cni 5882530828ecf62032409b298a3e8b19e08b6534 github.com/blang/semver v3.1.0 github.com/containernetworking/cni v0.6.0 diff --git a/vendor/github.com/containerd/continuity/driver/driver_unix.go b/vendor/github.com/containerd/continuity/driver/driver_unix.go index c7d4e6ba15..67493ade08 100644 --- a/vendor/github.com/containerd/continuity/driver/driver_unix.go +++ b/vendor/github.com/containerd/continuity/driver/driver_unix.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "os" + "path/filepath" "sort" "github.com/containerd/continuity/devices" @@ -25,6 +26,18 @@ func (d *driver) Mkfifo(path string, mode os.FileMode) error { return devices.Mknod(path, mode, 0, 0) } +// Lchmod changes the mode of an file not following symlinks. +func (d *driver) Lchmod(path string, mode os.FileMode) (err error) { + if !filepath.IsAbs(path) { + path, err = filepath.Abs(path) + if err != nil { + return + } + } + + return sysx.Fchmodat(0, path, uint32(mode), sysx.AtSymlinkNofollow) +} + // Getxattr returns all of the extended attributes for the file at path p. func (d *driver) Getxattr(p string) (map[string][]byte, error) { xattrs, err := sysx.Listxattr(p) diff --git a/vendor/github.com/containerd/continuity/driver/lchmod_linux.go b/vendor/github.com/containerd/continuity/driver/lchmod_linux.go deleted file mode 100644 index 39ffe9cc32..0000000000 --- a/vendor/github.com/containerd/continuity/driver/lchmod_linux.go +++ /dev/null @@ -1,19 +0,0 @@ -package driver - -import ( - "os" - - "golang.org/x/sys/unix" -) - -// Lchmod changes the mode of a file not following symlinks. -func (d *driver) Lchmod(path string, mode os.FileMode) error { - // On Linux, file mode is not supported for symlinks, - // and fchmodat() does not support AT_SYMLINK_NOFOLLOW, - // so symlinks need to be skipped entirely. - if st, err := os.Stat(path); err == nil && st.Mode()&os.ModeSymlink != 0 { - return nil - } - - return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0) -} diff --git a/vendor/github.com/containerd/continuity/driver/lchmod_unix.go b/vendor/github.com/containerd/continuity/driver/lchmod_unix.go deleted file mode 100644 index 1b539f78e3..0000000000 --- a/vendor/github.com/containerd/continuity/driver/lchmod_unix.go +++ /dev/null @@ -1,14 +0,0 @@ -// +build darwin freebsd solaris - -package driver - -import ( - "os" - - "golang.org/x/sys/unix" -) - -// Lchmod changes the mode of a file not following symlinks. -func (d *driver) Lchmod(path string, mode os.FileMode) error { - return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW) -} diff --git a/vendor/github.com/containerd/continuity/fs/du.go b/vendor/github.com/containerd/continuity/fs/du.go index f8fc9a9946..26f5333154 100644 --- a/vendor/github.com/containerd/continuity/fs/du.go +++ b/vendor/github.com/containerd/continuity/fs/du.go @@ -10,8 +10,8 @@ type Usage struct { // DiskUsage counts the number of inodes and disk usage for the resources under // path. -func DiskUsage(ctx context.Context, roots ...string) (Usage, error) { - return diskUsage(ctx, roots...) +func DiskUsage(roots ...string) (Usage, error) { + return diskUsage(roots...) } // DiffUsage counts the numbers of inodes and disk usage in the diff --git a/vendor/github.com/containerd/continuity/fs/du_unix.go b/vendor/github.com/containerd/continuity/fs/du_unix.go index 9f6bc55fd9..fe3426d278 100644 --- a/vendor/github.com/containerd/continuity/fs/du_unix.go +++ b/vendor/github.com/containerd/continuity/fs/du_unix.go @@ -24,7 +24,7 @@ func newInode(stat *syscall.Stat_t) inode { } } -func diskUsage(ctx context.Context, roots ...string) (Usage, error) { +func diskUsage(roots ...string) (Usage, error) { var ( size int64 @@ -37,12 +37,6 @@ func diskUsage(ctx context.Context, roots ...string) (Usage, error) { return err } - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - inoKey := newInode(fi.Sys().(*syscall.Stat_t)) if _, ok := inodes[inoKey]; !ok { inodes[inoKey] = struct{}{} diff --git a/vendor/github.com/containerd/continuity/fs/du_windows.go b/vendor/github.com/containerd/continuity/fs/du_windows.go index faa443feda..3f852fc15e 100644 --- a/vendor/github.com/containerd/continuity/fs/du_windows.go +++ b/vendor/github.com/containerd/continuity/fs/du_windows.go @@ -8,7 +8,7 @@ import ( "path/filepath" ) -func diskUsage(ctx context.Context, roots ...string) (Usage, error) { +func diskUsage(roots ...string) (Usage, error) { var ( size int64 ) @@ -21,12 +21,6 @@ func diskUsage(ctx context.Context, roots ...string) (Usage, error) { return err } - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - size += fi.Size() return nil }); err != nil { diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_darwin.go b/vendor/github.com/containerd/continuity/sysx/chmod_darwin.go new file mode 100644 index 0000000000..e3ae2b7bbf --- /dev/null +++ b/vendor/github.com/containerd/continuity/sysx/chmod_darwin.go @@ -0,0 +1,18 @@ +package sysx + +const ( + // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in + AtSymlinkNofollow = 0x20 +) + +const ( + + // SYS_FCHMODAT defined from golang.org/sys/unix + SYS_FCHMODAT = 467 +) + +// These functions will be generated by generate.sh +// $ GOOS=darwin GOARCH=386 ./generate.sh chmod +// $ GOOS=darwin GOARCH=amd64 ./generate.sh chmod + +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_darwin_386.go b/vendor/github.com/containerd/continuity/sysx/chmod_darwin_386.go new file mode 100644 index 0000000000..5a8cf5b57d --- /dev/null +++ b/vendor/github.com/containerd/continuity/sysx/chmod_darwin_386.go @@ -0,0 +1,25 @@ +// mksyscall.pl -l32 chmod_darwin.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + use(unsafe.Pointer(_p0)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_darwin_amd64.go b/vendor/github.com/containerd/continuity/sysx/chmod_darwin_amd64.go new file mode 100644 index 0000000000..3287d1d579 --- /dev/null +++ b/vendor/github.com/containerd/continuity/sysx/chmod_darwin_amd64.go @@ -0,0 +1,25 @@ +// mksyscall.pl chmod_darwin.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + use(unsafe.Pointer(_p0)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_freebsd.go b/vendor/github.com/containerd/continuity/sysx/chmod_freebsd.go new file mode 100644 index 0000000000..b64a708be1 --- /dev/null +++ b/vendor/github.com/containerd/continuity/sysx/chmod_freebsd.go @@ -0,0 +1,17 @@ +package sysx + +const ( + // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in + AtSymlinkNofollow = 0x200 +) + +const ( + + // SYS_FCHMODAT defined from golang.org/sys/unix + SYS_FCHMODAT = 490 +) + +// These functions will be generated by generate.sh +// $ GOOS=freebsd GOARCH=amd64 ./generate.sh chmod + +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_freebsd_amd64.go b/vendor/github.com/containerd/continuity/sysx/chmod_freebsd_amd64.go new file mode 100644 index 0000000000..5a271abb1e --- /dev/null +++ b/vendor/github.com/containerd/continuity/sysx/chmod_freebsd_amd64.go @@ -0,0 +1,25 @@ +// mksyscall.pl chmod_freebsd.go +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT + +package sysx + +import ( + "syscall" + "unsafe" +) + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + use(unsafe.Pointer(_p0)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_linux.go b/vendor/github.com/containerd/continuity/sysx/chmod_linux.go new file mode 100644 index 0000000000..89df6d38ef --- /dev/null +++ b/vendor/github.com/containerd/continuity/sysx/chmod_linux.go @@ -0,0 +1,12 @@ +package sysx + +import "syscall" + +const ( + // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in /usr/include/linux/fcntl.h + AtSymlinkNofollow = 0x100 +) + +func Fchmodat(dirfd int, path string, mode uint32, flags int) error { + return syscall.Fchmodat(dirfd, path, mode, flags) +} diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_solaris.go b/vendor/github.com/containerd/continuity/sysx/chmod_solaris.go new file mode 100644 index 0000000000..3ba6e5edc8 --- /dev/null +++ b/vendor/github.com/containerd/continuity/sysx/chmod_solaris.go @@ -0,0 +1,11 @@ +package sysx + +import "golang.org/x/sys/unix" + +const ( + AtSymlinkNofollow = unix.AT_SYMLINK_NOFOLLOW +) + +func Fchmodat(dirfd int, path string, mode uint32, flags int) error { + return unix.Fchmodat(dirfd, path, mode, flags) +} diff --git a/vendor/github.com/containerd/continuity/sysx/xattr_darwin.go b/vendor/github.com/containerd/continuity/sysx/xattr_darwin.go index 58da430706..1164a7d11c 100644 --- a/vendor/github.com/containerd/continuity/sysx/xattr_darwin.go +++ b/vendor/github.com/containerd/continuity/sysx/xattr_darwin.go @@ -8,6 +8,7 @@ package sysx //sys setxattr(path string, attr string, data []byte, flags int) (err error) //sys removexattr(path string, attr string, options int) (err error) //sys listxattr(path string, dest []byte, options int) (sz int, err error) +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) const ( xattrNoFollow = 0x01 diff --git a/vendor/github.com/containerd/go-runc/command_linux.go b/vendor/github.com/containerd/go-runc/command_linux.go index d97400d066..71b52f9de4 100644 --- a/vendor/github.com/containerd/go-runc/command_linux.go +++ b/vendor/github.com/containerd/go-runc/command_linux.go @@ -18,6 +18,7 @@ package runc import ( "context" + "os" "os/exec" "syscall" ) @@ -31,6 +32,7 @@ func (r *Runc) command(context context.Context, args ...string) *exec.Cmd { cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: r.Setpgid, } + cmd.Env = os.Environ() if r.PdeathSignal != 0 { cmd.SysProcAttr.Pdeathsig = r.PdeathSignal } diff --git a/vendor/github.com/containerd/go-runc/command_other.go b/vendor/github.com/containerd/go-runc/command_other.go index 5209a14fb9..b8fd4b8660 100644 --- a/vendor/github.com/containerd/go-runc/command_other.go +++ b/vendor/github.com/containerd/go-runc/command_other.go @@ -20,6 +20,7 @@ package runc import ( "context" + "os" "os/exec" ) @@ -28,5 +29,7 @@ func (r *Runc) command(context context.Context, args ...string) *exec.Cmd { if command == "" { command = DefaultCommand } - return exec.CommandContext(context, command, append(r.args(), args...)...) + cmd := exec.CommandContext(context, command, append(r.args(), args...)...) + cmd.Env = os.Environ() + return cmd } diff --git a/vendor/github.com/containerd/go-runc/console.go b/vendor/github.com/containerd/go-runc/console.go index dc7b82ea04..09973e9d6b 100644 --- a/vendor/github.com/containerd/go-runc/console.go +++ b/vendor/github.com/containerd/go-runc/console.go @@ -50,7 +50,8 @@ func NewConsoleSocket(path string) (*Socket, error) { // NewTempConsoleSocket returns a temp console socket for use with a container // On Close(), the socket is deleted func NewTempConsoleSocket() (*Socket, error) { - dir, err := ioutil.TempDir("", "pty") + runtimeDir := os.Getenv("XDG_RUNTIME_DIR") + dir, err := ioutil.TempDir(runtimeDir, "pty") if err != nil { return nil, err } @@ -66,6 +67,11 @@ func NewTempConsoleSocket() (*Socket, error) { if err != nil { return nil, err } + if runtimeDir != "" { + if err := os.Chmod(abs, 0755|os.ModeSticky); err != nil { + return nil, err + } + } return &Socket{ l: l, rmdir: true, diff --git a/vendor/github.com/containerd/go-runc/runc.go b/vendor/github.com/containerd/go-runc/runc.go index e4cf98e8eb..ac9c89d805 100644 --- a/vendor/github.com/containerd/go-runc/runc.go +++ b/vendor/github.com/containerd/go-runc/runc.go @@ -66,6 +66,7 @@ type Runc struct { Setpgid bool Criu string SystemdCgroup bool + Rootless *bool // nil stands for "auto" } // List returns all containers created inside the provided runc root directory @@ -208,7 +209,7 @@ func (o *ExecOpts) args() (out []string, err error) { // Exec executres and additional process inside the container based on a full // OCI Process specification func (r *Runc) Exec(context context.Context, id string, spec specs.Process, opts *ExecOpts) error { - f, err := ioutil.TempFile("", "runc-process") + f, err := ioutil.TempFile(os.Getenv("XDG_RUNTIME_DIR"), "runc-process") if err != nil { return err } @@ -411,7 +412,7 @@ func (r *Runc) Top(context context.Context, id string, psOptions string) (*TopRe return nil, fmt.Errorf("%s: %s", err, data) } - topResults, err := parsePSOutput(data) + topResults, err := ParsePSOutput(data) if err != nil { return nil, fmt.Errorf("%s: ", err) } @@ -655,6 +656,10 @@ func (r *Runc) args() (out []string) { if r.SystemdCgroup { out = append(out, "--systemd-cgroup") } + if r.Rootless != nil { + // nil stands for "auto" (differs from explicit "false") + out = append(out, "--rootless="+strconv.FormatBool(*r.Rootless)) + } return out } diff --git a/vendor/github.com/containerd/go-runc/utils.go b/vendor/github.com/containerd/go-runc/utils.go index cc0af3fe86..69ad6ead75 100644 --- a/vendor/github.com/containerd/go-runc/utils.go +++ b/vendor/github.com/containerd/go-runc/utils.go @@ -73,8 +73,8 @@ func fieldsASCII(s string) []string { return strings.FieldsFunc(s, fn) } -// parsePSOutput parses the runtime's ps raw output and returns a TopResults -func parsePSOutput(output []byte) (*TopResults, error) { +// ParsePSOutput parses the runtime's ps raw output and returns a TopResults +func ParsePSOutput(output []byte) (*TopResults, error) { topResults := &TopResults{} lines := strings.Split(string(output), "\n") diff --git a/vendor/github.com/opencontainers/runtime-spec/README.md b/vendor/github.com/opencontainers/runtime-spec/README.md index f0ad86e672..b40dba17d8 100644 --- a/vendor/github.com/opencontainers/runtime-spec/README.md +++ b/vendor/github.com/opencontainers/runtime-spec/README.md @@ -22,12 +22,12 @@ To provide context for users the following section gives example use cases for e ### Application Bundle Builders Application bundle builders can create a [bundle](bundle.md) directory that includes all of the files required for launching an application as a container. -The bundle contains an OCI [configuration file](config.md) where the builder can specify host-independent details such as [which executable to launch](config.md#process) and host-specific settings such as [mount](config.md#mounts) locations, [hook](config.md#hooks) paths, Linux [namespaces](config-linux.md#namespaces) and [cgroups](config-linux.md#control-groups). +The bundle contains an OCI [configuration file](config.md) where the builder can specify host-independent details such as [which executable to launch](config.md#process) and host-specific settings such as [mount](config.md#mounts) locations, [hook](config.md#posix-platform-hooks) paths, Linux [namespaces](config-linux.md#namespaces) and [cgroups](config-linux.md#control-groups). Because the configuration includes host-specific settings, application bundle directories copied between two hosts may require configuration adjustments. ### Hook Developers -[Hook](config.md#hooks) developers can extend the functionality of an OCI-compliant runtime by hooking into a container's lifecycle with an external application. +[Hook](config.md#posix-platform-hooks) developers can extend the functionality of an OCI-compliant runtime by hooking into a container's lifecycle with an external application. Example use cases include sophisticated network configuration, volume garbage collection, etc. ### Runtime Developers @@ -54,7 +54,7 @@ When in doubt, start on the [mailing-list](#mailing-list). ### Meetings -The contributors and maintainers of all OCI projects have monthly meetings at 2:00 PM (USA Pacific) on the first Wednesday of every month. +The contributors and maintainers of all OCI projects have monthly meetings, which are usually at 2:00 PM (USA Pacific) on the first Wednesday of every month. There is an [iCalendar][rfc5545] format for the meetings [here](meeting.ics). Everyone is welcome to participate via [UberConference web][uberconference] or audio-only: +1 415 968 0849 (no PIN needed). An initial agenda will be posted to the [mailing list](#mailing-list) in the week before each meeting, and everyone is welcome to propose additional topics or suggest other agenda alterations there. diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go index 71c9fa7731..7781c53617 100644 --- a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go +++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go @@ -25,6 +25,8 @@ type Spec struct { Solaris *Solaris `json:"solaris,omitempty" platform:"solaris"` // Windows is platform-specific configuration for Windows based containers. Windows *Windows `json:"windows,omitempty" platform:"windows"` + // VM specifies configuration for virtual-machine-based containers. + VM *VM `json:"vm,omitempty" platform:"vm"` } // Process contains information to start a specific application inside the container. @@ -194,10 +196,10 @@ const ( // LinuxIDMapping specifies UID/GID mappings type LinuxIDMapping struct { - // HostID is the starting UID/GID on the host to be mapped to 'ContainerID' - HostID uint32 `json:"hostID"` // ContainerID is the starting UID/GID in the container ContainerID uint32 `json:"containerID"` + // HostID is the starting UID/GID on the host to be mapped to 'ContainerID' + HostID uint32 `json:"hostID"` // Size is the number of IDs to be mapped Size uint32 `json:"size"` } @@ -320,6 +322,14 @@ type LinuxNetwork struct { Priorities []LinuxInterfacePriority `json:"priorities,omitempty"` } +// LinuxRdma for Linux cgroup 'rdma' resource management (Linux 4.11) +type LinuxRdma struct { + // Maximum number of HCA handles that can be opened. Default is "no limit". + HcaHandles *uint32 `json:"hcaHandles,omitempty"` + // Maximum number of HCA objects that can be created. Default is "no limit". + HcaObjects *uint32 `json:"hcaObjects,omitempty"` +} + // LinuxResources has container runtime resource constraints type LinuxResources struct { // Devices configures the device whitelist. @@ -336,6 +346,10 @@ type LinuxResources struct { HugepageLimits []LinuxHugepageLimit `json:"hugepageLimits,omitempty"` // Network restriction configuration Network *LinuxNetwork `json:"network,omitempty"` + // Rdma resource restriction configuration. + // Limits are a set of key value pairs that define RDMA resource limits, + // where the key is device name and value is resource limits. + Rdma map[string]LinuxRdma `json:"rdma,omitempty"` } // LinuxDevice represents the mknod information for a Linux special device file @@ -419,6 +433,8 @@ type SolarisAnet struct { type Windows struct { // LayerFolders contains a list of absolute paths to directories containing image layers. LayerFolders []string `json:"layerFolders"` + // Devices are the list of devices to be mapped into the container. + Devices []WindowsDevice `json:"devices,omitempty"` // Resources contains information for handling resource constraints for the container. Resources *WindowsResources `json:"resources,omitempty"` // CredentialSpec contains a JSON object describing a group Managed Service Account (gMSA) specification. @@ -433,6 +449,14 @@ type Windows struct { Network *WindowsNetwork `json:"network,omitempty"` } +// WindowsDevice represents information about a host device to be mapped into the container. +type WindowsDevice struct { + // Device identifier: interface class GUID, etc. + ID string `json:"id"` + // Device identifier type: "class", etc. + IDType string `json:"idType"` +} + // WindowsResources has container runtime resource constraints for containers running on Windows. type WindowsResources struct { // Memory restriction configuration. @@ -487,6 +511,42 @@ type WindowsHyperV struct { UtilityVMPath string `json:"utilityVMPath,omitempty"` } +// VM contains information for virtual-machine-based containers. +type VM struct { + // Hypervisor specifies hypervisor-related configuration for virtual-machine-based containers. + Hypervisor VMHypervisor `json:"hypervisor,omitempty"` + // Kernel specifies kernel-related configuration for virtual-machine-based containers. + Kernel VMKernel `json:"kernel"` + // Image specifies guest image related configuration for virtual-machine-based containers. + Image VMImage `json:"image,omitempty"` +} + +// VMHypervisor contains information about the hypervisor to use for a virtual machine. +type VMHypervisor struct { + // Path is the host path to the hypervisor used to manage the virtual machine. + Path string `json:"path"` + // Parameters specifies parameters to pass to the hypervisor. + Parameters string `json:"parameters,omitempty"` +} + +// VMKernel contains information about the kernel to use for a virtual machine. +type VMKernel struct { + // Path is the host path to the kernel used to boot the virtual machine. + Path string `json:"path"` + // Parameters specifies parameters to pass to the kernel. + Parameters string `json:"parameters,omitempty"` + // InitRD is the host path to an initial ramdisk to be used by the kernel. + InitRD string `json:"initrd,omitempty"` +} + +// VMImage contains information about the virtual machine root image. +type VMImage struct { + // Path is the host path to the root image that the VM kernel would boot into. + Path string `json:"path"` + // Format is the root image format type (e.g. "qcow2", "raw", "vhd", etc). + Format string `json:"format"` +} + // LinuxSeccomp represents syscall restrictions type LinuxSeccomp struct { DefaultAction LinuxSeccompAction `json:"defaultAction"` diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go index ff0cb6a80e..b920fc1b39 100644 --- a/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go +++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go @@ -11,7 +11,7 @@ const ( VersionPatch = 1 // VersionDev indicates development branch. Releases will be empty string. - VersionDev = "" + VersionDev = "-dev" ) // Version is the specification version that the package types support.