Bläddra i källkod

Merge pull request #37664 from dmcgowan/vendor-containerd-1.2

Update containerd vendor to 1.2 beta
Sebastiaan van Stijn 6 år sedan
förälder
incheckning
7d4fa69e33
100 ändrade filer med 3231 tillägg och 757 borttagningar
  1. 1 1
      cmd/dockerd/daemon_unix.go
  2. 11 1
      libcontainerd/client_daemon.go
  3. 6 6
      vendor.conf
  4. 30 0
      vendor/github.com/containerd/cgroups/cgroup.go
  5. 4 1
      vendor/github.com/containerd/cgroups/control.go
  6. 4 0
      vendor/github.com/containerd/cgroups/cpuset.go
  7. 437 0
      vendor/github.com/containerd/cgroups/metrics.pb.go
  8. 12 0
      vendor/github.com/containerd/cgroups/metrics.proto
  9. 153 0
      vendor/github.com/containerd/cgroups/rdma.go
  10. 2 0
      vendor/github.com/containerd/cgroups/subsystem.go
  11. 1 0
      vendor/github.com/containerd/cgroups/utils.go
  12. 23 1
      vendor/github.com/containerd/containerd/README.md
  13. 256 51
      vendor/github.com/containerd/containerd/api/services/containers/v1/containers.pb.go
  14. 5 0
      vendor/github.com/containerd/containerd/api/services/containers/v1/containers.proto
  15. 72 32
      vendor/github.com/containerd/containerd/api/services/leases/v1/leases.pb.go
  16. 6 0
      vendor/github.com/containerd/containerd/api/services/leases/v1/leases.proto
  17. 153 0
      vendor/github.com/containerd/containerd/archive/compression/compression.go
  18. 37 1
      vendor/github.com/containerd/containerd/archive/tar.go
  19. 18 0
      vendor/github.com/containerd/containerd/archive/tar_opts.go
  20. 1 0
      vendor/github.com/containerd/containerd/archive/tar_opts_unix.go
  21. 1 0
      vendor/github.com/containerd/containerd/archive/tar_opts_windows.go
  22. 0 6
      vendor/github.com/containerd/containerd/cio/io_windows.go
  23. 105 41
      vendor/github.com/containerd/containerd/client.go
  24. 16 3
      vendor/github.com/containerd/containerd/client_opts.go
  25. 1 4
      vendor/github.com/containerd/containerd/container.go
  26. 3 4
      vendor/github.com/containerd/containerd/container_opts.go
  27. 2 2
      vendor/github.com/containerd/containerd/containers/containers.go
  28. 46 1
      vendor/github.com/containerd/containerd/containerstore.go
  29. 34 0
      vendor/github.com/containerd/containerd/content/local/store.go
  30. 20 9
      vendor/github.com/containerd/containerd/image.go
  31. 1 4
      vendor/github.com/containerd/containerd/import.go
  32. 91 0
      vendor/github.com/containerd/containerd/install.go
  33. 38 0
      vendor/github.com/containerd/containerd/install_opts.go
  34. 6 68
      vendor/github.com/containerd/containerd/lease.go
  35. 2 2
      vendor/github.com/containerd/containerd/leases/context.go
  36. 43 0
      vendor/github.com/containerd/containerd/leases/id.go
  37. 76 0
      vendor/github.com/containerd/containerd/leases/lease.go
  38. 93 0
      vendor/github.com/containerd/containerd/leases/proxy/manager.go
  39. 4 0
      vendor/github.com/containerd/containerd/log/context.go
  40. 18 0
      vendor/github.com/containerd/containerd/metadata/adaptors.go
  41. 1 0
      vendor/github.com/containerd/containerd/metadata/buckets.go
  42. 97 5
      vendor/github.com/containerd/containerd/metadata/content.go
  43. 1 1
      vendor/github.com/containerd/containerd/metadata/db.go
  44. 138 17
      vendor/github.com/containerd/containerd/metadata/gc.go
  45. 94 42
      vendor/github.com/containerd/containerd/metadata/leases.go
  46. 153 2
      vendor/github.com/containerd/containerd/mount/mount_linux.go
  47. 6 5
      vendor/github.com/containerd/containerd/mount/temp_unix.go
  48. 2 2
      vendor/github.com/containerd/containerd/mount/temp_unsupported.go
  49. 15 2
      vendor/github.com/containerd/containerd/oci/spec.go
  50. 35 0
      vendor/github.com/containerd/containerd/oci/spec_opts.go
  51. 117 4
      vendor/github.com/containerd/containerd/oci/spec_opts_unix.go
  52. 5 4
      vendor/github.com/containerd/containerd/oci/spec_unix.go
  53. 4 3
      vendor/github.com/containerd/containerd/oci/spec_windows.go
  54. 11 0
      vendor/github.com/containerd/containerd/platforms/platforms.go
  55. 2 0
      vendor/github.com/containerd/containerd/plugin/plugin.go
  56. 27 9
      vendor/github.com/containerd/containerd/remotes/docker/resolver.go
  57. 18 9
      vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go
  58. 1 1
      vendor/github.com/containerd/containerd/rootfs/apply.go
  59. 7 5
      vendor/github.com/containerd/containerd/runtime/runtime.go
  60. 6 6
      vendor/github.com/containerd/containerd/runtime/task.go
  61. 10 2
      vendor/github.com/containerd/containerd/runtime/task_list.go
  62. 2 2
      vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go
  63. 0 0
      vendor/github.com/containerd/containerd/runtime/v1/linux/proc/deleted_state.go
  64. 2 2
      vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go
  65. 0 0
      vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go
  66. 60 110
      vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go
  67. 2 2
      vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init_state.go
  68. 0 0
      vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go
  69. 0 0
      vendor/github.com/containerd/containerd/runtime/v1/linux/proc/process.go
  70. 7 2
      vendor/github.com/containerd/containerd/runtime/v1/linux/proc/types.go
  71. 0 0
      vendor/github.com/containerd/containerd/runtime/v1/linux/proc/utils.go
  72. 16 1
      vendor/github.com/containerd/containerd/runtime/v1/linux/process.go
  73. 14 88
      vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go
  74. 40 34
      vendor/github.com/containerd/containerd/runtime/v1/linux/task.go
  75. 2 2
      vendor/github.com/containerd/containerd/runtime/v1/shim/client/client.go
  76. 0 0
      vendor/github.com/containerd/containerd/runtime/v1/shim/client/client_linux.go
  77. 0 0
      vendor/github.com/containerd/containerd/runtime/v1/shim/client/client_unix.go
  78. 1 1
      vendor/github.com/containerd/containerd/runtime/v1/shim/local.go
  79. 0 0
      vendor/github.com/containerd/containerd/runtime/v1/shim/reaper.go
  80. 86 19
      vendor/github.com/containerd/containerd/runtime/v1/shim/service.go
  81. 0 0
      vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go
  82. 0 0
      vendor/github.com/containerd/containerd/runtime/v1/shim/service_unix.go
  83. 0 0
      vendor/github.com/containerd/containerd/runtime/v1/shim/v1/doc.go
  84. 75 75
      vendor/github.com/containerd/containerd/runtime/v1/shim/v1/shim.pb.go
  85. 1 1
      vendor/github.com/containerd/containerd/runtime/v1/shim/v1/shim.proto
  86. 3 3
      vendor/github.com/containerd/containerd/services.go
  87. 8 0
      vendor/github.com/containerd/containerd/services/server/config.go
  88. 85 3
      vendor/github.com/containerd/containerd/services/server/server.go
  89. 119 0
      vendor/github.com/containerd/containerd/sys/mount_linux.go
  90. 3 1
      vendor/github.com/containerd/containerd/sys/reaper.go
  91. 52 0
      vendor/github.com/containerd/containerd/sys/reaper_linux.go
  92. 30 0
      vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.go
  93. 15 0
      vendor/github.com/containerd/containerd/sys/subprocess_unsafe_linux.s
  94. 5 4
      vendor/github.com/containerd/containerd/task.go
  95. 0 9
      vendor/github.com/containerd/containerd/task_opts.go
  96. 6 6
      vendor/github.com/containerd/containerd/vendor.conf
  97. 13 0
      vendor/github.com/containerd/continuity/driver/driver_unix.go
  98. 0 19
      vendor/github.com/containerd/continuity/driver/lchmod_linux.go
  99. 0 14
      vendor/github.com/containerd/continuity/driver/lchmod_unix.go
  100. 2 2
      vendor/github.com/containerd/continuity/fs/du.go

+ 1 - 1
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/supervisor"

+ 11 - 1
libcontainerd/client_daemon.go

@@ -559,7 +559,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 {

+ 6 - 6
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

+ 30 - 0
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()

+ 4 - 1
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

+ 4 - 0
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

+ 437 - 0
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

+ 12 - 0
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;
+}

+ 153 - 0
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
+}

+ 2 - 0
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)

+ 1 - 0
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

+ 23 - 1
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

+ 256 - 51
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,
 }

+ 5 - 0
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;
+}

+ 72 - 32
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,
 }

+ 6 - 0
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 {

+ 153 - 0
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 ""
+}

+ 37 - 1
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
+}

+ 18 - 0
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
+	}
+}

+ 1 - 0
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
 }

+ 1 - 0
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

+ 0 - 6
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)

+ 105 - 41
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, err
+	}
+
+	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 resolve reference %q", ref)
+		return images.Image{}, errors.Wrapf(err, "failed to resolve reference %q", ref)
 	}
 
-	fetcher, err := pullCtx.Resolver.Fetcher(ctx, name)
+	fetcher, err := rCtx.Resolver.Fetcher(ctx, name)
 	if err != nil {
-		return nil, errors.Wrapf(err, "failed to get fetcher for %q", name)
+		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)
 }
 

+ 16 - 3
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 {

+ 1 - 4
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) {

+ 3 - 4
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

+ 2 - 2
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

+ 46 - 1
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) {

+ 34 - 0
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")

+ 20 - 9
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
 		}

+ 1 - 4
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
 }

+ 91 - 0
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
+}

+ 38 - 0
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
+}

+ 6 - 68
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
-}

+ 2 - 2
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)

+ 43 - 0
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
+	}
+}

+ 76 - 0
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
+	}
+}

+ 93 - 0
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
+}

+ 4 - 0
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) {

+ 18 - 0
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

+ 1 - 0
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
 )

+ 97 - 5
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
 }

+ 1 - 1
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)

+ 138 - 17
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 {
+			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
+			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

+ 94 - 42
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))
+}

+ 153 - 2
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")
+}

+ 6 - 5
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
 }

+ 2 - 2
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
 }

+ 15 - 2
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)
 }

+ 35 - 0
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 {

+ 117 - 4
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(

+ 5 - 4
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
 }

+ 4 - 3
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
 }

+ 11 - 0
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 == "" {

+ 2 - 0
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

+ 27 - 9
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 {

+ 18 - 9
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")

+ 1 - 1
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"

+ 7 - 5
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)
 }

+ 6 - 6
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

+ 10 - 2
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

+ 2 - 2
vendor/github.com/containerd/containerd/runtime/linux/bundle.go → 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"
 )
 

+ 0 - 0
vendor/github.com/containerd/containerd/runtime/linux/proc/deleted_state.go → vendor/github.com/containerd/containerd/runtime/v1/linux/proc/deleted_state.go


+ 2 - 2
vendor/github.com/containerd/containerd/runtime/linux/proc/exec.go → 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, &copyWaitGroup); err != nil {
+		if e.console, err = e.parent.Platform.CopyConsole(ctx, console, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg, &copyWaitGroup); err != nil {
 			return errors.Wrap(err, "failed to start console copy")
 		}
 	} else if !e.stdio.IsNull() {

+ 0 - 0
vendor/github.com/containerd/containerd/runtime/linux/proc/exec_state.go → vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go


+ 60 - 110
vendor/github.com/containerd/containerd/runtime/linux/proc/init.go → 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
-
-	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
+	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
+	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, &copyWaitGroup)
+		console, err = p.Platform.CopyConsole(ctx, console, r.Stdin, r.Stdout, r.Stderr, &p.wg, &copyWaitGroup)
 		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, &copyWaitGroup); 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, &copyWaitGroup); 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)
 		}

+ 2 - 2
vendor/github.com/containerd/containerd/runtime/linux/proc/init_state.go → 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, &copyWaitGroup)
+		console, err = p.Platform.CopyConsole(ctx, console, sio.Stdin, sio.Stdout, sio.Stderr, &p.wg, &copyWaitGroup)
 		if err != nil {
 			return errors.Wrap(err, "failed to start console copy")
 		}

+ 0 - 0
vendor/github.com/containerd/containerd/runtime/linux/proc/io.go → vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go


+ 0 - 0
vendor/github.com/containerd/containerd/runtime/linux/proc/process.go → vendor/github.com/containerd/containerd/runtime/v1/linux/proc/process.go


+ 7 - 2
vendor/github.com/containerd/containerd/runtime/linux/proc/types.go → 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
 }

+ 0 - 0
vendor/github.com/containerd/containerd/runtime/linux/proc/utils.go → vendor/github.com/containerd/containerd/runtime/v1/linux/proc/utils.go


+ 16 - 1
vendor/github.com/containerd/containerd/runtime/linux/process.go → 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
+}

+ 14 - 88
vendor/github.com/containerd/containerd/runtime/linux/runtime.go → 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

+ 40 - 34
vendor/github.com/containerd/containerd/runtime/linux/task.go → 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

+ 2 - 2
vendor/github.com/containerd/containerd/runtime/shim/client/client.go → 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"
 )

+ 0 - 0
vendor/github.com/containerd/containerd/runtime/shim/client/client_linux.go → vendor/github.com/containerd/containerd/runtime/v1/shim/client/client_linux.go


+ 0 - 0
vendor/github.com/containerd/containerd/runtime/shim/client/client_unix.go → vendor/github.com/containerd/containerd/runtime/v1/shim/client/client_unix.go


+ 1 - 1
vendor/github.com/containerd/containerd/runtime/shim/local.go → 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"
 )
 

+ 0 - 0
vendor/github.com/containerd/containerd/runtime/shim/reaper.go → vendor/github.com/containerd/containerd/runtime/v1/shim/reaper.go


+ 86 - 19
vendor/github.com/containerd/containerd/runtime/shim/service.go → 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
+}

+ 0 - 0
vendor/github.com/containerd/containerd/runtime/shim/service_linux.go → vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go


+ 0 - 0
vendor/github.com/containerd/containerd/runtime/shim/service_unix.go → vendor/github.com/containerd/containerd/runtime/v1/shim/service_unix.go


+ 0 - 0
vendor/github.com/containerd/containerd/runtime/shim/v1/doc.go → vendor/github.com/containerd/containerd/runtime/v1/shim/v1/doc.go


+ 75 - 75
vendor/github.com/containerd/containerd/runtime/shim/v1/shim.pb.go → 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,
 }

+ 1 - 1
vendor/github.com/containerd/containerd/runtime/shim/v1/shim.proto → 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

+ 3 - 3
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
 	}

+ 8 - 0
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]

+ 85 - 3
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

+ 119 - 0
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")
+}

+ 3 - 1
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 {

+ 52 - 0
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
+}

+ 30 - 0
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()

+ 15 - 0
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.
+*/

+ 5 - 4
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

+ 0 - 9
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 {

+ 6 - 6
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

+ 13 - 0
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)

+ 0 - 19
vendor/github.com/containerd/continuity/driver/lchmod_linux.go

@@ -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)
-}

+ 0 - 14
vendor/github.com/containerd/continuity/driver/lchmod_unix.go

@@ -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)
-}

+ 2 - 2
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

Vissa filer visades inte eftersom för många filer har ändrats