瀏覽代碼

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

Update containerd vendor to 1.2 beta
Sebastiaan van Stijn 6 年之前
父節點
當前提交
7d4fa69e33
共有 100 個文件被更改,包括 3231 次插入757 次删除
  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"
 	"path/filepath"
 	"strconv"
 	"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/cmd/dockerd/hack"
 	"github.com/docker/docker/daemon"
 	"github.com/docker/docker/daemon"
 	"github.com/docker/docker/libcontainerd/supervisor"
 	"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{}
 	opts := []containerd.CheckpointTaskOpts{}
 	if exit {
 	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...)
 	img, err := p.(containerd.Task).Checkpoint(ctx, opts...)
 	if err != nil {
 	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
 # 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/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/opencontainers/image-spec v1.0.1
 github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
 github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
 
 
@@ -114,12 +114,12 @@ github.com/googleapis/gax-go v2.0.0
 google.golang.org/genproto 694d95ba50e67b2e363f3483057db5d4910c18f9
 google.golang.org/genproto 694d95ba50e67b2e363f3483057db5d4910c18f9
 
 
 # containerd
 # containerd
-github.com/containerd/containerd b41633746ed4833f52c3c071e8edcfa2713e5677
+github.com/containerd/containerd v1.2.0-beta.0
 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
 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/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
 github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
 github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
 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
 	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
 // Delete will remove the control group from each of the subsystems registered
 func (c *cgroup) Delete() error {
 func (c *cgroup) Delete() error {
 	c.mu.Lock()
 	c.mu.Lock()

+ 4 - 1
vendor/github.com/containerd/cgroups/control.go

@@ -24,6 +24,7 @@ import (
 
 
 const (
 const (
 	cgroupProcs    = "cgroup.procs"
 	cgroupProcs    = "cgroup.procs"
+	cgroupTasks    = "tasks"
 	defaultDirPerm = 0755
 	defaultDirPerm = 0755
 )
 )
 
 
@@ -48,8 +49,10 @@ type Process struct {
 type Cgroup interface {
 type Cgroup interface {
 	// New creates a new cgroup under the calling cgroup
 	// New creates a new cgroup under the calling cgroup
 	New(string, *specs.LinuxResources) (Cgroup, error)
 	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
 	Add(Process) error
+	// AddTask adds a process to the cgroup (tasks)
+	AddTask(Process) error
 	// Delete removes the cgroup as a whole
 	// Delete removes the cgroup as a whole
 	Delete() error
 	Delete() error
 	// MoveTo moves all the processes under the calling cgroup to the provided one
 	// 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
 	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) {
 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) {
 	if cpus, err = ioutil.ReadFile(filepath.Join(path, "cpuset.cpus")); err != nil && !os.IsNotExist(err) {
 		return
 		return

+ 437 - 0
vendor/github.com/containerd/cgroups/metrics.pb.go

@@ -19,6 +19,8 @@
 		MemoryEntry
 		MemoryEntry
 		BlkIOStat
 		BlkIOStat
 		BlkIOEntry
 		BlkIOEntry
+		RdmaStat
+		RdmaEntry
 */
 */
 package cgroups
 package cgroups
 
 
@@ -49,6 +51,7 @@ type Metrics struct {
 	CPU     *CPUStat       `protobuf:"bytes,3,opt,name=cpu" json:"cpu,omitempty"`
 	CPU     *CPUStat       `protobuf:"bytes,3,opt,name=cpu" json:"cpu,omitempty"`
 	Memory  *MemoryStat    `protobuf:"bytes,4,opt,name=memory" json:"memory,omitempty"`
 	Memory  *MemoryStat    `protobuf:"bytes,4,opt,name=memory" json:"memory,omitempty"`
 	Blkio   *BlkIOStat     `protobuf:"bytes,5,opt,name=blkio" json:"blkio,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{} }
 func (m *Metrics) Reset()                    { *m = Metrics{} }
@@ -187,6 +190,25 @@ func (m *BlkIOEntry) Reset()                    { *m = BlkIOEntry{} }
 func (*BlkIOEntry) ProtoMessage()               {}
 func (*BlkIOEntry) ProtoMessage()               {}
 func (*BlkIOEntry) Descriptor() ([]byte, []int) { return fileDescriptorMetrics, []int{9} }
 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() {
 func init() {
 	proto.RegisterType((*Metrics)(nil), "io.containerd.cgroups.v1.Metrics")
 	proto.RegisterType((*Metrics)(nil), "io.containerd.cgroups.v1.Metrics")
 	proto.RegisterType((*HugetlbStat)(nil), "io.containerd.cgroups.v1.HugetlbStat")
 	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((*MemoryEntry)(nil), "io.containerd.cgroups.v1.MemoryEntry")
 	proto.RegisterType((*BlkIOStat)(nil), "io.containerd.cgroups.v1.BlkIOStat")
 	proto.RegisterType((*BlkIOStat)(nil), "io.containerd.cgroups.v1.BlkIOStat")
 	proto.RegisterType((*BlkIOEntry)(nil), "io.containerd.cgroups.v1.BlkIOEntry")
 	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) {
 func (m *Metrics) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	size := m.Size()
@@ -266,6 +290,16 @@ func (m *Metrics) MarshalTo(dAtA []byte) (int, error) {
 		}
 		}
 		i += n4
 		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
 	return i, nil
 }
 }
 
 
@@ -732,6 +766,7 @@ func (m *MemoryEntry) MarshalTo(dAtA []byte) (int, error) {
 	_ = i
 	_ = i
 	var l int
 	var l int
 	_ = l
 	_ = l
+
 	if m.Limit != 0 {
 	if m.Limit != 0 {
 		dAtA[i] = 0x8
 		dAtA[i] = 0x8
 		i++
 		i++
@@ -914,6 +949,82 @@ func (m *BlkIOEntry) MarshalTo(dAtA []byte) (int, error) {
 	return i, nil
 	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 {
 func encodeFixed64Metrics(dAtA []byte, offset int, v uint64) int {
 	dAtA[offset] = uint8(v)
 	dAtA[offset] = uint8(v)
 	dAtA[offset+1] = uint8(v >> 8)
 	dAtA[offset+1] = uint8(v >> 8)
@@ -966,6 +1077,10 @@ func (m *Metrics) Size() (n int) {
 		l = m.Blkio.Size()
 		l = m.Blkio.Size()
 		n += 1 + l + sovMetrics(uint64(l))
 		n += 1 + l + sovMetrics(uint64(l))
 	}
 	}
+	if m.Rdma != nil {
+		l = m.Rdma.Size()
+		n += 1 + l + sovMetrics(uint64(l))
+	}
 	return n
 	return n
 }
 }
 
 
@@ -1264,6 +1379,40 @@ func (m *BlkIOEntry) Size() (n int) {
 	return n
 	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) {
 func sovMetrics(x uint64) (n int) {
 	for {
 	for {
 		n++
 		n++
@@ -1287,6 +1436,7 @@ func (this *Metrics) String() string {
 		`CPU:` + strings.Replace(fmt.Sprintf("%v", this.CPU), "CPUStat", "CPUStat", 1) + `,`,
 		`CPU:` + strings.Replace(fmt.Sprintf("%v", this.CPU), "CPUStat", "CPUStat", 1) + `,`,
 		`Memory:` + strings.Replace(fmt.Sprintf("%v", this.Memory), "MemoryStat", "MemoryStat", 1) + `,`,
 		`Memory:` + strings.Replace(fmt.Sprintf("%v", this.Memory), "MemoryStat", "MemoryStat", 1) + `,`,
 		`Blkio:` + strings.Replace(fmt.Sprintf("%v", this.Blkio), "BlkIOStat", "BlkIOStat", 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
 	return s
@@ -1440,6 +1590,29 @@ func (this *BlkIOEntry) String() string {
 	}, "")
 	}, "")
 	return s
 	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 {
 func valueToStringMetrics(v interface{}) string {
 	rv := reflect.ValueOf(v)
 	rv := reflect.ValueOf(v)
 	if rv.IsNil() {
 	if rv.IsNil() {
@@ -1451,6 +1624,7 @@ func valueToStringMetrics(v interface{}) string {
 func (m *Metrics) Unmarshal(dAtA []byte) error {
 func (m *Metrics) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	l := len(dAtA)
 	iNdEx := 0
 	iNdEx := 0
+
 	for iNdEx < l {
 	for iNdEx < l {
 		preIndex := iNdEx
 		preIndex := iNdEx
 		var wire uint64
 		var wire uint64
@@ -1640,6 +1814,39 @@ func (m *Metrics) Unmarshal(dAtA []byte) error {
 				return err
 				return err
 			}
 			}
 			iNdEx = postIndex
 			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:
 		default:
 			iNdEx = preIndex
 			iNdEx = preIndex
 			skippy, err := skipMetrics(dAtA[iNdEx:])
 			skippy, err := skipMetrics(dAtA[iNdEx:])
@@ -3656,6 +3863,236 @@ func (m *BlkIOEntry) Unmarshal(dAtA []byte) error {
 	}
 	}
 	return nil
 	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) {
 func skipMetrics(dAtA []byte) (n int, err error) {
 	l := len(dAtA)
 	l := len(dAtA)
 	iNdEx := 0
 	iNdEx := 0

+ 12 - 0
vendor/github.com/containerd/cgroups/metrics.proto

@@ -10,6 +10,7 @@ message Metrics {
 	CPUStat cpu = 3 [(gogoproto.customname) = "CPU"];
 	CPUStat cpu = 3 [(gogoproto.customname) = "CPU"];
 	MemoryStat memory = 4;
 	MemoryStat memory = 4;
 	BlkIOStat blkio = 5;
 	BlkIOStat blkio = 5;
+	RdmaStat rdma = 6;
 }
 }
 
 
 message HugetlbStat {
 message HugetlbStat {
@@ -109,3 +110,14 @@ message BlkIOEntry {
 	uint64 minor = 4;
 	uint64 minor = 4;
 	uint64 value = 5;
 	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"
 	Cpuacct   Name = "cpuacct"
 	Memory    Name = "memory"
 	Memory    Name = "memory"
 	Blkio     Name = "blkio"
 	Blkio     Name = "blkio"
+	Rdma      Name = "rdma"
 )
 )
 
 
 // Subsystems returns a complete list of the default cgroups
 // Subsystems returns a complete list of the default cgroups
@@ -55,6 +56,7 @@ func Subsystems() []Name {
 		Cpuacct,
 		Cpuacct,
 		Memory,
 		Memory,
 		Blkio,
 		Blkio,
+		Rdma,
 	}
 	}
 	if !isUserNS {
 	if !isUserNS {
 		n = append(n, Devices)
 		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),
 		NewCpuacct(root),
 		NewMemory(root),
 		NewMemory(root),
 		NewBlkio(root),
 		NewBlkio(root),
+		NewRdma(root),
 	}
 	}
 	// only add the devices cgroup if we are not in a user namespace
 	// only add the devices cgroup if we are not in a user namespace
 	// because modifications are not allowed
 	// 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
 ```go
 // checkpoint the task then push it to a registry
 // 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)
 err := client.Push(context, "myregistry/checkpoints/redis:master", checkpoint)
 
 
@@ -184,6 +184,28 @@ defer task.Delete(context)
 err := task.Start(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
 ### Releases and API Stability
 
 
 Please see [RELEASES.md](RELEASES.md) for details on versioning and 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
 		UpdateContainerRequest
 		UpdateContainerResponse
 		UpdateContainerResponse
 		DeleteContainerRequest
 		DeleteContainerRequest
+		ListContainerMessage
 */
 */
 package containers
 package containers
 
 
@@ -218,6 +219,14 @@ func (m *DeleteContainerRequest) Reset()                    { *m = DeleteContain
 func (*DeleteContainerRequest) ProtoMessage()               {}
 func (*DeleteContainerRequest) ProtoMessage()               {}
 func (*DeleteContainerRequest) Descriptor() ([]byte, []int) { return fileDescriptorContainers, []int{9} }
 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() {
 func init() {
 	proto.RegisterType((*Container)(nil), "containerd.services.containers.v1.Container")
 	proto.RegisterType((*Container)(nil), "containerd.services.containers.v1.Container")
 	proto.RegisterType((*Container_Runtime)(nil), "containerd.services.containers.v1.Container.Runtime")
 	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((*UpdateContainerRequest)(nil), "containerd.services.containers.v1.UpdateContainerRequest")
 	proto.RegisterType((*UpdateContainerResponse)(nil), "containerd.services.containers.v1.UpdateContainerResponse")
 	proto.RegisterType((*UpdateContainerResponse)(nil), "containerd.services.containers.v1.UpdateContainerResponse")
 	proto.RegisterType((*DeleteContainerRequest)(nil), "containerd.services.containers.v1.DeleteContainerRequest")
 	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.
 // Reference imports to suppress errors if they are not otherwise used.
@@ -245,6 +255,7 @@ const _ = grpc.SupportPackageIsVersion4
 type ContainersClient interface {
 type ContainersClient interface {
 	Get(ctx context.Context, in *GetContainerRequest, opts ...grpc.CallOption) (*GetContainerResponse, error)
 	Get(ctx context.Context, in *GetContainerRequest, opts ...grpc.CallOption) (*GetContainerResponse, error)
 	List(ctx context.Context, in *ListContainersRequest, opts ...grpc.CallOption) (*ListContainersResponse, 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)
 	Create(ctx context.Context, in *CreateContainerRequest, opts ...grpc.CallOption) (*CreateContainerResponse, error)
 	Update(ctx context.Context, in *UpdateContainerRequest, opts ...grpc.CallOption) (*UpdateContainerResponse, 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)
 	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
 	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) {
 func (c *containersClient) Create(ctx context.Context, in *CreateContainerRequest, opts ...grpc.CallOption) (*CreateContainerResponse, error) {
 	out := new(CreateContainerResponse)
 	out := new(CreateContainerResponse)
 	err := grpc.Invoke(ctx, "/containerd.services.containers.v1.Containers/Create", in, out, c.cc, opts...)
 	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 {
 type ContainersServer interface {
 	Get(context.Context, *GetContainerRequest) (*GetContainerResponse, error)
 	Get(context.Context, *GetContainerRequest) (*GetContainerResponse, error)
 	List(context.Context, *ListContainersRequest) (*ListContainersResponse, error)
 	List(context.Context, *ListContainersRequest) (*ListContainersResponse, error)
+	ListStream(*ListContainersRequest, Containers_ListStreamServer) error
 	Create(context.Context, *CreateContainerRequest) (*CreateContainerResponse, error)
 	Create(context.Context, *CreateContainerRequest) (*CreateContainerResponse, error)
 	Update(context.Context, *UpdateContainerRequest) (*UpdateContainerResponse, error)
 	Update(context.Context, *UpdateContainerRequest) (*UpdateContainerResponse, error)
 	Delete(context.Context, *DeleteContainerRequest) (*google_protobuf2.Empty, 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)
 	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) {
 func _Containers_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 	in := new(CreateContainerRequest)
 	in := new(CreateContainerRequest)
 	if err := dec(in); err != nil {
 	if err := dec(in); err != nil {
@@ -432,7 +497,13 @@ var _Containers_serviceDesc = grpc.ServiceDesc{
 			Handler:    _Containers_Delete_Handler,
 			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",
 	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
 	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 {
 func encodeVarintContainers(dAtA []byte, offset int, v uint64) int {
 	for v >= 1<<7 {
 	for v >= 1<<7 {
 		dAtA[offset] = uint8(v&0x7f | 0x80)
 		dAtA[offset] = uint8(v&0x7f | 0x80)
@@ -1004,6 +1103,16 @@ func (m *DeleteContainerRequest) Size() (n int) {
 	return n
 	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) {
 func sovContainers(x uint64) (n int) {
 	for {
 	for {
 		n++
 		n++
@@ -1158,6 +1267,16 @@ func (this *DeleteContainerRequest) String() string {
 	}, "")
 	}, "")
 	return s
 	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 {
 func valueToStringContainers(v interface{}) string {
 	rv := reflect.ValueOf(v)
 	rv := reflect.ValueOf(v)
 	if rv.IsNil() {
 	if rv.IsNil() {
@@ -2562,6 +2681,89 @@ func (m *DeleteContainerRequest) Unmarshal(dAtA []byte) error {
 	}
 	}
 	return nil
 	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) {
 func skipContainers(dAtA []byte) (n int, err error) {
 	l := len(dAtA)
 	l := len(dAtA)
 	iNdEx := 0
 	iNdEx := 0
@@ -2672,54 +2874,57 @@ func init() {
 }
 }
 
 
 var fileDescriptorContainers = []byte{
 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 {
 service Containers {
 	rpc Get(GetContainerRequest) returns (GetContainerResponse);
 	rpc Get(GetContainerRequest) returns (GetContainerResponse);
 	rpc List(ListContainersRequest) returns (ListContainersResponse);
 	rpc List(ListContainersRequest) returns (ListContainersResponse);
+	rpc ListStream(ListContainersRequest) returns (stream ListContainerMessage);
 	rpc Create(CreateContainerRequest) returns (CreateContainerResponse);
 	rpc Create(CreateContainerRequest) returns (CreateContainerResponse);
 	rpc Update(UpdateContainerRequest) returns (UpdateContainerResponse);
 	rpc Update(UpdateContainerRequest) returns (UpdateContainerResponse);
 	rpc Delete(DeleteContainerRequest) returns (google.protobuf.Empty);
 	rpc Delete(DeleteContainerRequest) returns (google.protobuf.Empty);
@@ -156,3 +157,7 @@ message UpdateContainerResponse {
 message DeleteContainerRequest {
 message DeleteContainerRequest {
 	string id = 1;
 	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 {
 type DeleteRequest struct {
 	ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
 	ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	// 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{} }
 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 = encodeVarintLeases(dAtA, i, uint64(len(m.ID)))
 		i += copy(dAtA[i:], 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
 	return i, nil
 }
 }
 
 
@@ -534,6 +549,9 @@ func (m *DeleteRequest) Size() (n int) {
 	if l > 0 {
 	if l > 0 {
 		n += 1 + l + sovLeases(uint64(l))
 		n += 1 + l + sovLeases(uint64(l))
 	}
 	}
+	if m.Sync {
+		n += 2
+	}
 	return n
 	return n
 }
 }
 
 
@@ -633,6 +651,7 @@ func (this *DeleteRequest) String() string {
 	}
 	}
 	s := strings.Join([]string{`&DeleteRequest{`,
 	s := strings.Join([]string{`&DeleteRequest{`,
 		`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
 		`ID:` + fmt.Sprintf("%v", this.ID) + `,`,
+		`Sync:` + fmt.Sprintf("%v", this.Sync) + `,`,
 		`}`,
 		`}`,
 	}, "")
 	}, "")
 	return s
 	return s
@@ -1230,6 +1249,26 @@ func (m *DeleteRequest) Unmarshal(dAtA []byte) error {
 			}
 			}
 			m.ID = string(dAtA[iNdEx:postIndex])
 			m.ID = string(dAtA[iNdEx:postIndex])
 			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:
 		default:
 			iNdEx = preIndex
 			iNdEx = preIndex
 			skippy, err := skipLeases(dAtA[iNdEx:])
 			skippy, err := skipLeases(dAtA[iNdEx:])
@@ -1521,37 +1560,38 @@ func init() {
 }
 }
 
 
 var fileDescriptorLeases = []byte{
 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,
 	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 {
 message DeleteRequest {
 	string id = 1;
 	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 {
 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")
 			return 0, errors.Wrap(err, "failed to apply option")
 		}
 		}
 	}
 	}
+	if options.Filter == nil {
+		options.Filter = all
+	}
 
 
 	return apply(ctx, root, tar.NewReader(r), options)
 	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
 		// Normalize name, for safety and for a simple is-root check
 		hdr.Name = filepath.Clean(hdr.Name)
 		hdr.Name = filepath.Clean(hdr.Name)
 
 
+		accept, err := options.Filter(hdr)
+		if err != nil {
+			return 0, err
+		}
+		if !accept {
+			continue
+		}
+
 		if skipFile(hdr) {
 		if skipFile(hdr) {
 			log.G(ctx).Warnf("file %q ignored: archive may not be supported on system", hdr.Name)
 			log.G(ctx).Warnf("file %q ignored: archive may not be supported on system", hdr.Name)
 			continue
 			continue
@@ -366,10 +377,11 @@ func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header
 		}
 		}
 
 
 	case tar.TypeLink:
 	case tar.TypeLink:
-		targetPath, err := fs.RootPath(extractDir, hdr.Linkname)
+		targetPath, err := hardlinkRootPath(extractDir, hdr.Linkname)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
+
 		if err := os.Link(targetPath, path); err != nil {
 		if err := os.Link(targetPath, path); err != nil {
 			return err
 			return err
 		}
 		}
@@ -648,3 +660,27 @@ func copyBuffered(ctx context.Context, dst io.Writer, src io.Reader) (written in
 	return written, err
 	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
 package archive
 
 
+import "archive/tar"
+
 // ApplyOpt allows setting mutable archive apply properties on creation
 // ApplyOpt allows setting mutable archive apply properties on creation
 type ApplyOpt func(options *ApplyOptions) error
 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
 // ApplyOptions provides additional options for an Apply operation
 type ApplyOptions struct {
 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 {
 type ApplyOptions struct {
 	ParentLayerPaths        []string // Parent layer paths used for Windows layer apply
 	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
 	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
 // 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"
 	"fmt"
 	"io"
 	"io"
 	"net"
 	"net"
-	"sync"
 
 
 	winio "github.com/Microsoft/go-winio"
 	winio "github.com/Microsoft/go-winio"
 	"github.com/containerd/containerd/log"
 	"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) {
 func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
 	var (
 	var (
-		wg  sync.WaitGroup
 		set []io.Closer
 		set []io.Closer
 	)
 	)
 
 
@@ -85,9 +83,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
 		}(l)
 		}(l)
 		set = append(set, l)
 		set = append(set, l)
 
 
-		wg.Add(1)
 		go func() {
 		go func() {
-			defer wg.Done()
 			c, err := l.Accept()
 			c, err := l.Accept()
 			if err != nil {
 			if err != nil {
 				log.L.WithError(err).Errorf("failed to accept stdout connection on %s", fifos.Stdout)
 				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)
 		}(l)
 		set = append(set, l)
 		set = append(set, l)
 
 
-		wg.Add(1)
 		go func() {
 		go func() {
-			defer wg.Done()
 			c, err := l.Accept()
 			c, err := l.Accept()
 			if err != nil {
 			if err != nil {
 				log.L.WithError(err).Errorf("failed to accept stderr connection on %s", fifos.Stderr)
 				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/errdefs"
 	"github.com/containerd/containerd/events"
 	"github.com/containerd/containerd/events"
 	"github.com/containerd/containerd/images"
 	"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/namespaces"
 	"github.com/containerd/containerd/pkg/dialer"
 	"github.com/containerd/containerd/pkg/dialer"
+	"github.com/containerd/containerd/platforms"
 	"github.com/containerd/containerd/plugin"
 	"github.com/containerd/containerd/plugin"
 	"github.com/containerd/containerd/remotes"
 	"github.com/containerd/containerd/remotes"
 	"github.com/containerd/containerd/remotes/docker"
 	"github.com/containerd/containerd/remotes/docker"
@@ -79,8 +82,12 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
 			return nil, err
 			return nil, err
 		}
 		}
 	}
 	}
+	rt := fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS)
+	if copts.defaultRuntime != "" {
+		rt = copts.defaultRuntime
+	}
 	c := &Client{
 	c := &Client{
-		runtime: fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS),
+		runtime: rt,
 	}
 	}
 	if copts.services != nil {
 	if copts.services != nil {
 		c.services = *copts.services
 		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
 // 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) {
 func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image, error) {
 	pullCtx := defaultRemoteContext()
 	pullCtx := defaultRemoteContext()
 	for _, o := range opts {
 	for _, o := range opts {
@@ -292,7 +323,12 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
 			return nil, err
 			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)
 	ctx, done, err := c.WithLease(ctx)
 	if err != nil {
 	if err != nil {
@@ -300,82 +336,92 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
 	}
 	}
 	defer done(ctx)
 	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 {
 	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 {
 	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 (
 	var (
 		schema1Converter *schema1.Converter
 		schema1Converter *schema1.Converter
 		handler          images.Handler
 		handler          images.Handler
 	)
 	)
-	if desc.MediaType == images.MediaTypeDockerSchema1Manifest && pullCtx.ConvertSchema1 {
+	if desc.MediaType == images.MediaTypeDockerSchema1Manifest && rCtx.ConvertSchema1 {
 		schema1Converter = schema1.NewConverter(store, fetcher)
 		schema1Converter = schema1.NewConverter(store, fetcher)
-		handler = images.Handlers(append(pullCtx.BaseHandlers, schema1Converter)...)
+		handler = images.Handlers(append(rCtx.BaseHandlers, schema1Converter)...)
 	} else {
 	} else {
 		// Get all the children for a descriptor
 		// Get all the children for a descriptor
 		childrenHandler := images.ChildrenHandler(store)
 		childrenHandler := images.ChildrenHandler(store)
 		// Set any children labels for that content
 		// Set any children labels for that content
 		childrenHandler = images.SetChildrenLabels(store, childrenHandler)
 		childrenHandler = images.SetChildrenLabels(store, childrenHandler)
 		// Filter children by platforms
 		// 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),
 			remotes.FetchHandler(store, fetcher),
 			childrenHandler,
 			childrenHandler,
 		)...)
 		)...)
 	}
 	}
 
 
 	if err := images.Dispatch(ctx, handler, desc); err != nil {
 	if err := images.Dispatch(ctx, handler, desc); err != nil {
-		return nil, err
+		return images.Image{}, err
 	}
 	}
 	if schema1Converter != nil {
 	if schema1Converter != nil {
 		desc, err = schema1Converter.Convert(ctx)
 		desc, err = schema1Converter.Convert(ctx)
 		if err != nil {
 		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()
 	is := c.ImageService()
 	for {
 	for {
-		if created, err := is.Create(ctx, img.i); err != nil {
+		if created, err := is.Create(ctx, img); err != nil {
 			if !errdefs.IsAlreadyExists(err) {
 			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 err != nil {
 				// if image was removed, try create again
 				// if image was removed, try create again
 				if errdefs.IsNotFound(err) {
 				if errdefs.IsNotFound(err) {
 					continue
 					continue
 				}
 				}
-				return nil, err
+				return images.Image{}, err
 			}
 			}
 
 
-			img.i = updated
+			img = updated
 		} else {
 		} else {
-			img.i = created
+			img = created
 		}
 		}
+
 		return img, nil
 		return img, nil
 	}
 	}
 }
 }
@@ -403,10 +449,7 @@ func (c *Client) GetImage(ctx context.Context, ref string) (Image, error) {
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	return &image{
-		client: c,
-		i:      i,
-	}, nil
+	return NewImage(c, i), nil
 }
 }
 
 
 // ListImages returns all existing images
 // 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))
 	images := make([]Image, len(imgs))
 	for i, img := range imgs {
 	for i, img := range imgs {
-		images[i] = &image{
-			client: c,
-			i:      img,
-		}
+		images[i] = NewImage(c, img)
 	}
 	}
 	return images, nil
 	return images, nil
 }
 }
@@ -451,6 +491,8 @@ func (c *Client) NamespaceService() namespaces.Store {
 	if c.namespaceStore != nil {
 	if c.namespaceStore != nil {
 		return c.namespaceStore
 		return c.namespaceStore
 	}
 	}
+	c.connMu.Lock()
+	defer c.connMu.Unlock()
 	return NewNamespaceStoreFromClient(namespacesapi.NewNamespacesClient(c.conn))
 	return NewNamespaceStoreFromClient(namespacesapi.NewNamespacesClient(c.conn))
 }
 }
 
 
@@ -459,6 +501,8 @@ func (c *Client) ContainerService() containers.Store {
 	if c.containerStore != nil {
 	if c.containerStore != nil {
 		return c.containerStore
 		return c.containerStore
 	}
 	}
+	c.connMu.Lock()
+	defer c.connMu.Unlock()
 	return NewRemoteContainerStore(containersapi.NewContainersClient(c.conn))
 	return NewRemoteContainerStore(containersapi.NewContainersClient(c.conn))
 }
 }
 
 
@@ -467,6 +511,8 @@ func (c *Client) ContentStore() content.Store {
 	if c.contentStore != nil {
 	if c.contentStore != nil {
 		return c.contentStore
 		return c.contentStore
 	}
 	}
+	c.connMu.Lock()
+	defer c.connMu.Unlock()
 	return contentproxy.NewContentStore(contentapi.NewContentClient(c.conn))
 	return contentproxy.NewContentStore(contentapi.NewContentClient(c.conn))
 }
 }
 
 
@@ -475,6 +521,8 @@ func (c *Client) SnapshotService(snapshotterName string) snapshots.Snapshotter {
 	if c.snapshotters != nil {
 	if c.snapshotters != nil {
 		return c.snapshotters[snapshotterName]
 		return c.snapshotters[snapshotterName]
 	}
 	}
+	c.connMu.Lock()
+	defer c.connMu.Unlock()
 	return snproxy.NewSnapshotter(snapshotsapi.NewSnapshotsClient(c.conn), snapshotterName)
 	return snproxy.NewSnapshotter(snapshotsapi.NewSnapshotsClient(c.conn), snapshotterName)
 }
 }
 
 
@@ -483,6 +531,8 @@ func (c *Client) TaskService() tasks.TasksClient {
 	if c.taskService != nil {
 	if c.taskService != nil {
 		return c.taskService
 		return c.taskService
 	}
 	}
+	c.connMu.Lock()
+	defer c.connMu.Unlock()
 	return tasks.NewTasksClient(c.conn)
 	return tasks.NewTasksClient(c.conn)
 }
 }
 
 
@@ -491,6 +541,8 @@ func (c *Client) ImageService() images.Store {
 	if c.imageStore != nil {
 	if c.imageStore != nil {
 		return c.imageStore
 		return c.imageStore
 	}
 	}
+	c.connMu.Lock()
+	defer c.connMu.Unlock()
 	return NewImageStoreFromClient(imagesapi.NewImagesClient(c.conn))
 	return NewImageStoreFromClient(imagesapi.NewImagesClient(c.conn))
 }
 }
 
 
@@ -499,24 +551,32 @@ func (c *Client) DiffService() DiffService {
 	if c.diffService != nil {
 	if c.diffService != nil {
 		return c.diffService
 		return c.diffService
 	}
 	}
+	c.connMu.Lock()
+	defer c.connMu.Unlock()
 	return NewDiffServiceFromClient(diffapi.NewDiffClient(c.conn))
 	return NewDiffServiceFromClient(diffapi.NewDiffClient(c.conn))
 }
 }
 
 
 // IntrospectionService returns the underlying Introspection Client
 // IntrospectionService returns the underlying Introspection Client
 func (c *Client) IntrospectionService() introspectionapi.IntrospectionClient {
 func (c *Client) IntrospectionService() introspectionapi.IntrospectionClient {
+	c.connMu.Lock()
+	defer c.connMu.Unlock()
 	return introspectionapi.NewIntrospectionClient(c.conn)
 	return introspectionapi.NewIntrospectionClient(c.conn)
 }
 }
 
 
 // LeasesService returns the underlying Leases Client
 // LeasesService returns the underlying Leases Client
-func (c *Client) LeasesService() leasesapi.LeasesClient {
+func (c *Client) LeasesService() leases.Manager {
 	if c.leasesService != nil {
 	if c.leasesService != nil {
 		return c.leasesService
 		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
 // HealthService returns the underlying GRPC HealthClient
 func (c *Client) HealthService() grpc_health_v1.HealthClient {
 func (c *Client) HealthService() grpc_health_v1.HealthClient {
+	c.connMu.Lock()
+	defer c.connMu.Unlock()
 	return grpc_health_v1.NewHealthClient(c.conn)
 	return grpc_health_v1.NewHealthClient(c.conn)
 }
 }
 
 
@@ -525,11 +585,15 @@ func (c *Client) EventService() EventService {
 	if c.eventService != nil {
 	if c.eventService != nil {
 		return c.eventService
 		return c.eventService
 	}
 	}
+	c.connMu.Lock()
+	defer c.connMu.Unlock()
 	return NewEventServiceFromClient(eventsapi.NewEventsClient(c.conn))
 	return NewEventServiceFromClient(eventsapi.NewEventsClient(c.conn))
 }
 }
 
 
 // VersionService returns the underlying VersionClient
 // VersionService returns the underlying VersionClient
 func (c *Client) VersionService() versionservice.VersionClient {
 func (c *Client) VersionService() versionservice.VersionClient {
+	c.connMu.Lock()
+	defer c.connMu.Unlock()
 	return versionservice.NewVersionClient(c.conn)
 	return versionservice.NewVersionClient(c.conn)
 }
 }
 
 

+ 16 - 3
vendor/github.com/containerd/containerd/client_opts.go

@@ -18,14 +18,16 @@ package containerd
 
 
 import (
 import (
 	"github.com/containerd/containerd/images"
 	"github.com/containerd/containerd/images"
+	"github.com/containerd/containerd/platforms"
 	"github.com/containerd/containerd/remotes"
 	"github.com/containerd/containerd/remotes"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc"
 )
 )
 
 
 type clientOpts struct {
 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
 // 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
 // WithDialOpts allows grpc.DialOptions to be set on the connection
 func WithDialOpts(opts []grpc.DialOption) ClientOpt {
 func WithDialOpts(opts []grpc.DialOption) ClientOpt {
 	return func(c *clientOpts) error {
 	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
 // WithPlatform allows the caller to specify a platform to retrieve
 // content for
 // content for
 func WithPlatform(platform string) RemoteOpt {
 func WithPlatform(platform string) RemoteOpt {
+	if platform == "" {
+		platform = platforms.Default()
+	}
 	return func(_ *Client, c *RemoteContext) error {
 	return func(_ *Client, c *RemoteContext) error {
 		for _, p := range c.Platforms {
 		for _, p := range c.Platforms {
 			if p == platform {
 			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 {
 	if err != nil {
 		return nil, errors.Wrapf(err, "failed to get image %s for container", r.Image)
 		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) {
 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
 // WithSpec sets the provided spec on the container
 func WithSpec(s *oci.Spec, opts ...oci.SpecOpts) NewContainerOpts {
 func WithSpec(s *oci.Spec, opts ...oci.SpecOpts) NewContainerOpts {
 	return func(ctx context.Context, client *Client, c *containers.Container) error {
 	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
 		var err error
 		c.Spec, err = typeurl.MarshalAny(s)
 		c.Spec, err = typeurl.MarshalAny(s)
 		return err
 		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.
 	// Image specifies the image reference used for a container.
 	//
 	//
-	// This property is optional but immutable.
+	// This property is optional and mutable.
 	Image string
 	Image string
 
 
 	// Runtime specifies which runtime should be used when launching container
 	// 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
 	// look up the mounts from the snapshot service and include those on the
 	// task create request.
 	// task create request.
 	//
 	//
-	// This field is not required but immutable.
+	// This field is not required but mutable.
 	SnapshotKey string
 	SnapshotKey string
 
 
 	// Snapshotter specifies the snapshotter name used for rootfs
 	// Snapshotter specifies the snapshotter name used for rootfs

+ 46 - 1
vendor/github.com/containerd/containerd/containerstore.go

@@ -18,11 +18,15 @@ package containerd
 
 
 import (
 import (
 	"context"
 	"context"
+	"errors"
+	"io"
 
 
 	containersapi "github.com/containerd/containerd/api/services/containers/v1"
 	containersapi "github.com/containerd/containerd/api/services/containers/v1"
 	"github.com/containerd/containerd/containers"
 	"github.com/containerd/containerd/containers"
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/errdefs"
 	ptypes "github.com/gogo/protobuf/types"
 	ptypes "github.com/gogo/protobuf/types"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
 )
 )
 
 
 type remoteContainers struct {
 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) {
 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{
 	resp, err := r.client.List(ctx, &containersapi.ListContainersRequest{
 		Filters: filters,
 		Filters: filters,
 	})
 	})
 	if err != nil {
 	if err != nil {
 		return nil, errdefs.FromGRPC(err)
 		return nil, errdefs.FromGRPC(err)
 	}
 	}
-
 	return containersFromProto(resp.Containers), nil
 	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) {
 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
 	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.
 // status works like stat above except uses the path to the ingest.
 func (s *store) status(ingestPath string) (content.Status, error) {
 func (s *store) status(ingestPath string) (content.Status, error) {
 	dp := filepath.Join(ingestPath, "data")
 	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
 // NewImage returns a client image object from the metadata image
 func NewImage(client *Client, i images.Image) Image {
 func NewImage(client *Client, i images.Image) Image {
 	return &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 {
 type image struct {
 	client *Client
 	client *Client
 
 
-	i images.Image
+	i        images.Image
+	platform string
 }
 }
 
 
 func (i *image) Name() 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) {
 func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) {
 	provider := i.client.ContentStore()
 	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) {
 func (i *image) Size(ctx context.Context) (int64, error) {
 	provider := i.client.ContentStore()
 	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) {
 func (i *image) Config(ctx context.Context) (ocispec.Descriptor, error) {
 	provider := i.client.ContentStore()
 	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) {
 func (i *image) IsUnpacked(ctx context.Context, snapshotterName string) (bool, error) {
 	sn := i.client.SnapshotService(snapshotterName)
 	sn := i.client.SnapshotService(snapshotterName)
 	cs := i.client.ContentStore()
 	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 {
 	if err != nil {
 		return false, err
 		return false, err
 	}
 	}
@@ -117,7 +128,7 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string) error {
 	}
 	}
 	defer done(ctx)
 	defer done(ctx)
 
 
-	layers, err := i.getLayers(ctx, platforms.Default())
+	layers, err := i.getLayers(ctx, i.platform)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -154,7 +165,7 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string) error {
 	}
 	}
 
 
 	if unpacked {
 	if unpacked {
-		desc, err := i.i.Config(ctx, cs, platforms.Default())
+		desc, err := i.i.Config(ctx, cs, i.platform)
 		if err != nil {
 		if err != nil {
 			return err
 			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
 			imgrec = updated
 		}
 		}
 
 
-		images = append(images, &image{
-			client: c,
-			i:      imgrec,
-		})
+		images = append(images, NewImage(c, imgrec))
 	}
 	}
 	return images, nil
 	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"
 	"context"
 	"time"
 	"time"
 
 
-	leasesapi "github.com/containerd/containerd/api/services/leases/v1"
 	"github.com/containerd/containerd/leases"
 	"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
 // WithLease attaches a lease on the context
 func (c *Client) WithLease(ctx context.Context) (context.Context, func(context.Context) error, error) {
 func (c *Client) WithLease(ctx context.Context) (context.Context, func(context.Context) error, error) {
-	_, ok := leases.Lease(ctx)
+	_, ok := leases.FromContext(ctx)
 	if ok {
 	if ok {
 		return ctx, func(context.Context) error {
 		return ctx, func(context.Context) error {
 			return nil
 			return nil
 		}, 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 {
 	if err != nil {
 		return nil, nil, err
 		return nil, nil, err
 	}
 	}
 
 
-	ctx = leases.WithLease(ctx, l.ID())
+	ctx = leases.WithLease(ctx, l.ID)
 	return ctx, func(ctx context.Context) error {
 	return ctx, func(ctx context.Context) error {
-		return l.Delete(ctx)
+		return ls.Delete(ctx, l)
 	}, nil
 	}, 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)
 	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)
 	lid, ok := ctx.Value(leaseKey{}).(string)
 	if !ok {
 	if !ok {
 		return fromGRPCHeader(ctx)
 		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.
 // and is usually used to trace detailed behavior of the program.
 const TraceLevel = logrus.Level(uint32(logrus.DebugLevel + 1))
 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.
 // ParseLevel takes a string level and returns the Logrus log level constant.
 // It supports trace level.
 // It supports trace level.
 func ParseLevel(lvl string) (logrus.Level, error) {
 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/content"
 	"github.com/containerd/containerd/filters"
 	"github.com/containerd/containerd/filters"
 	"github.com/containerd/containerd/images"
 	"github.com/containerd/containerd/images"
+	"github.com/containerd/containerd/leases"
 )
 )
 
 
 func adaptImage(o interface{}) filters.Adaptor {
 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) {
 func checkMap(fieldpath []string, m map[string]string) (string, bool) {
 	if len(m) == 0 {
 	if len(m) == 0 {
 		return "", false
 		return "", false

+ 1 - 0
vendor/github.com/containerd/containerd/metadata/buckets.go

@@ -72,6 +72,7 @@ var (
 	bucketKeyCreatedAt   = []byte("createdat")
 	bucketKeyCreatedAt   = []byte("createdat")
 	bucketKeyExpected    = []byte("expected")
 	bucketKeyExpected    = []byte("expected")
 	bucketKeyRef         = []byte("ref")
 	bucketKeyRef         = []byte("ref")
+	bucketKeyExpireAt    = []byte("expireat")
 
 
 	deprecatedBucketKeyObjectIngest = []byte("ingest") // stores ingest links, deprecated in v1.2
 	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
 			return err
 		}
 		}
 
 
+		if err := removeIngestLease(ctx, tx, ref); err != nil {
+			return err
+		}
+
 		// if not shared content, delete active ingest on backend
 		// if not shared content, delete active ingest on backend
 		if expected == "" {
 		if expected == "" {
 			return cs.Store.Abort(ctx, bref)
 			return cs.Store.Abort(ctx, bref)
@@ -395,6 +399,11 @@ func (cs *contentStore) Writer(ctx context.Context, opts ...content.WriterOpt) (
 			return err
 			return err
 		}
 		}
 
 
+		leased, err := addIngestLease(ctx, tx, wOpts.Ref)
+		if err != nil {
+			return err
+		}
+
 		brefb := bkt.Get(bucketKeyRef)
 		brefb := bkt.Get(bucketKeyRef)
 		if brefb == nil {
 		if brefb == nil {
 			sid, err := bkt.NextSequence()
 			sid, err := bkt.NextSequence()
@@ -409,6 +418,18 @@ func (cs *contentStore) Writer(ctx context.Context, opts ...content.WriterOpt) (
 		} else {
 		} else {
 			bref = string(brefb)
 			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 shared {
 			if err := bkt.Put(bucketKeyExpected, []byte(wOpts.Desc.Digest)); err != nil {
 			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 {
 		if err != nil {
 			return err
 			return err
 		}
 		}
+		if err := removeIngestLease(ctx, tx, nw.ref); err != nil {
+			return err
+		}
 		return addContentLease(ctx, tx, dgst)
 		return addContentLease(ctx, tx, dgst)
 	})
 	})
 }
 }
@@ -697,6 +721,30 @@ func writeInfo(info *content.Info, bkt *bolt.Bucket) error {
 	return bkt.Put(bucketKeySize, sizeEncoded)
 	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) {
 func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, err error) {
 	cs.l.Lock()
 	cs.l.Lock()
 	t1 := time.Now()
 	t1 := time.Now()
@@ -707,7 +755,8 @@ func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, er
 		cs.l.Unlock()
 		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 {
 	if err := cs.db.View(func(tx *bolt.Tx) error {
 		v1bkt := tx.Bucket(bucketKeyVersion)
 		v1bkt := tx.Bucket(bucketKeyVersion)
 		if v1bkt == nil {
 		if v1bkt == nil {
@@ -730,7 +779,7 @@ func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, er
 			if bbkt != nil {
 			if bbkt != nil {
 				if err := bbkt.ForEach(func(ck, cv []byte) error {
 				if err := bbkt.ForEach(func(ck, cv []byte) error {
 					if cv == nil {
 					if cv == nil {
-						seen[string(ck)] = struct{}{}
+						contentSeen[string(ck)] = struct{}{}
 					}
 					}
 					return nil
 					return nil
 				}); err != nil {
 				}); err != nil {
@@ -742,9 +791,17 @@ func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, er
 			if ibkt != nil {
 			if ibkt != nil {
 				if err := ibkt.ForEach(func(ref, v []byte) error {
 				if err := ibkt.ForEach(func(ref, v []byte) error {
 					if v == nil {
 					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 {
 						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
 					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 {
 	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 {
 			if err := cs.Store.Delete(ctx, info.Digest); err != nil {
 				return err
 				return err
 			}
 			}
@@ -768,5 +825,40 @@ func (cs *contentStore) garbageCollect(ctx context.Context) (d time.Duration, er
 		}
 		}
 		return nil
 		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
 	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 {
 				if idx := strings.IndexRune(n.Key, '/'); idx > 0 {
 					m.dirtySS[n.Key[:idx]] = struct{}{}
 					m.dirtySS[n.Key[:idx]] = struct{}{}
 				}
 				}
-			} else if n.Type == ResourceContent {
+			} else if n.Type == ResourceContent || n.Type == ResourceIngest {
 				m.dirtyCS = true
 				m.dirtyCS = true
 			}
 			}
 			return remove(ctx, tx, n)
 			return remove(ctx, tx, n)

+ 138 - 17
vendor/github.com/containerd/containerd/metadata/gc.go

@@ -21,6 +21,7 @@ import (
 	"context"
 	"context"
 	"fmt"
 	"fmt"
 	"strings"
 	"strings"
+	"time"
 
 
 	"github.com/boltdb/bolt"
 	"github.com/boltdb/bolt"
 	"github.com/containerd/containerd/gc"
 	"github.com/containerd/containerd/gc"
@@ -39,12 +40,17 @@ const (
 	ResourceContainer
 	ResourceContainer
 	// ResourceTask specifies a task resource
 	// ResourceTask specifies a task resource
 	ResourceTask
 	ResourceTask
+	// ResourceLease specifies a lease
+	ResourceLease
+	// ResourceIngest specifies a content ingest
+	ResourceIngest
 )
 )
 
 
 var (
 var (
 	labelGCRoot       = []byte("containerd.io/gc.root")
 	labelGCRoot       = []byte("containerd.io/gc.root")
 	labelGCSnapRef    = []byte("containerd.io/gc.ref.snapshot.")
 	labelGCSnapRef    = []byte("containerd.io/gc.ref.snapshot.")
 	labelGCContentRef = []byte("containerd.io/gc.ref.content")
 	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 {
 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
 		return nil
 	}
 	}
 
 
+	expThreshold := time.Now()
+
 	// iterate through each namespace
 	// iterate through each namespace
 	v1c := v1bkt.Cursor()
 	v1c := v1bkt.Cursor()
 
 
@@ -71,6 +79,30 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
 				}
 				}
 				libkt := lbkt.Bucket(k)
 				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)
 				cbkt := libkt.Bucket(bucketKeyObjectContent)
 				if cbkt != nil {
 				if cbkt != nil {
 					if err := cbkt.ForEach(func(k, v []byte) error {
 					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
 				return nil
 			}); err != nil {
 			}); err != nil {
 				return err
 				return err
@@ -141,16 +187,39 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
 
 
 		cbkt := nbkt.Bucket(bucketKeyObjectContent)
 		cbkt := nbkt.Bucket(bucketKeyObjectContent)
 		if cbkt != nil {
 		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
 					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)
 		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
 	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)
 		nbkt := v1bkt.Bucket(k)
 		ns := string(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)
 		sbkt := nbkt.Bucket(bucketKeyObjectSnapshots)
 		if sbkt != nil {
 		if sbkt != nil {
 			if err := sbkt.ForEach(func(sk, sv []byte) error {
 			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)
 		cbkt := nbkt.Bucket(bucketKeyObjectContent)
 		if cbkt != nil {
 		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)
 			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]))
 				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
 	return nil

+ 94 - 42
vendor/github.com/containerd/containerd/metadata/leases.go

@@ -22,6 +22,7 @@ import (
 
 
 	"github.com/boltdb/bolt"
 	"github.com/boltdb/bolt"
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/filters"
 	"github.com/containerd/containerd/leases"
 	"github.com/containerd/containerd/leases"
 	"github.com/containerd/containerd/metadata/boltutil"
 	"github.com/containerd/containerd/metadata/boltutil"
 	"github.com/containerd/containerd/namespaces"
 	"github.com/containerd/containerd/namespaces"
@@ -29,17 +30,6 @@ import (
 	"github.com/pkg/errors"
 	"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
 // LeaseManager manages the create/delete lifecyle of leases
 // and also returns existing leases
 // and also returns existing leases
 type LeaseManager struct {
 type LeaseManager struct {
@@ -55,49 +45,56 @@ func NewLeaseManager(tx *bolt.Tx) *LeaseManager {
 }
 }
 
 
 // Create creates a new lease using the provided lease
 // 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)
 	namespace, err := namespaces.NamespaceRequired(ctx)
 	if err != nil {
 	if err != nil {
-		return Lease{}, err
+		return leases.Lease{}, err
 	}
 	}
 
 
 	topbkt, err := createBucketIfNotExists(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases)
 	topbkt, err := createBucketIfNotExists(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases)
 	if err != nil {
 	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 != nil {
 		if err == bolt.ErrBucketExists {
 		if err == bolt.ErrBucketExists {
 			err = errdefs.ErrAlreadyExists
 			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()
 	t := time.Now().UTC()
 	createdAt, err := t.MarshalBinary()
 	createdAt, err := t.MarshalBinary()
 	if err != nil {
 	if err != nil {
-		return Lease{}, err
+		return leases.Lease{}, err
 	}
 	}
 	if err := txbkt.Put(bucketKeyCreatedAt, createdAt); err != nil {
 	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
 // 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)
 	namespace, err := namespaces.NamespaceRequired(ctx)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -105,26 +102,34 @@ func (lm *LeaseManager) Delete(ctx context.Context, lid string) error {
 
 
 	topbkt := getBucket(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases)
 	topbkt := getBucket(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases)
 	if topbkt == nil {
 	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 err
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
 // List lists all active leases
 // 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)
 	namespace, err := namespaces.NamespaceRequired(ctx)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		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)
 	topbkt := getBucket(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases)
 	if topbkt == nil {
 	if topbkt == nil {
-		return leases, nil
+		return ll, nil
 	}
 	}
 
 
 	if err := topbkt.ForEach(func(k, v []byte) error {
 	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)
 		txbkt := topbkt.Bucket(k)
 
 
-		l := Lease{
+		l := leases.Lease{
 			ID: string(k),
 			ID: string(k),
 		}
 		}
 
 
@@ -150,21 +155,20 @@ func (lm *LeaseManager) List(ctx context.Context, includeResources bool, filter
 		}
 		}
 		l.Labels = labels
 		l.Labels = labels
 
 
-		// TODO: Read Snapshots
-		// TODO: Read Content
-
-		leases = append(leases, l)
+		if filter.Match(adaptLease(l)) {
+			ll = append(ll, l)
+		}
 
 
 		return nil
 		return nil
 	}); err != nil {
 	}); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	return leases, nil
+	return ll, nil
 }
 }
 
 
 func addSnapshotLease(ctx context.Context, tx *bolt.Tx, snapshotter, key string) error {
 func addSnapshotLease(ctx context.Context, tx *bolt.Tx, snapshotter, key string) error {
-	lid, ok := leases.Lease(ctx)
+	lid, ok := leases.FromContext(ctx)
 	if !ok {
 	if !ok {
 		return nil
 		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 {
 func removeSnapshotLease(ctx context.Context, tx *bolt.Tx, snapshotter, key string) error {
-	lid, ok := leases.Lease(ctx)
+	lid, ok := leases.FromContext(ctx)
 	if !ok {
 	if !ok {
 		return nil
 		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 {
 func addContentLease(ctx context.Context, tx *bolt.Tx, dgst digest.Digest) error {
-	lid, ok := leases.Lease(ctx)
+	lid, ok := leases.FromContext(ctx)
 	if !ok {
 	if !ok {
 		return nil
 		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 {
 func removeContentLease(ctx context.Context, tx *bolt.Tx, dgst digest.Digest) error {
-	lid, ok := leases.Lease(ctx)
+	lid, ok := leases.FromContext(ctx)
 	if !ok {
 	if !ok {
 		return nil
 		return nil
 	}
 	}
@@ -255,3 +259,51 @@ func removeContentLease(ctx context.Context, tx *bolt.Tx, dgst digest.Digest) er
 
 
 	return bkt.Delete([]byte(dgst.String()))
 	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
 package mount
 
 
 import (
 import (
+	"fmt"
+	"os"
+	"path"
 	"strings"
 	"strings"
 	"time"
 	"time"
 
 
+	"github.com/containerd/containerd/sys"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 	"golang.org/x/sys/unix"
 	"golang.org/x/sys/unix"
 )
 )
 
 
+var pagesize = 4096
+
+func init() {
+	pagesize = os.Getpagesize()
+}
+
 // Mount to the provided target path
 // Mount to the provided target path
 func (m *Mount) Mount(target string) error {
 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.
 	// propagation types.
 	const ptypes = unix.MS_SHARED | unix.MS_PRIVATE | unix.MS_SLAVE | unix.MS_UNBINDABLE
 	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 != "" {
 	if flags&unix.MS_REMOUNT == 0 || data != "" {
 		// Initial call applying all non-propagation flags for mount
 		// Initial call applying all non-propagation flags for mount
 		// or remount with changed data
 		// 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
 			return err
 		}
 		}
 	}
 	}
@@ -155,3 +180,129 @@ func parseMountOptions(options []string) (int, string) {
 	}
 	}
 	return flag, strings.Join(data, ",")
 	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
 // CleanupTempMounts all temp mounts and remove the directories
-func CleanupTempMounts(flags int) error {
+func CleanupTempMounts(flags int) (warnings []error, err error) {
 	mounts, err := Self()
 	mounts, err := Self()
 	if err != nil {
 	if err != nil {
-		return err
+		return nil, err
 	}
 	}
 	var toUnmount []string
 	var toUnmount []string
 	for _, m := range mounts {
 	for _, m := range mounts {
@@ -53,11 +53,12 @@ func CleanupTempMounts(flags int) error {
 	sort.Sort(sort.Reverse(sort.StringSlice(toUnmount)))
 	sort.Sort(sort.Reverse(sort.StringSlice(toUnmount)))
 	for _, path := range toUnmount {
 	for _, path := range toUnmount {
 		if err := UnmountAll(path, flags); err != nil {
 		if err := UnmountAll(path, flags); err != nil {
-			return err
+			warnings = append(warnings, err)
+			continue
 		}
 		}
 		if err := os.Remove(path); err != nil {
 		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
 // 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 {
 	if err != nil {
 		return nil, err
 		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 {
 	for _, o := range opts {
 		if err := o(ctx, client, c, s); err != nil {
 		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 (
 import (
 	"context"
 	"context"
+	"encoding/json"
+	"io/ioutil"
 	"strings"
 	"strings"
 
 
 	"github.com/containerd/containerd/containers"
 	"github.com/containerd/containerd/containers"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
+	"github.com/pkg/errors"
 )
 )
 
 
 // SpecOpts sets spec specific information to a newly generated OCI spec
 // 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
 // WithProcessArgs replaces the args on the generated spec
 func WithProcessArgs(args ...string) SpecOpts {
 func WithProcessArgs(args ...string) SpecOpts {
 	return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
 	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
 // WithImageConfig configures the spec to from the configuration of an Image
 func WithImageConfig(image Image) SpecOpts {
 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 {
 	return func(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
 		ic, err := image.Config(ctx)
 		ic, err := image.Config(ctx)
 		if err != nil {
 		if err != nil {
@@ -133,6 +139,9 @@ func WithImageConfig(image Image) SpecOpts {
 		setProcess(s)
 		setProcess(s)
 		s.Process.Env = append(s.Process.Env, config.Env...)
 		s.Process.Env = append(s.Process.Env, config.Env...)
 		cmd := config.Cmd
 		cmd := config.Cmd
+		if len(args) > 0 {
+			cmd = args
+		}
 		s.Process.Args = append(config.Entrypoint, cmd...)
 		s.Process.Args = append(config.Entrypoint, cmd...)
 		cwd := config.WorkingDir
 		cwd := config.WorkingDir
 		if cwd == "" {
 		if cwd == "" {
@@ -348,8 +357,8 @@ func WithUIDGID(uid, gid uint32) SpecOpts {
 
 
 // WithUserID sets the correct UID and GID for the container based
 // WithUserID sets the correct UID and GID for the container based
 // on the image's /etc/passwd contents. If /etc/passwd does not exist,
 // 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 {
 func WithUserID(uid uint32) SpecOpts {
 	return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) {
 	return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) {
 		setProcess(s)
 		setProcess(s)
@@ -362,7 +371,7 @@ func WithUserID(uid uint32) SpecOpts {
 			})
 			})
 			if err != nil {
 			if err != nil {
 				if os.IsNotExist(err) || err == errNoUsersFound {
 				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 nil
 				}
 				}
 				return err
 				return err
@@ -388,7 +397,7 @@ func WithUserID(uid uint32) SpecOpts {
 			})
 			})
 			if err != nil {
 			if err != nil {
 				if os.IsNotExist(err) || err == errNoUsersFound {
 				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 nil
 				}
 				}
 				return err
 				return err
@@ -593,6 +602,110 @@ func WithSeccompUnconfined(_ context.Context, _ Client, _ *containers.Container,
 	return nil
 	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
 // WithPrivileged sets up options for a privileged container
 // TODO(justincormack) device handling
 // TODO(justincormack) device handling
 var WithPrivileged = Compose(
 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)
 	ns, err := namespaces.NamespaceRequired(ctx)
 	if err != nil {
 	if err != nil {
-		return nil, err
+		return err
 	}
 	}
-	s := &Spec{
+
+	*s = Spec{
 		Version: specs.Version,
 		Version: specs.Version,
 		Root: &specs.Root{
 		Root: &specs.Root{
 			Path: defaultRootfsPath,
 			Path: defaultRootfsPath,
@@ -183,5 +184,5 @@ func createDefaultSpec(ctx context.Context, id string) (*Spec, error) {
 			Namespaces: defaultNamespaces(),
 			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"
 	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,
 		Version: specs.Version,
 		Root:    &specs.Root{},
 		Root:    &specs.Root{},
 		Process: &specs.Process{
 		Process: &specs.Process{
@@ -39,5 +39,6 @@ func createDefaultSpec(ctx context.Context, id string) (*Spec, error) {
 				AllowUnqualifiedDNSQuery: true,
 				AllowUnqualifiedDNSQuery: true,
 			},
 			},
 		},
 		},
-	}, nil
+	}
+	return nil
 }
 }

+ 11 - 0
vendor/github.com/containerd/containerd/platforms/platforms.go

@@ -109,6 +109,7 @@ package platforms
 import (
 import (
 	"regexp"
 	"regexp"
 	"runtime"
 	"runtime"
+	"strconv"
 	"strings"
 	"strings"
 
 
 	"github.com/containerd/containerd/errdefs"
 	"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)
 	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.
 // Format returns a string specifier from the provided platform specification.
 func Format(platform specs.Platform) string {
 func Format(platform specs.Platform) string {
 	if platform.OS == "" {
 	if platform.OS == "" {

+ 2 - 0
vendor/github.com/containerd/containerd/plugin/plugin.go

@@ -58,6 +58,8 @@ const (
 	InternalPlugin Type = "io.containerd.internal.v1"
 	InternalPlugin Type = "io.containerd.internal.v1"
 	// RuntimePlugin implements a runtime
 	// RuntimePlugin implements a runtime
 	RuntimePlugin Type = "io.containerd.runtime.v1"
 	RuntimePlugin Type = "io.containerd.runtime.v1"
+	// RuntimePluginV2 implements a runtime v2
+	RuntimePluginV2 Type = "io.containerd.runtime.v2"
 	// ServicePlugin implements a internal service
 	// ServicePlugin implements a internal service
 	ServicePlugin Type = "io.containerd.service.v1"
 	ServicePlugin Type = "io.containerd.service.v1"
 	// GRPCPlugin implements a grpc service
 	// GRPCPlugin implements a grpc service

+ 27 - 9
vendor/github.com/containerd/containerd/remotes/docker/resolver.go

@@ -53,6 +53,7 @@ var (
 
 
 type dockerResolver struct {
 type dockerResolver struct {
 	credentials func(string) (string, string, error)
 	credentials func(string) (string, string, error)
+	host        func(string) (string, error)
 	plainHTTP   bool
 	plainHTTP   bool
 	client      *http.Client
 	client      *http.Client
 	tracker     StatusTracker
 	tracker     StatusTracker
@@ -65,6 +66,9 @@ type ResolverOptions struct {
 	// is interpretted as a long lived token.
 	// is interpretted as a long lived token.
 	Credentials func(string) (string, string, error)
 	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 specifies to use plain http and not https
 	PlainHTTP bool
 	PlainHTTP bool
 
 
@@ -77,14 +81,27 @@ type ResolverOptions struct {
 	Tracker StatusTracker
 	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
 // NewResolver returns a new resolver to a Docker registry
 func NewResolver(options ResolverOptions) remotes.Resolver {
 func NewResolver(options ResolverOptions) remotes.Resolver {
 	tracker := options.Tracker
 	tracker := options.Tracker
 	if tracker == nil {
 	if tracker == nil {
 		tracker = NewInMemoryTracker()
 		tracker = NewInMemoryTracker()
 	}
 	}
+	host := options.Host
+	if host == nil {
+		host = DefaultHost
+	}
 	return &dockerResolver{
 	return &dockerResolver{
 		credentials: options.Credentials,
 		credentials: options.Credentials,
+		host:        host,
 		plainHTTP:   options.PlainHTTP,
 		plainHTTP:   options.PlainHTTP,
 		client:      options.Client,
 		client:      options.Client,
 		tracker:     tracker,
 		tracker:     tracker,
@@ -270,18 +287,19 @@ func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {
 	)
 	)
 
 
 	host := refspec.Hostname()
 	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 {
 	if r.credentials != nil {
 		username, secret, err = r.credentials(base.Host)
 		username, secret, err = r.credentials(base.Host)
 		if err != nil {
 		if err != nil {

+ 18 - 9
vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go

@@ -18,7 +18,6 @@ package schema1
 
 
 import (
 import (
 	"bytes"
 	"bytes"
-	"compress/gzip"
 	"context"
 	"context"
 	"encoding/base64"
 	"encoding/base64"
 	"encoding/json"
 	"encoding/json"
@@ -31,6 +30,7 @@ import (
 
 
 	"golang.org/x/sync/errgroup"
 	"golang.org/x/sync/errgroup"
 
 
+	"github.com/containerd/containerd/archive/compression"
 	"github.com/containerd/containerd/content"
 	"github.com/containerd/containerd/content"
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/images"
 	"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")
 	log.G(ctx).Debug("fetch blob")
 
 
 	var (
 	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
 	// 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()
 		defer ra.Close()
 
 
-		gr, err := gzip.NewReader(content.NewReader(ra))
+		r, err := compression.DecompressStream(content.NewReader(ra))
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
-		defer gr.Close()
 
 
-		_, err = io.Copy(calc, gr)
+		compressMethod = r.GetCompression()
+		_, err = io.Copy(calc, r)
+		r.Close()
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
@@ -303,13 +305,14 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro
 		pr, pw := io.Pipe()
 		pr, pw := io.Pipe()
 
 
 		eg.Go(func() error {
 		eg.Go(func() error {
-			gr, err := gzip.NewReader(pr)
+			r, err := compression.DecompressStream(pr)
 			if err != nil {
 			if err != nil {
 				return err
 				return err
 			}
 			}
-			defer gr.Close()
 
 
-			_, err = io.Copy(calc, gr)
+			compressMethod = r.GetCompression()
+			_, err = io.Copy(calc, r)
+			r.Close()
 			pr.CloseWithError(err)
 			pr.CloseWithError(err)
 			return err
 			return err
 		})
 		})
@@ -333,6 +336,11 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro
 		desc.Size = info.Size
 		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()
 	state := calc.State()
 
 
 	c.mu.Lock()
 	c.mu.Lock()
@@ -342,6 +350,7 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro
 
 
 	return nil
 	return nil
 }
 }
+
 func (c *Converter) schema1ManifestHistory() ([]ocispec.History, []digest.Digest, error) {
 func (c *Converter) schema1ManifestHistory() ([]ocispec.History, []digest.Digest, error) {
 	if c.pulledManifest == nil {
 	if c.pulledManifest == nil {
 		return nil, nil, errors.New("missing schema 1 manifest for conversion")
 		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 (
 import (
 	"context"
 	"context"
-	"crypto/rand"
 	"encoding/base64"
 	"encoding/base64"
 	"fmt"
 	"fmt"
+	"math/rand"
 	"time"
 	"time"
 
 
 	"github.com/containerd/containerd/diff"
 	"github.com/containerd/containerd/diff"

+ 7 - 5
vendor/github.com/containerd/containerd/runtime/runtime.go

@@ -42,8 +42,12 @@ type CreateOpts struct {
 	IO IO
 	IO IO
 	// Checkpoint digest to restore container state
 	// Checkpoint digest to restore container state
 	Checkpoint string
 	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
 // Exit information for a process
@@ -64,7 +68,5 @@ type PlatformRuntime interface {
 	Get(context.Context, string) (Task, error)
 	Get(context.Context, string) (Task, error)
 	// Tasks returns all the current tasks for the runtime.
 	// Tasks returns all the current tasks for the runtime.
 	// Any container runs at most one task at a time.
 	// 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
 	Start(context.Context) error
 	// Wait for the process to exit
 	// Wait for the process to exit
 	Wait(context.Context) (*Exit, error)
 	Wait(context.Context) (*Exit, error)
+	// Delete deletes the process
+	Delete(context.Context) (*Exit, error)
 }
 }
 
 
 // Task is the runtime object for an executing container
 // Task is the runtime object for an executing container
 type Task interface {
 type Task interface {
 	Process
 	Process
 
 
-	// Information of the container
-	Info() TaskInfo
+	// Namespace that the task exists in
+	Namespace() string
 	// Pause pauses the container process
 	// Pause pauses the container process
 	Pause(context.Context) error
 	Pause(context.Context) error
 	// Resume unpauses the container process
 	// Resume unpauses the container process
@@ -64,14 +66,12 @@ type Task interface {
 	Pids(context.Context) ([]ProcessInfo, error)
 	Pids(context.Context) ([]ProcessInfo, error)
 	// Checkpoint checkpoints a container to an image with live system data
 	// Checkpoint checkpoints a container to an image with live system data
 	Checkpoint(context.Context, string, *types.Any) error
 	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 sets the provided resources to a running task
 	Update(context.Context, *types.Any) error
 	Update(context.Context, *types.Any) error
 	// Process returns a process within the task for the provided id
 	// Process returns a process within the task for the provided id
 	Process(context.Context, string) (Process, error)
 	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
 // 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
 // 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()
 	l.mu.Lock()
 	defer l.mu.Unlock()
 	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)
 	namespace, err := namespaces.NamespaceRequired(ctx)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	var o []Task
 	tasks, ok := l.tasks[namespace]
 	tasks, ok := l.tasks[namespace]
 	if !ok {
 	if !ok {
 		return o, nil
 		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/events/exchange"
 	"github.com/containerd/containerd/runtime/linux/runctypes"
 	"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"
 	"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) {
 func (e *execProcess) setExited(status int) {
 	e.status = status
 	e.status = status
 	e.exited = time.Now()
 	e.exited = time.Now()
-	e.parent.platform.ShutdownConsole(context.Background(), e.console)
+	e.parent.Platform.ShutdownConsole(context.Background(), e.console)
 	close(e.waitBlock)
 	close(e.waitBlock)
 }
 }
 
 
@@ -180,7 +180,7 @@ func (e *execProcess) start(ctx context.Context) (err error) {
 		if err != nil {
 		if err != nil {
 			return errors.Wrap(err, "failed to retrieve console master")
 			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")
 			return errors.Wrap(err, "failed to start console copy")
 		}
 		}
 	} else if !e.stdio.IsNull() {
 	} 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/console"
 	"github.com/containerd/containerd/log"
 	"github.com/containerd/containerd/log"
 	"github.com/containerd/containerd/mount"
 	"github.com/containerd/containerd/mount"
-	"github.com/containerd/containerd/runtime/linux/runctypes"
 	"github.com/containerd/containerd/runtime/proc"
 	"github.com/containerd/containerd/runtime/proc"
 	"github.com/containerd/fifo"
 	"github.com/containerd/fifo"
 	runc "github.com/containerd/go-runc"
 	runc "github.com/containerd/go-runc"
-	"github.com/containerd/typeurl"
 	google_protobuf "github.com/gogo/protobuf/types"
 	google_protobuf "github.com/gogo/protobuf/types"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
@@ -59,23 +57,25 @@ type Init struct {
 
 
 	waitBlock chan 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
 // 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{
 	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,
 		status:    0,
 		waitBlock: make(chan struct{}),
 		waitBlock: make(chan struct{}),
-		IoUID:     int(options.IoUid),
-		IoGID:     int(options.IoGid),
 	}
 	}
 	p.initState = &createdState{p: p}
 	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 (
 	var (
 		err    error
 		err    error
 		socket *runc.Socket
 		socket *runc.Socket
 	)
 	)
 	if r.Terminal {
 	if r.Terminal {
 		if socket, err = runc.NewTempConsoleSocket(); err != nil {
 		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()
 		defer socket.Close()
 	} else if hasNoIO(r) {
 	} else if hasNoIO(r) {
 		if p.io, err = runc.NewNullIO(); err != nil {
 		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 {
 	} 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 != "" {
 	if r.Checkpoint != "" {
 		opts := &runc.RestoreOpts{
 		opts := &runc.RestoreOpts{
 			CheckpointOpts: runc.CheckpointOpts{
 			CheckpointOpts: runc.CheckpointOpts{
 				ImagePath:  r.Checkpoint,
 				ImagePath:  r.Checkpoint,
-				WorkDir:    p.workDir,
+				WorkDir:    p.WorkDir,
 				ParentPath: r.ParentCheckpoint,
 				ParentPath: r.ParentCheckpoint,
 			},
 			},
 			PidFile:     pidFile,
 			PidFile:     pidFile,
 			IO:          p.io,
 			IO:          p.io,
-			NoPivot:     options.NoPivotRoot,
+			NoPivot:     p.NoPivotRoot,
 			Detach:      true,
 			Detach:      true,
 			NoSubreaper: true,
 			NoSubreaper: true,
 		}
 		}
@@ -185,25 +145,24 @@ func New(context context.Context, path, workDir, runtimeRoot, namespace, criu st
 			p:    p,
 			p:    p,
 			opts: opts,
 			opts: opts,
 		}
 		}
-		success = true
-		return p, nil
+		return nil
 	}
 	}
 	opts := &runc.CreateOpts{
 	opts := &runc.CreateOpts{
 		PidFile:      pidFile,
 		PidFile:      pidFile,
 		IO:           p.io,
 		IO:           p.io,
-		NoPivot:      options.NoPivotRoot,
-		NoNewKeyring: options.NoNewKeyring,
+		NoPivot:      p.NoPivotRoot,
+		NoNewKeyring: p.NoNewKeyring,
 	}
 	}
 	if socket != nil {
 	if socket != nil {
 		opts.ConsoleSocket = socket
 		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 != "" {
 	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 {
 		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.stdin = sc
 		p.closers = append(p.closers, 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 {
 	if socket != nil {
 		console, err := socket.ReceiveMaster()
 		console, err := socket.ReceiveMaster()
 		if err != nil {
 		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 {
 		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
 		p.console = console
 	} else if !hasNoIO(r) {
 	} 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()
 	copyWaitGroup.Wait()
 	pid, err := runc.ReadPidFile(pidFile)
 	pid, err := runc.ReadPidFile(pidFile)
 	if err != nil {
 	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
 	p.pid = pid
-	success = true
-	return p, nil
+	return nil
 }
 }
 
 
 // Wait for the process to exit
 // Wait for the process to exit
@@ -286,7 +244,7 @@ func (p *Init) start(context context.Context) error {
 func (p *Init) setExited(status int) {
 func (p *Init) setExited(status int) {
 	p.exited = time.Now()
 	p.exited = time.Now()
 	p.status = status
 	p.status = status
-	p.platform.ShutdownConsole(context.Background(), p.console)
+	p.Platform.ShutdownConsole(context.Background(), p.console)
 	close(p.waitBlock)
 	close(p.waitBlock)
 }
 }
 
 
@@ -312,7 +270,7 @@ func (p *Init) delete(context context.Context) error {
 		}
 		}
 		p.io.Close()
 		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")
 		log.G(context).WithError(err2).Warn("failed to cleanup rootfs mount")
 		if err == nil {
 		if err == nil {
 			err = errors.Wrap(err2, "failed rootfs umount")
 			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 {
 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
 	var actions []runc.CheckpointAction
-	if !options.Exit {
+	if !r.Exit {
 		actions = append(actions, runc.LeaveRunning)
 		actions = append(actions, runc.LeaveRunning)
 	}
 	}
-	work := filepath.Join(p.workDir, "criu-work")
+	work := filepath.Join(p.WorkDir, "criu-work")
 	defer os.RemoveAll(work)
 	defer os.RemoveAll(work)
 	if err := p.runtime.Checkpoint(context, p.id, &runc.CheckpointOpts{
 	if err := p.runtime.Checkpoint(context, p.id, &runc.CheckpointOpts{
 		WorkDir:                  work,
 		WorkDir:                  work,
 		ImagePath:                r.Path,
 		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 {
 	}, 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 {
 		if cerr := copyFile(dumpLog, filepath.Join(work, "dump.log")); cerr != nil {
 			log.G(context).Error(err)
 			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
 		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")
 		return p.runtimeError(err, "OCI runtime restore failed")
 	}
 	}
 	if sio.Stdin != "" {
 	if sio.Stdin != "" {
@@ -226,7 +226,7 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
 		if err != nil {
 		if err != nil {
 			return errors.Wrap(err, "failed to retrieve console master")
 			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 {
 		if err != nil {
 			return errors.Wrap(err, "failed to start console copy")
 			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
 // CheckpointConfig holds task checkpoint configuration
 type CheckpointConfig struct {
 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/api/types/task"
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/runtime"
 	"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/containerd/ttrpc"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 )
 )
@@ -149,3 +149,18 @@ func (p *Process) Wait(ctx context.Context) (*runtime.Exit, error) {
 		Status:    r.ExitStatus,
 		Status:    r.ExitStatus,
 	}, nil
 	}, 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/platforms"
 	"github.com/containerd/containerd/plugin"
 	"github.com/containerd/containerd/plugin"
 	"github.com/containerd/containerd/runtime"
 	"github.com/containerd/containerd/runtime"
-	"github.com/containerd/containerd/runtime/linux/proc"
 	"github.com/containerd/containerd/runtime/linux/runctypes"
 	"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"
 	runc "github.com/containerd/go-runc"
 	"github.com/containerd/typeurl"
 	"github.com/containerd/typeurl"
 	ptypes "github.com/gogo/protobuf/types"
 	ptypes "github.com/gogo/protobuf/types"
@@ -69,7 +69,6 @@ func init() {
 		ID:     "linux",
 		ID:     "linux",
 		InitFn: New,
 		InitFn: New,
 		Requires: []plugin.Type{
 		Requires: []plugin.Type{
-			plugin.TaskMonitorPlugin,
 			plugin.MetadataPlugin,
 			plugin.MetadataPlugin,
 		},
 		},
 		Config: &Config{
 		Config: &Config{
@@ -105,10 +104,6 @@ func New(ic *plugin.InitContext) (interface{}, error) {
 	if err := os.MkdirAll(ic.State, 0711); err != nil {
 	if err := os.MkdirAll(ic.State, 0711); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	monitor, err := ic.Get(plugin.TaskMonitorPlugin)
-	if err != nil {
-		return nil, err
-	}
 	m, err := ic.Get(plugin.MetadataPlugin)
 	m, err := ic.Get(plugin.MetadataPlugin)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
@@ -117,7 +112,6 @@ func New(ic *plugin.InitContext) (interface{}, error) {
 	r := &Runtime{
 	r := &Runtime{
 		root:    ic.Root,
 		root:    ic.Root,
 		state:   ic.State,
 		state:   ic.State,
-		monitor: monitor.(runtime.TaskMonitor),
 		tasks:   runtime.NewTaskList(),
 		tasks:   runtime.NewTaskList(),
 		db:      m.(*metadata.DB),
 		db:      m.(*metadata.DB),
 		address: ic.Address,
 		address: ic.Address,
@@ -128,8 +122,6 @@ func New(ic *plugin.InitContext) (interface{}, error) {
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-
-	// TODO: need to add the tasks to the monitor
 	for _, t := range tasks {
 	for _, t := range tasks {
 		if err := r.tasks.AddWithNamespace(t.namespace, t); err != nil {
 		if err := r.tasks.AddWithNamespace(t.namespace, t); err != nil {
 			return nil, err
 			return nil, err
@@ -144,10 +136,9 @@ type Runtime struct {
 	state   string
 	state   string
 	address 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
 	config *Config
 }
 }
@@ -189,8 +180,8 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts
 	shimopt := ShimLocal(r.config, r.events)
 	shimopt := ShimLocal(r.config, r.events)
 	if !r.config.NoShim {
 	if !r.config.NoShim {
 		var cgroup string
 		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 {
 			if err != nil {
 				return nil, err
 				return nil, err
 			}
 			}
@@ -205,14 +196,6 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts
 			}
 			}
 			lc := t.(*Task)
 			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{
 			log.G(ctx).WithFields(logrus.Fields{
 				"id":        id,
 				"id":        id,
 				"namespace": namespace,
 				"namespace": namespace,
@@ -252,7 +235,7 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts
 		Stderr:     opts.IO.Stderr,
 		Stderr:     opts.IO.Stderr,
 		Terminal:   opts.IO.Terminal,
 		Terminal:   opts.IO.Terminal,
 		Checkpoint: opts.Checkpoint,
 		Checkpoint: opts.Checkpoint,
-		Options:    opts.Options,
+		Options:    opts.TaskOptions,
 	}
 	}
 	for _, m := range opts.Rootfs {
 	for _, m := range opts.Rootfs {
 		sopts.Rootfs = append(sopts.Rootfs, &types.Mount{
 		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 {
 	if err != nil {
 		return nil, errdefs.FromGRPC(err)
 		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 {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	if err := r.tasks.Add(ctx, t); err != nil {
 	if err := r.tasks.Add(ctx, t); err != nil {
 		return nil, err
 		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{
 	r.events.Publish(ctx, runtime.TaskCreateEventTopic, &eventstypes.TaskCreate{
 		ContainerID: sopts.ID,
 		ContainerID: sopts.ID,
 		Bundle:      sopts.Bundle,
 		Bundle:      sopts.Bundle,
@@ -300,56 +273,9 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts
 	return t, nil
 	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
 // 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) {
 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
 			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 {
 		if err != nil {
 			log.G(ctx).WithError(err).Error("loading task type")
 			log.G(ctx).WithError(err).Error("loading task type")
 			continue
 			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/errdefs"
 	"github.com/containerd/containerd/events/exchange"
 	"github.com/containerd/containerd/events/exchange"
 	"github.com/containerd/containerd/identifiers"
 	"github.com/containerd/containerd/identifiers"
+	"github.com/containerd/containerd/log"
 	"github.com/containerd/containerd/runtime"
 	"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"
 	runc "github.com/containerd/go-runc"
 	"github.com/containerd/ttrpc"
 	"github.com/containerd/ttrpc"
+	"github.com/containerd/typeurl"
 	"github.com/gogo/protobuf/types"
 	"github.com/gogo/protobuf/types"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 )
 )
@@ -45,12 +47,12 @@ type Task struct {
 	shim      *client.Client
 	shim      *client.Client
 	namespace string
 	namespace string
 	cg        cgroups.Cgroup
 	cg        cgroups.Cgroup
-	monitor   runtime.TaskMonitor
 	events    *exchange.Exchange
 	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 (
 	var (
 		err error
 		err error
 		cg  cgroups.Cgroup
 		cg  cgroups.Cgroup
@@ -67,9 +69,9 @@ func newTask(id, namespace string, pid int, shim *client.Client, monitor runtime
 		shim:      shim,
 		shim:      shim,
 		namespace: namespace,
 		namespace: namespace,
 		cg:        cg,
 		cg:        cg,
-		monitor:   monitor,
 		events:    events,
 		events:    events,
-		runtime:   runtime,
+		tasks:     list,
+		bundle:    bundle,
 	}, nil
 	}, nil
 }
 }
 
 
@@ -78,13 +80,35 @@ func (t *Task) ID() string {
 	return t.id
 	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
 // Start the task
@@ -107,9 +131,6 @@ func (t *Task) Start(ctx context.Context) error {
 		t.mu.Lock()
 		t.mu.Lock()
 		t.cg = cg
 		t.cg = cg
 		t.mu.Unlock()
 		t.mu.Unlock()
-		if err := t.monitor.Monitor(t); err != nil {
-			return err
-		}
 	}
 	}
 	t.events.Publish(ctx, runtime.TaskStartEventTopic, &eventstypes.TaskStart{
 	t.events.Publish(ctx, runtime.TaskStartEventTopic, &eventstypes.TaskStart{
 		ContainerID: t.id,
 		ContainerID: t.id,
@@ -270,21 +291,6 @@ func (t *Task) Checkpoint(ctx context.Context, path string, options *types.Any)
 	return nil
 	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
 // Update changes runtime information of a running task
 func (t *Task) Update(ctx context.Context, resources *types.Any) error {
 func (t *Task) Update(ctx context.Context, resources *types.Any) error {
 	if _, err := t.shim.Update(ctx, &shim.UpdateTaskRequest{
 	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
 	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()
 	t.mu.Lock()
 	defer t.mu.Unlock()
 	defer t.mu.Unlock()
 	if t.cg == nil {
 	if t.cg == nil {
@@ -318,7 +324,7 @@ func (t *Task) Metrics(ctx context.Context) (interface{}, error) {
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	return stats, nil
+	return typeurl.MarshalAny(stats)
 }
 }
 
 
 // Cgroup returns the underlying cgroup for a linux task
 // 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/events"
 	"github.com/containerd/containerd/log"
 	"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"
 	"github.com/containerd/containerd/sys"
 	ptypes "github.com/gogo/protobuf/types"
 	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"
 	"path/filepath"
 
 
 	"github.com/containerd/containerd/mount"
 	"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"
 	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"
 	"context"
 	"fmt"
 	"fmt"
 	"os"
 	"os"
+	"path/filepath"
 	"sync"
 	"sync"
 
 
 	"github.com/containerd/console"
 	"github.com/containerd/console"
@@ -30,12 +31,13 @@ import (
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/events"
 	"github.com/containerd/containerd/events"
 	"github.com/containerd/containerd/log"
 	"github.com/containerd/containerd/log"
+	"github.com/containerd/containerd/mount"
 	"github.com/containerd/containerd/namespaces"
 	"github.com/containerd/containerd/namespaces"
 	"github.com/containerd/containerd/runtime"
 	"github.com/containerd/containerd/runtime"
-	"github.com/containerd/containerd/runtime/linux/proc"
 	"github.com/containerd/containerd/runtime/linux/runctypes"
 	"github.com/containerd/containerd/runtime/linux/runctypes"
 	rproc "github.com/containerd/containerd/runtime/proc"
 	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"
 	runc "github.com/containerd/go-runc"
 	"github.com/containerd/typeurl"
 	"github.com/containerd/typeurl"
 	ptypes "github.com/gogo/protobuf/types"
 	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
 // 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()
 	s.mu.Lock()
 	defer s.mu.Unlock()
 	defer s.mu.Unlock()
 
 
@@ -121,7 +123,39 @@ func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (*sh
 			Options: m.Options,
 			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,
 		ctx,
 		s.config.Path,
 		s.config.Path,
 		s.config.WorkDir,
 		s.config.WorkDir,
@@ -130,23 +164,14 @@ func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (*sh
 		s.config.Criu,
 		s.config.Criu,
 		s.config.SystemdCgroup,
 		s.config.SystemdCgroup,
 		s.platform,
 		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 {
 	if err != nil {
 		return nil, errdefs.ToGRPC(err)
 		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
 	// save the main task id and bundle to the shim for additional requests
 	s.id = r.ID
 	s.id = r.ID
 	s.bundle = r.Bundle
 	s.bundle = r.Bundle
@@ -414,9 +439,22 @@ func (s *Service) Checkpoint(ctx context.Context, r *shimapi.CheckpointTaskReque
 	if p == nil {
 	if p == nil {
 		return nil, errdefs.ToGRPCf(errdefs.ErrFailedPrecondition, "container must be created")
 		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{
 	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 {
 	}); err != nil {
 		return nil, errdefs.ToGRPC(err)
 		return nil, errdefs.ToGRPC(err)
 	}
 	}
@@ -545,3 +583,32 @@ func getTopic(ctx context.Context, e interface{}) string {
 	}
 	}
 	return runtime.TaskUnknownTopic
 	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.
 // 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.
 	Package shim is a generated protocol buffer package.
 
 
 	It is generated from these files:
 	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:
 	It has these top-level messages:
 		CreateTaskRequest
 		CreateTaskRequest
@@ -4352,80 +4352,80 @@ var (
 )
 )
 
 
 func init() {
 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{
 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/mount.proto";
 import "github.com/containerd/containerd/api/types/task/task.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
 // 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
 // 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"
 	containersapi "github.com/containerd/containerd/api/services/containers/v1"
 	"github.com/containerd/containerd/api/services/diff/v1"
 	"github.com/containerd/containerd/api/services/diff/v1"
 	imagesapi "github.com/containerd/containerd/api/services/images/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"
 	namespacesapi "github.com/containerd/containerd/api/services/namespaces/v1"
 	"github.com/containerd/containerd/api/services/tasks/v1"
 	"github.com/containerd/containerd/api/services/tasks/v1"
 	"github.com/containerd/containerd/containers"
 	"github.com/containerd/containerd/containers"
 	"github.com/containerd/containerd/content"
 	"github.com/containerd/containerd/content"
 	"github.com/containerd/containerd/images"
 	"github.com/containerd/containerd/images"
+	"github.com/containerd/containerd/leases"
 	"github.com/containerd/containerd/namespaces"
 	"github.com/containerd/containerd/namespaces"
 	"github.com/containerd/containerd/snapshots"
 	"github.com/containerd/containerd/snapshots"
 )
 )
@@ -39,7 +39,7 @@ type services struct {
 	taskService    tasks.TasksClient
 	taskService    tasks.TasksClient
 	diffService    DiffService
 	diffService    DiffService
 	eventService   EventService
 	eventService   EventService
-	leasesService  leases.LeasesClient
+	leasesService  leases.Manager
 }
 }
 
 
 // ServicesOpt allows callers to set options on the services
 // ServicesOpt allows callers to set options on the services
@@ -105,7 +105,7 @@ func WithNamespaceService(namespaceService namespacesapi.NamespacesClient) Servi
 }
 }
 
 
 // WithLeasesService sets the lease service.
 // WithLeasesService sets the lease service.
-func WithLeasesService(leasesService leases.LeasesClient) ServicesOpt {
+func WithLeasesService(leasesService leases.Manager) ServicesOpt {
 	return func(s *services) {
 	return func(s *services) {
 		s.leasesService = leasesService
 		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"`
 	OOMScore int `toml:"oom_score"`
 	// Cgroup specifies cgroup information for the containerd daemon process
 	// Cgroup specifies cgroup information for the containerd daemon process
 	Cgroup CgroupConfig `toml:"cgroup"`
 	Cgroup CgroupConfig `toml:"cgroup"`
+	// ProxyPlugins configures plugins which are communicated to over GRPC
+	ProxyPlugins map[string]ProxyPlugin `toml:"proxy_plugins"`
 
 
 	md toml.MetaData
 	md toml.MetaData
 }
 }
@@ -75,6 +77,12 @@ type CgroupConfig struct {
 	Path string `toml:"path"`
 	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
 // Decode unmarshals a plugin specific configuration by plugin id
 func (c *Config) Decode(id string, v interface{}) (interface{}, error) {
 func (c *Config) Decode(id string, v interface{}) (interface{}, error) {
 	data, ok := c.Plugins[id]
 	data, ok := c.Plugins[id]

+ 85 - 3
vendor/github.com/containerd/containerd/services/server/server.go

@@ -26,19 +26,26 @@ import (
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 	"strings"
 	"strings"
+	"sync"
+	"time"
 
 
 	"github.com/boltdb/bolt"
 	"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"
 	"github.com/containerd/containerd/content/local"
 	"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/events/exchange"
 	"github.com/containerd/containerd/log"
 	"github.com/containerd/containerd/log"
 	"github.com/containerd/containerd/metadata"
 	"github.com/containerd/containerd/metadata"
+	"github.com/containerd/containerd/pkg/dialer"
 	"github.com/containerd/containerd/plugin"
 	"github.com/containerd/containerd/plugin"
 	"github.com/containerd/containerd/snapshots"
 	"github.com/containerd/containerd/snapshots"
+	ssproxy "github.com/containerd/containerd/snapshots/proxy"
 	metrics "github.com/docker/go-metrics"
 	metrics "github.com/docker/go-metrics"
 	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
 	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
-
 	"google.golang.org/grpc"
 	"google.golang.org/grpc"
 )
 )
 
 
@@ -62,7 +69,7 @@ func New(ctx context.Context, config *Config) (*Server, error) {
 	if err := apply(ctx, config); err != nil {
 	if err := apply(ctx, config); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	plugins, err := LoadPlugins(config)
+	plugins, err := LoadPlugins(ctx, config)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -204,7 +211,7 @@ func (s *Server) Stop() {
 
 
 // LoadPlugins loads all plugins into containerd and generates an ordered graph
 // LoadPlugins loads all plugins into containerd and generates an ordered graph
 // of all plugins.
 // 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
 	// load all plugins into containerd
 	if err := plugin.Load(filepath.Join(config.Root, "plugins")); err != nil {
 	if err := plugin.Load(filepath.Join(config.Root, "plugins")); err != nil {
 		return nil, err
 		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 the ordered graph for plugins
 	return plugin.Graph(config.DisabledPlugins), nil
 	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 {
 func trapClosedConnErr(err error) error {
 	if err == nil {
 	if err == nil {
 		return 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
 package sys
 
 
-import "golang.org/x/sys/unix"
+import (
+	"golang.org/x/sys/unix"
+)
 
 
 // Exit is the wait4 information from an exited process
 // Exit is the wait4 information from an exited process
 type Exit struct {
 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"
 	"github.com/containerd/typeurl"
 	google_protobuf "github.com/gogo/protobuf/types"
 	google_protobuf "github.com/gogo/protobuf/types"
 	digest "github.com/opencontainers/go-digest"
 	digest "github.com/opencontainers/go-digest"
+	is "github.com/opencontainers/image-spec/specs-go"
 	"github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/opencontainers/image-spec/specs-go/v1"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
 	specs "github.com/opencontainers/runtime-spec/specs-go"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
@@ -424,6 +425,9 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag
 		return nil, err
 		return nil, err
 	}
 	}
 	index := v1.Index{
 	index := v1.Index{
+		Versioned: is.Versioned{
+			SchemaVersion: 2,
+		},
 		Annotations: make(map[string]string),
 		Annotations: make(map[string]string),
 	}
 	}
 	if err := t.checkpointTask(ctx, &index, request); err != nil {
 	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 {
 	if im, err = t.client.ImageService().Create(ctx, im); err != nil {
 		return nil, err
 		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
 // 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/errdefs"
 	"github.com/containerd/containerd/mount"
 	"github.com/containerd/containerd/mount"
-	"github.com/containerd/containerd/runtime/linux/runctypes"
 )
 )
 
 
 // NewTaskOpts allows the caller to set options on a new task
 // 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
 // WithCheckpointName sets the image name for the checkpoint
 func WithCheckpointName(name string) CheckpointTaskOpts {
 func WithCheckpointName(name string) CheckpointTaskOpts {
 	return func(r *CheckpointTaskInfo) error {
 	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/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
 github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244
 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/protobuf v1.0.0
 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
 github.com/golang/protobuf v1.1.0
 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/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340
 github.com/sirupsen/logrus v1.0.0
 github.com/sirupsen/logrus v1.0.0
 github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
 github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
@@ -27,7 +27,7 @@ golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
 google.golang.org/grpc v1.12.0
 google.golang.org/grpc v1.12.0
 github.com/pkg/errors v0.8.0
 github.com/pkg/errors v0.8.0
 github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
 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
 github.com/opencontainers/image-spec v1.0.1
 golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
 golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
 github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
 github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
@@ -43,7 +43,7 @@ gotest.tools v2.1.0
 github.com/google/go-cmp v0.1.0
 github.com/google/go-cmp v0.1.0
 
 
 # cri dependencies
 # cri dependencies
-github.com/containerd/cri v1.11.0
+github.com/containerd/cri v1.11.1
 github.com/containerd/go-cni 5882530828ecf62032409b298a3e8b19e08b6534
 github.com/containerd/go-cni 5882530828ecf62032409b298a3e8b19e08b6534
 github.com/blang/semver v3.1.0
 github.com/blang/semver v3.1.0
 github.com/containernetworking/cni v0.6.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"
 	"errors"
 	"fmt"
 	"fmt"
 	"os"
 	"os"
+	"path/filepath"
 	"sort"
 	"sort"
 
 
 	"github.com/containerd/continuity/devices"
 	"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)
 	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.
 // Getxattr returns all of the extended attributes for the file at path p.
 func (d *driver) Getxattr(p string) (map[string][]byte, error) {
 func (d *driver) Getxattr(p string) (map[string][]byte, error) {
 	xattrs, err := sysx.Listxattr(p)
 	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
 // DiskUsage counts the number of inodes and disk usage for the resources under
 // path.
 // 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
 // DiffUsage counts the numbers of inodes and disk usage in the

部分文件因文件數量過多而無法顯示