瀏覽代碼

Merge pull request #75 from thaJeztah/18.09_backport_bump_containerd_client_1.2.0_rc.1

[18.09] backport update containerd client and dependencies to v1.2.0-rc.1
Tibor Vass 6 年之前
父節點
當前提交
8e67dfab97
共有 97 個文件被更改,包括 2971 次插入978 次删除
  1. 11 11
      vendor.conf
  2. 137 137
      vendor/github.com/Microsoft/go-winio/ea.go
  3. 108 82
      vendor/github.com/Microsoft/go-winio/vhd/vhd.go
  4. 35 0
      vendor/github.com/Microsoft/go-winio/vhd/zvhd.go
  5. 2 0
      vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
  6. 47 0
      vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go
  7. 7 0
      vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
  8. 43 5
      vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go
  9. 30 0
      vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go
  10. 1 1
      vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go
  11. 1 1
      vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go
  12. 53 9
      vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go
  13. 3 3
      vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go
  14. 43 14
      vendor/github.com/containerd/containerd/archive/compression/compression.go
  15. 17 0
      vendor/github.com/containerd/containerd/container_opts.go
  16. 2 2
      vendor/github.com/containerd/containerd/containers/containers.go
  17. 6 0
      vendor/github.com/containerd/containerd/image.go
  18. 9 1
      vendor/github.com/containerd/containerd/images/archive/importer.go
  19. 8 1
      vendor/github.com/containerd/containerd/images/image.go
  20. 13 4
      vendor/github.com/containerd/containerd/metadata/content.go
  21. 15 0
      vendor/github.com/containerd/containerd/oci/spec_opts.go
  22. 317 0
      vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
  23. 69 269
      vendor/github.com/containerd/containerd/remotes/docker/resolver.go
  24. 3 4
      vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go
  25. 60 0
      vendor/github.com/containerd/containerd/signal_map_linux.go
  26. 58 0
      vendor/github.com/containerd/containerd/signal_map_unix.go
  27. 39 0
      vendor/github.com/containerd/containerd/signal_map_windows.go
  28. 105 0
      vendor/github.com/containerd/containerd/signals.go
  29. 4 4
      vendor/github.com/containerd/containerd/vendor.conf
  30. 16 0
      vendor/github.com/containerd/continuity/context.go
  31. 16 0
      vendor/github.com/containerd/continuity/devices/devices.go
  32. 16 0
      vendor/github.com/containerd/continuity/devices/devices_unix.go
  33. 16 0
      vendor/github.com/containerd/continuity/devices/devices_windows.go
  34. 16 0
      vendor/github.com/containerd/continuity/digests.go
  35. 16 0
      vendor/github.com/containerd/continuity/driver/driver.go
  36. 26 2
      vendor/github.com/containerd/continuity/driver/driver_unix.go
  37. 18 3
      vendor/github.com/containerd/continuity/driver/driver_windows.go
  38. 21 1
      vendor/github.com/containerd/continuity/driver/lchmod_linux.go
  39. 21 1
      vendor/github.com/containerd/continuity/driver/lchmod_unix.go
  40. 16 0
      vendor/github.com/containerd/continuity/driver/utils.go
  41. 16 0
      vendor/github.com/containerd/continuity/fs/copy.go
  42. 16 0
      vendor/github.com/containerd/continuity/fs/copy_linux.go
  43. 16 0
      vendor/github.com/containerd/continuity/fs/copy_unix.go
  44. 16 0
      vendor/github.com/containerd/continuity/fs/copy_windows.go
  45. 16 0
      vendor/github.com/containerd/continuity/fs/diff.go
  46. 16 0
      vendor/github.com/containerd/continuity/fs/diff_unix.go
  47. 16 0
      vendor/github.com/containerd/continuity/fs/diff_windows.go
  48. 16 0
      vendor/github.com/containerd/continuity/fs/dtype_linux.go
  49. 16 0
      vendor/github.com/containerd/continuity/fs/du.go
  50. 16 0
      vendor/github.com/containerd/continuity/fs/du_unix.go
  51. 16 0
      vendor/github.com/containerd/continuity/fs/du_windows.go
  52. 16 0
      vendor/github.com/containerd/continuity/fs/hardlink.go
  53. 16 0
      vendor/github.com/containerd/continuity/fs/hardlink_unix.go
  54. 16 0
      vendor/github.com/containerd/continuity/fs/hardlink_windows.go
  55. 16 6
      vendor/github.com/containerd/continuity/fs/path.go
  56. 16 0
      vendor/github.com/containerd/continuity/fs/stat_bsd.go
  57. 16 0
      vendor/github.com/containerd/continuity/fs/stat_linux.go
  58. 16 0
      vendor/github.com/containerd/continuity/fs/time.go
  59. 16 0
      vendor/github.com/containerd/continuity/groups_unix.go
  60. 16 0
      vendor/github.com/containerd/continuity/hardlinks.go
  61. 16 0
      vendor/github.com/containerd/continuity/hardlinks_unix.go
  62. 16 0
      vendor/github.com/containerd/continuity/hardlinks_windows.go
  63. 16 0
      vendor/github.com/containerd/continuity/ioutils.go
  64. 16 0
      vendor/github.com/containerd/continuity/manifest.go
  65. 16 0
      vendor/github.com/containerd/continuity/pathdriver/path_driver.go
  66. 16 0
      vendor/github.com/containerd/continuity/proto/gen.go
  67. 16 0
      vendor/github.com/containerd/continuity/resource.go
  68. 16 0
      vendor/github.com/containerd/continuity/resource_unix.go
  69. 16 0
      vendor/github.com/containerd/continuity/resource_windows.go
  70. 16 0
      vendor/github.com/containerd/continuity/syscallx/syscall_unix.go
  71. 16 0
      vendor/github.com/containerd/continuity/syscallx/syscall_windows.go
  72. 16 0
      vendor/github.com/containerd/continuity/sysx/file_posix.go
  73. 16 0
      vendor/github.com/containerd/continuity/sysx/nodata_linux.go
  74. 16 0
      vendor/github.com/containerd/continuity/sysx/nodata_solaris.go
  75. 16 0
      vendor/github.com/containerd/continuity/sysx/nodata_unix.go
  76. 16 0
      vendor/github.com/containerd/continuity/sysx/xattr.go
  77. 16 0
      vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go
  78. 4 0
      vendor/github.com/containerd/ttrpc/client.go
  79. 1 1
      vendor/github.com/containerd/ttrpc/server.go
  80. 11 9
      vendor/github.com/grpc-ecosystem/go-grpc-prometheus/README.md
  81. 23 56
      vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client.go
  82. 170 0
      vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_metrics.go
  83. 13 78
      vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_reporter.go
  84. 41 0
      vendor/github.com/grpc-ecosystem/go-grpc-prometheus/metric_options.go
  85. 29 55
      vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server.go
  86. 185 0
      vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_metrics.go
  87. 13 124
      vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_reporter.go
  88. 23 0
      vendor/github.com/grpc-ecosystem/go-grpc-prometheus/util.go
  89. 12 0
      vendor/github.com/opencontainers/runc/README.md
  90. 13 12
      vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
  91. 3 3
      vendor/github.com/opencontainers/runc/libcontainer/nsenter/README.md
  92. 1 1
      vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c
  93. 2 0
      vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
  94. 1 4
      vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go
  95. 201 73
      vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
  96. 188 0
      vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
  97. 1 1
      vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go

+ 11 - 11
vendor.conf

@@ -1,7 +1,7 @@
 # the following lines are in sorted order, FYI
 github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
-github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55
-github.com/Microsoft/go-winio v0.4.10
+github.com/Microsoft/hcsshim v0.7.6
+github.com/Microsoft/go-winio v0.4.11
 github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
 github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git
 github.com/golang/gddo 9b12a26f3fbd7397dee4e20939ddca719d840d2a
@@ -75,8 +75,8 @@ github.com/pborman/uuid v1.0
 google.golang.org/grpc v1.12.0
 
 # This does not need to match RUNC_COMMIT as it is used for helper packages but should be newer or equal
-github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd
-github.com/opencontainers/runtime-spec d810dbc60d8c5aeeb3d054bd1132fab2121968ce # v1.0.1-43-gd810dbc
+github.com/opencontainers/runc 00dc70017d222b178a002ed30e9321b12647af2d
+github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
 github.com/opencontainers/image-spec v1.0.1
 github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
 
@@ -114,16 +114,16 @@ github.com/googleapis/gax-go v2.0.0
 google.golang.org/genproto 694d95ba50e67b2e363f3483057db5d4910c18f9
 
 # containerd
-github.com/containerd/containerd v1.2.0-rc.0
+github.com/containerd/containerd 0c5f8f63c3368856c320ae8a1c125e703b73b51d # v1.2.0-rc.1
 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
-github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537
+github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
 github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
 github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
+github.com/containerd/cri 9f39e3289533fc228c5e5fcac0a6dbdd60c6047b # release/1.2 branch
 github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3
 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
-github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
+github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
-github.com/containerd/cri 9f39e3289533fc228c5e5fcac0a6dbdd60c6047b # release/1.2 branch
 
 # cluster
 github.com/docker/swarmkit 3044c576a8a970d3079492b585054f29e96e27f1
@@ -144,8 +144,8 @@ github.com/prometheus/client_model fa8ad6fec33561be4280a8f0514318c79d7f6cb6
 github.com/prometheus/common ebdfc6da46522d58825777cf1f90490a5b1ef1d8
 github.com/prometheus/procfs abf152e5f3e97f2fafac028d2cc06c1feb87ffa5
 github.com/matttproud/golang_protobuf_extensions v1.0.0
-github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9
-github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
+github.com/pkg/errors 645ef00459ed84a119197bfb8d8205042c6df63d # v0.8.0
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
 
 # cli
 github.com/spf13/cobra v0.0.3
@@ -156,7 +156,7 @@ github.com/Nvveen/Gotty a8b993ba6abdb0e0c12b0125c603323a71c7790c https://github.
 # metrics
 github.com/docker/go-metrics d466d4f6fd960e01820085bd7e1a24426ee7ef18
 
-github.com/opencontainers/selinux b29023b86e4a69d1b46b7e7b4e2b6fda03f0b9cd
+github.com/opencontainers/selinux b6fa367ed7f534f9ba25391cc2d467085dbb445a
 
 
 # archive/tar (for Go 1.10, see https://github.com/golang/go/issues/24787)

+ 137 - 137
vendor/github.com/Microsoft/go-winio/ea.go

@@ -1,137 +1,137 @@
-package winio
-
-import (
-	"bytes"
-	"encoding/binary"
-	"errors"
-)
-
-type fileFullEaInformation struct {
-	NextEntryOffset uint32
-	Flags           uint8
-	NameLength      uint8
-	ValueLength     uint16
-}
-
-var (
-	fileFullEaInformationSize = binary.Size(&fileFullEaInformation{})
-
-	errInvalidEaBuffer = errors.New("invalid extended attribute buffer")
-	errEaNameTooLarge  = errors.New("extended attribute name too large")
-	errEaValueTooLarge = errors.New("extended attribute value too large")
-)
-
-// ExtendedAttribute represents a single Windows EA.
-type ExtendedAttribute struct {
-	Name  string
-	Value []byte
-	Flags uint8
-}
-
-func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
-	var info fileFullEaInformation
-	err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
-	if err != nil {
-		err = errInvalidEaBuffer
-		return
-	}
-
-	nameOffset := fileFullEaInformationSize
-	nameLen := int(info.NameLength)
-	valueOffset := nameOffset + int(info.NameLength) + 1
-	valueLen := int(info.ValueLength)
-	nextOffset := int(info.NextEntryOffset)
-	if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
-		err = errInvalidEaBuffer
-		return
-	}
-
-	ea.Name = string(b[nameOffset : nameOffset+nameLen])
-	ea.Value = b[valueOffset : valueOffset+valueLen]
-	ea.Flags = info.Flags
-	if info.NextEntryOffset != 0 {
-		nb = b[info.NextEntryOffset:]
-	}
-	return
-}
-
-// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
-// buffer retrieved from BackupRead, ZwQueryEaFile, etc.
-func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
-	for len(b) != 0 {
-		ea, nb, err := parseEa(b)
-		if err != nil {
-			return nil, err
-		}
-
-		eas = append(eas, ea)
-		b = nb
-	}
-	return
-}
-
-func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
-	if int(uint8(len(ea.Name))) != len(ea.Name) {
-		return errEaNameTooLarge
-	}
-	if int(uint16(len(ea.Value))) != len(ea.Value) {
-		return errEaValueTooLarge
-	}
-	entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value))
-	withPadding := (entrySize + 3) &^ 3
-	nextOffset := uint32(0)
-	if !last {
-		nextOffset = withPadding
-	}
-	info := fileFullEaInformation{
-		NextEntryOffset: nextOffset,
-		Flags:           ea.Flags,
-		NameLength:      uint8(len(ea.Name)),
-		ValueLength:     uint16(len(ea.Value)),
-	}
-
-	err := binary.Write(buf, binary.LittleEndian, &info)
-	if err != nil {
-		return err
-	}
-
-	_, err = buf.Write([]byte(ea.Name))
-	if err != nil {
-		return err
-	}
-
-	err = buf.WriteByte(0)
-	if err != nil {
-		return err
-	}
-
-	_, err = buf.Write(ea.Value)
-	if err != nil {
-		return err
-	}
-
-	_, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize])
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION
-// buffer for use with BackupWrite, ZwSetEaFile, etc.
-func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) {
-	var buf bytes.Buffer
-	for i := range eas {
-		last := false
-		if i == len(eas)-1 {
-			last = true
-		}
-
-		err := writeEa(&buf, &eas[i], last)
-		if err != nil {
-			return nil, err
-		}
-	}
-	return buf.Bytes(), nil
-}
+package winio
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+)
+
+type fileFullEaInformation struct {
+	NextEntryOffset uint32
+	Flags           uint8
+	NameLength      uint8
+	ValueLength     uint16
+}
+
+var (
+	fileFullEaInformationSize = binary.Size(&fileFullEaInformation{})
+
+	errInvalidEaBuffer = errors.New("invalid extended attribute buffer")
+	errEaNameTooLarge  = errors.New("extended attribute name too large")
+	errEaValueTooLarge = errors.New("extended attribute value too large")
+)
+
+// ExtendedAttribute represents a single Windows EA.
+type ExtendedAttribute struct {
+	Name  string
+	Value []byte
+	Flags uint8
+}
+
+func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
+	var info fileFullEaInformation
+	err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
+	if err != nil {
+		err = errInvalidEaBuffer
+		return
+	}
+
+	nameOffset := fileFullEaInformationSize
+	nameLen := int(info.NameLength)
+	valueOffset := nameOffset + int(info.NameLength) + 1
+	valueLen := int(info.ValueLength)
+	nextOffset := int(info.NextEntryOffset)
+	if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
+		err = errInvalidEaBuffer
+		return
+	}
+
+	ea.Name = string(b[nameOffset : nameOffset+nameLen])
+	ea.Value = b[valueOffset : valueOffset+valueLen]
+	ea.Flags = info.Flags
+	if info.NextEntryOffset != 0 {
+		nb = b[info.NextEntryOffset:]
+	}
+	return
+}
+
+// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
+// buffer retrieved from BackupRead, ZwQueryEaFile, etc.
+func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
+	for len(b) != 0 {
+		ea, nb, err := parseEa(b)
+		if err != nil {
+			return nil, err
+		}
+
+		eas = append(eas, ea)
+		b = nb
+	}
+	return
+}
+
+func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
+	if int(uint8(len(ea.Name))) != len(ea.Name) {
+		return errEaNameTooLarge
+	}
+	if int(uint16(len(ea.Value))) != len(ea.Value) {
+		return errEaValueTooLarge
+	}
+	entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value))
+	withPadding := (entrySize + 3) &^ 3
+	nextOffset := uint32(0)
+	if !last {
+		nextOffset = withPadding
+	}
+	info := fileFullEaInformation{
+		NextEntryOffset: nextOffset,
+		Flags:           ea.Flags,
+		NameLength:      uint8(len(ea.Name)),
+		ValueLength:     uint16(len(ea.Value)),
+	}
+
+	err := binary.Write(buf, binary.LittleEndian, &info)
+	if err != nil {
+		return err
+	}
+
+	_, err = buf.Write([]byte(ea.Name))
+	if err != nil {
+		return err
+	}
+
+	err = buf.WriteByte(0)
+	if err != nil {
+		return err
+	}
+
+	_, err = buf.Write(ea.Value)
+	if err != nil {
+		return err
+	}
+
+	_, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize])
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION
+// buffer for use with BackupWrite, ZwSetEaFile, etc.
+func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) {
+	var buf bytes.Buffer
+	for i := range eas {
+		last := false
+		if i == len(eas)-1 {
+			last = true
+		}
+
+		err := writeEa(&buf, &eas[i], last)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return buf.Bytes(), nil
+}

+ 108 - 82
vendor/github.com/Microsoft/go-winio/vhd/vhd.go

@@ -1,82 +1,108 @@
-// +build windows
-
-package vhd
-
-import "syscall"
-
-//go:generate go run mksyscall_windows.go -output zvhd.go vhd.go
-
-//sys createVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.CreateVirtualDisk
-
-type virtualStorageType struct {
-	DeviceID uint32
-	VendorID [16]byte
-}
-
-const virtualDiskAccessNONE uint32 = 0
-const virtualDiskAccessATTACHRO uint32 = 65536
-const virtualDiskAccessATTACHRW uint32 = 131072
-const virtualDiskAccessDETACH uint32 = 262144
-const virtualDiskAccessGETINFO uint32 = 524288
-const virtualDiskAccessCREATE uint32 = 1048576
-const virtualDiskAccessMETAOPS uint32 = 2097152
-const virtualDiskAccessREAD uint32 = 851968
-const virtualDiskAccessALL uint32 = 4128768
-const virtualDiskAccessWRITABLE uint32 = 3276800
-
-const createVirtualDiskFlagNone uint32 = 0
-const createVirtualDiskFlagFullPhysicalAllocation uint32 = 1
-const createVirtualDiskFlagPreventWritesToSourceDisk uint32 = 2
-const createVirtualDiskFlagDoNotCopyMetadataFromParent uint32 = 4
-
-type version2 struct {
-	UniqueID                 [16]byte // GUID
-	MaximumSize              uint64
-	BlockSizeInBytes         uint32
-	SectorSizeInBytes        uint32
-	ParentPath               *uint16 // string
-	SourcePath               *uint16 // string
-	OpenFlags                uint32
-	ParentVirtualStorageType virtualStorageType
-	SourceVirtualStorageType virtualStorageType
-	ResiliencyGUID           [16]byte // GUID
-}
-
-type createVirtualDiskParameters struct {
-	Version  uint32 // Must always be set to 2
-	Version2 version2
-}
-
-// CreateVhdx will create a simple vhdx file at the given path using default values.
-func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error {
-	var defaultType virtualStorageType
-
-	parameters := createVirtualDiskParameters{
-		Version: 2,
-		Version2: version2{
-			MaximumSize:      uint64(maxSizeInGb) * 1024 * 1024 * 1024,
-			BlockSizeInBytes: blockSizeInMb * 1024 * 1024,
-		},
-	}
-
-	var handle syscall.Handle
-
-	if err := createVirtualDisk(
-		&defaultType,
-		path,
-		virtualDiskAccessNONE,
-		nil,
-		createVirtualDiskFlagNone,
-		0,
-		&parameters,
-		nil,
-		&handle); err != nil {
-		return err
-	}
-
-	if err := syscall.CloseHandle(handle); err != nil {
-		return err
-	}
-
-	return nil
-}
+// +build windows
+
+package vhd
+
+import "syscall"
+
+//go:generate go run mksyscall_windows.go -output zvhd.go vhd.go
+
+//sys createVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.CreateVirtualDisk
+//sys openVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, flags uint32, parameters *uintptr, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.OpenVirtualDisk
+//sys detachVirtualDisk(handle syscall.Handle, flags uint32, providerSpecificFlags uint32) (err error) [failretval != 0] = VirtDisk.DetachVirtualDisk
+
+type virtualStorageType struct {
+	DeviceID uint32
+	VendorID [16]byte
+}
+
+const virtualDiskAccessNONE uint32 = 0
+const virtualDiskAccessATTACHRO uint32 = 65536
+const virtualDiskAccessATTACHRW uint32 = 131072
+const virtualDiskAccessDETACH uint32 = 262144
+const virtualDiskAccessGETINFO uint32 = 524288
+const virtualDiskAccessCREATE uint32 = 1048576
+const virtualDiskAccessMETAOPS uint32 = 2097152
+const virtualDiskAccessREAD uint32 = 851968
+const virtualDiskAccessALL uint32 = 4128768
+const virtualDiskAccessWRITABLE uint32 = 3276800
+
+const createVirtualDiskFlagNone uint32 = 0
+const createVirtualDiskFlagFullPhysicalAllocation uint32 = 1
+const createVirtualDiskFlagPreventWritesToSourceDisk uint32 = 2
+const createVirtualDiskFlagDoNotCopyMetadataFromParent uint32 = 4
+
+type version2 struct {
+	UniqueID                 [16]byte // GUID
+	MaximumSize              uint64
+	BlockSizeInBytes         uint32
+	SectorSizeInBytes        uint32
+	ParentPath               *uint16 // string
+	SourcePath               *uint16 // string
+	OpenFlags                uint32
+	ParentVirtualStorageType virtualStorageType
+	SourceVirtualStorageType virtualStorageType
+	ResiliencyGUID           [16]byte // GUID
+}
+
+type createVirtualDiskParameters struct {
+	Version  uint32 // Must always be set to 2
+	Version2 version2
+}
+
+// CreateVhdx will create a simple vhdx file at the given path using default values.
+func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error {
+	var defaultType virtualStorageType
+
+	parameters := createVirtualDiskParameters{
+		Version: 2,
+		Version2: version2{
+			MaximumSize:      uint64(maxSizeInGb) * 1024 * 1024 * 1024,
+			BlockSizeInBytes: blockSizeInMb * 1024 * 1024,
+		},
+	}
+
+	var handle syscall.Handle
+
+	if err := createVirtualDisk(
+		&defaultType,
+		path,
+		virtualDiskAccessNONE,
+		nil,
+		createVirtualDiskFlagNone,
+		0,
+		&parameters,
+		nil,
+		&handle); err != nil {
+		return err
+	}
+
+	if err := syscall.CloseHandle(handle); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// DetachVhd detaches a VHD attached at the given path.
+func DetachVhd(path string) error {
+	var (
+		defaultType virtualStorageType
+		handle      syscall.Handle
+	)
+
+	if err := openVirtualDisk(
+		&defaultType,
+		path,
+		virtualDiskAccessDETACH,
+		0,
+		nil,
+		&handle); err != nil {
+		return err
+	}
+	defer syscall.CloseHandle(handle)
+
+	if err := detachVirtualDisk(handle, 0, 0); err != nil {
+		return err
+	}
+	return nil
+}

+ 35 - 0
vendor/github.com/Microsoft/go-winio/vhd/zvhd.go

@@ -40,6 +40,8 @@ var (
 	modVirtDisk = windows.NewLazySystemDLL("VirtDisk.dll")
 
 	procCreateVirtualDisk = modVirtDisk.NewProc("CreateVirtualDisk")
+	procOpenVirtualDisk   = modVirtDisk.NewProc("OpenVirtualDisk")
+	procDetachVirtualDisk = modVirtDisk.NewProc("DetachVirtualDisk")
 )
 
 func createVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) {
@@ -62,3 +64,36 @@ func _createVirtualDisk(virtualStorageType *virtualStorageType, path *uint16, vi
 	}
 	return
 }
+
+func openVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, flags uint32, parameters *uintptr, handle *syscall.Handle) (err error) {
+	var _p0 *uint16
+	_p0, err = syscall.UTF16PtrFromString(path)
+	if err != nil {
+		return
+	}
+	return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, flags, parameters, handle)
+}
+
+func _openVirtualDisk(virtualStorageType *virtualStorageType, path *uint16, virtualDiskAccessMask uint32, flags uint32, parameters *uintptr, handle *syscall.Handle) (err error) {
+	r1, _, e1 := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(flags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle)))
+	if r1 != 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
+func detachVirtualDisk(handle syscall.Handle, flags uint32, providerSpecificFlags uint32) (err error) {
+	r1, _, e1 := syscall.Syscall(procDetachVirtualDisk.Addr(), 3, uintptr(handle), uintptr(flags), uintptr(providerSpecificFlags))
+	if r1 != 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}

+ 2 - 0
vendor/github.com/Microsoft/hcsshim/hnsendpoint.go

@@ -6,6 +6,8 @@ import (
 
 // HNSEndpoint represents a network endpoint in HNS
 type HNSEndpoint = hns.HNSEndpoint
+// Namespace represents a Compartment.
+type Namespace = hns.Namespace
 
 //SystemType represents the type of the system on which actions are done
 type SystemType string

+ 47 - 0
vendor/github.com/Microsoft/hcsshim/internal/guid/guid.go

@@ -2,10 +2,16 @@ package guid
 
 import (
 	"crypto/rand"
+	"encoding/json"
 	"fmt"
 	"io"
+	"strconv"
+	"strings"
 )
 
+var _ = (json.Marshaler)(&GUID{})
+var _ = (json.Unmarshaler)(&GUID{})
+
 type GUID [16]byte
 
 func New() GUID {
@@ -20,3 +26,44 @@ func New() GUID {
 func (g GUID) String() string {
 	return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x", g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8:10], g[10:])
 }
+
+func FromString(s string) GUID {
+	if len(s) != 36 {
+		panic(fmt.Sprintf("invalid GUID length: %d", len(s)))
+	}
+	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
+		panic("invalid GUID format")
+	}
+	indexOrder := [16]int{
+		0, 2, 4, 6,
+		9, 11,
+		14, 16,
+		19, 21,
+		24, 26, 28, 30, 32, 34,
+	}
+	byteOrder := [16]int{
+		3, 2, 1, 0,
+		5, 4,
+		7, 6,
+		8, 9,
+		10, 11, 12, 13, 14, 15,
+	}
+	var g GUID
+	for i, x := range indexOrder {
+		b, err := strconv.ParseInt(s[x:x+2], 16, 16)
+		if err != nil {
+			panic(err)
+		}
+		g[byteOrder[i]] = byte(b)
+	}
+	return g
+}
+
+func (g GUID) MarshalJSON() ([]byte, error) {
+	return json.Marshal(g.String())
+}
+
+func (g *GUID) UnmarshalJSON(data []byte) error {
+	*g = FromString(strings.Trim(string(data), "\""))
+	return nil
+}

+ 7 - 0
vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go

@@ -2,6 +2,7 @@ package hcs
 
 import (
 	"encoding/json"
+	"fmt"
 	"io"
 	"sync"
 	"syscall"
@@ -83,7 +84,10 @@ func (process *Process) Kill() error {
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("TerminateProcess %s: %d", process.SystemID(), process.Pid()), &completed)
 	err := hcsTerminateProcess(process.handle, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return makeProcessError(process, operation, err, events)
@@ -177,7 +181,10 @@ func (process *Process) Properties() (*ProcessStatus, error) {
 		resultp     *uint16
 		propertiesp *uint16
 	)
+	completed := false
+	go syscallWatcher(fmt.Sprintf("GetProcessProperties %s: %d", process.SystemID(), process.Pid()), &completed)
 	err := hcsGetProcessProperties(process.handle, &propertiesp, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return nil, makeProcessError(process, operation, err, events)

+ 43 - 5
vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go

@@ -2,6 +2,7 @@ package hcs
 
 import (
 	"encoding/json"
+	"fmt"
 	"os"
 	"strconv"
 	"sync"
@@ -63,7 +64,10 @@ func CreateComputeSystem(id string, hcsDocumentInterface interface{}) (*System,
 		resultp  *uint16
 		identity syscall.Handle
 	)
+	completed := false
+	go syscallWatcher(fmt.Sprintf("CreateCompleteSystem %s: %s", id, hcsDocument), &completed)
 	createError := hcsCreateComputeSystem(id, hcsDocument, identity, &computeSystem.handle, &resultp)
+	completed = true
 
 	if createError == nil || IsPending(createError) {
 		if err := computeSystem.registerCallback(); err != nil {
@@ -74,7 +78,7 @@ func CreateComputeSystem(id string, hcsDocumentInterface interface{}) (*System,
 		}
 	}
 
-	events, err := processAsyncHcsResult(createError, resultp, computeSystem.callbackNumber, hcsNotificationSystemCreateCompleted, &timeout.Duration)
+	events, err := processAsyncHcsResult(createError, resultp, computeSystem.callbackNumber, hcsNotificationSystemCreateCompleted, &timeout.SystemCreate)
 	if err != nil {
 		if err == ErrTimeout {
 			// Terminate the compute system if it still exists. We're okay to
@@ -135,7 +139,10 @@ func GetComputeSystems(q schema1.ComputeSystemQuery) ([]schema1.ContainerPropert
 		resultp         *uint16
 		computeSystemsp *uint16
 	)
+	completed := false
+	go syscallWatcher(fmt.Sprintf("GetComputeSystems %s:", query), &completed)
 	err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return nil, &HcsError{Op: operation, Err: err, Events: events}
@@ -192,8 +199,11 @@ func (computeSystem *System) Start() error {
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("StartComputeSystem %s:", computeSystem.ID()), &completed)
 	err := hcsStartComputeSystem(computeSystem.handle, "", &resultp)
-	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.Duration)
+	completed = true
+	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.SystemStart)
 	if err != nil {
 		return makeSystemError(computeSystem, "Start", "", err, events)
 	}
@@ -219,7 +229,10 @@ func (computeSystem *System) Shutdown() error {
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("ShutdownComputeSystem %s:", computeSystem.ID()), &completed)
 	err := hcsShutdownComputeSystem(computeSystem.handle, "", &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return makeSystemError(computeSystem, "Shutdown", "", err, events)
@@ -242,7 +255,10 @@ func (computeSystem *System) Terminate() error {
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("TerminateComputeSystem %s:", computeSystem.ID()), &completed)
 	err := hcsTerminateComputeSystem(computeSystem.handle, "", &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return makeSystemError(computeSystem, "Terminate", "", err, events)
@@ -291,7 +307,10 @@ func (computeSystem *System) Properties(types ...schema1.PropertyType) (*schema1
 	}
 
 	var resultp, propertiesp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("GetComputeSystemProperties %s:", computeSystem.ID()), &completed)
 	err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryj), &propertiesp, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return nil, makeSystemError(computeSystem, "Properties", "", err, events)
@@ -320,8 +339,11 @@ func (computeSystem *System) Pause() error {
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("PauseComputeSystem %s:", computeSystem.ID()), &completed)
 	err := hcsPauseComputeSystem(computeSystem.handle, "", &resultp)
-	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.Duration)
+	completed = true
+	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.SystemPause)
 	if err != nil {
 		return makeSystemError(computeSystem, "Pause", "", err, events)
 	}
@@ -342,8 +364,11 @@ func (computeSystem *System) Resume() error {
 	}
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("ResumeComputeSystem %s:", computeSystem.ID()), &completed)
 	err := hcsResumeComputeSystem(computeSystem.handle, "", &resultp)
-	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.Duration)
+	completed = true
+	events, err := processAsyncHcsResult(err, resultp, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.SystemResume)
 	if err != nil {
 		return makeSystemError(computeSystem, "Resume", "", err, events)
 	}
@@ -375,7 +400,10 @@ func (computeSystem *System) CreateProcess(c interface{}) (*Process, error) {
 	configuration := string(configurationb)
 	logrus.Debugf(title+" config=%s", configuration)
 
+	completed := false
+	go syscallWatcher(fmt.Sprintf("CreateProcess %s: %s", computeSystem.ID(), configuration), &completed)
 	err = hcsCreateProcess(computeSystem.handle, configuration, &processInfo, &processHandle, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return nil, makeSystemError(computeSystem, "CreateProcess", configuration, err, events)
@@ -415,7 +443,10 @@ func (computeSystem *System) OpenProcess(pid int) (*Process, error) {
 		return nil, makeSystemError(computeSystem, "OpenProcess", "", ErrAlreadyClosed, nil)
 	}
 
+	completed := false
+	go syscallWatcher(fmt.Sprintf("OpenProcess %s: %d", computeSystem.ID(), pid), &completed)
 	err := hcsOpenProcess(computeSystem.handle, uint32(pid), &processHandle, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return nil, makeSystemError(computeSystem, "OpenProcess", "", err, events)
@@ -451,7 +482,11 @@ func (computeSystem *System) Close() error {
 		return makeSystemError(computeSystem, "Close", "", err, nil)
 	}
 
-	if err := hcsCloseComputeSystem(computeSystem.handle); err != nil {
+	completed := false
+	go syscallWatcher(fmt.Sprintf("CloseComputeSystem %s:", computeSystem.ID()), &completed)
+	err := hcsCloseComputeSystem(computeSystem.handle)
+	completed = true
+	if err != nil {
 		return makeSystemError(computeSystem, "Close", "", err, nil)
 	}
 
@@ -537,7 +572,10 @@ func (computeSystem *System) Modify(config interface{}) error {
 	logrus.Debugf(title + " " + requestString)
 
 	var resultp *uint16
+	completed := false
+	go syscallWatcher(fmt.Sprintf("ModifyComputeSystem %s: %s", computeSystem.ID(), requestString), &completed)
 	err = hcsModifyComputeSystem(computeSystem.handle, requestString, &resultp)
+	completed = true
 	events := processHcsResult(resultp)
 	if err != nil {
 		return makeSystemError(computeSystem, "Modify", requestString, err, events)

+ 30 - 0
vendor/github.com/Microsoft/hcsshim/internal/hcs/watcher.go

@@ -0,0 +1,30 @@
+package hcs
+
+import (
+	"time"
+
+	"github.com/Microsoft/hcsshim/internal/timeout"
+	"github.com/sirupsen/logrus"
+)
+
+// syscallWatcher is used as a very simple goroutine around calls into
+// the platform. In some cases, we have seen HCS APIs not returning due to
+// various bugs, and the goroutine making the syscall ends up not returning,
+// prior to its async callback. By spinning up a syscallWatcher, it allows
+// us to at least log a warning if a syscall doesn't complete in a reasonable
+// amount of time.
+//
+// Usage is:
+//
+// completed := false
+// go syscallWatcher("some description", &completed)
+// <syscall>
+// completed = true
+//
+func syscallWatcher(description string, syscallCompleted *bool) {
+	time.Sleep(timeout.SyscallWatcher)
+	if *syscallCompleted {
+		return
+	}
+	logrus.Warnf("%s: Did not complete within %s. This may indicate a platform issue. If it appears to be making no forward progress, obtain the stacks and see is there is a syscall stuck in the platform API for a significant length of time.", description, timeout.SyscallWatcher)
+}

+ 1 - 1
vendor/github.com/Microsoft/hcsshim/internal/interop/zsyscall_windows.go

@@ -1,4 +1,4 @@
-// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
+// Code generated by 'go generate'; DO NOT EDIT.
 
 package interop
 

+ 1 - 1
vendor/github.com/Microsoft/hcsshim/internal/safefile/zsyscall_windows.go

@@ -1,4 +1,4 @@
-// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
+// Code generated by 'go generate'; DO NOT EDIT.
 
 package safefile
 

+ 53 - 9
vendor/github.com/Microsoft/hcsshim/internal/timeout/timeout.go

@@ -6,21 +6,65 @@ import (
 	"time"
 )
 
-// Duration is the default time to wait for various operations.
-// - Waiting for async notifications from HCS
-// - Waiting for processes to launch through
-// - Waiting to copy data to/from a launched processes stdio pipes.
-//
-// This can be overridden through environment variable `HCS_TIMEOUT_SECONDS`
+var (
+	// defaultTimeout is the timeout for most operations that is not overridden.
+	defaultTimeout = 4 * time.Minute
 
-var Duration = 4 * time.Minute
+	// defaultTimeoutTestdRetry is the retry loop timeout for testd to respond
+	// for a disk to come online in LCOW.
+	defaultTimeoutTestdRetry = 5 * time.Second
+)
+
+// External variables for HCSShim consumers to use.
+var (
+	// SystemCreate is the timeout for creating a compute system
+	SystemCreate time.Duration = defaultTimeout
+
+	// SystemStart is the timeout for starting a compute system
+	SystemStart time.Duration = defaultTimeout
+
+	// SystemPause is the timeout for pausing a compute system
+	SystemPause time.Duration = defaultTimeout
+
+	// SystemResume is the timeout for resuming a compute system
+	SystemResume time.Duration = defaultTimeout
+
+	// SyscallWatcher is the timeout before warning of a potential stuck platform syscall.
+	SyscallWatcher time.Duration = defaultTimeout
+
+	// Tar2VHD is the timeout for the tar2vhd operation to complete
+	Tar2VHD time.Duration = defaultTimeout
+
+	// ExternalCommandToStart is the timeout for external commands to start
+	ExternalCommandToStart = defaultTimeout
+
+	// ExternalCommandToComplete is the timeout for external commands to complete.
+	// Generally this means copying data from their stdio pipes.
+	ExternalCommandToComplete = defaultTimeout
+
+	// TestDRetryLoop is the timeout for testd retry loop when onlining a SCSI disk in LCOW
+	TestDRetryLoop = defaultTimeoutTestdRetry
+)
 
 func init() {
-	envTimeout := os.Getenv("HCSSHIM_TIMEOUT_SECONDS")
+	SystemCreate = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMCREATE", SystemCreate)
+	SystemStart = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMSTART", SystemStart)
+	SystemPause = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMPAUSE", SystemPause)
+	SystemResume = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMRESUME", SystemResume)
+	SyscallWatcher = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSCALLWATCHER", SyscallWatcher)
+	Tar2VHD = durationFromEnvironment("HCSSHIM_TIMEOUT_TAR2VHD", Tar2VHD)
+	ExternalCommandToStart = durationFromEnvironment("HCSSHIM_TIMEOUT_EXTERNALCOMMANDSTART", ExternalCommandToStart)
+	ExternalCommandToComplete = durationFromEnvironment("HCSSHIM_TIMEOUT_EXTERNALCOMMANDCOMPLETE", ExternalCommandToComplete)
+	TestDRetryLoop = durationFromEnvironment("HCSSHIM_TIMEOUT_TESTDRETRYLOOP", TestDRetryLoop)
+}
+
+func durationFromEnvironment(env string, defaultValue time.Duration) time.Duration {
+	envTimeout := os.Getenv(env)
 	if len(envTimeout) > 0 {
 		e, err := strconv.Atoi(envTimeout)
 		if err == nil && e > 0 {
-			Duration = time.Second * time.Duration(e)
+			return time.Second * time.Duration(e)
 		}
 	}
+	return defaultValue
 }

+ 3 - 3
vendor/github.com/Microsoft/hcsshim/internal/wclayer/createlayer.go

@@ -9,15 +9,15 @@ import (
 // the parent layer provided.
 func CreateLayer(path, parent string) error {
 	title := "hcsshim::CreateLayer "
-	logrus.Debugf(title+"Flavour %d ID %s parent %s", path, parent)
+	logrus.Debugf(title+"ID %s parent %s", path, parent)
 
 	err := createLayer(&stdDriverInfo, path, parent)
 	if err != nil {
-		err = hcserror.Errorf(err, title, "path=%s parent=%s flavour=%d", path, parent)
+		err = hcserror.Errorf(err, title, "path=%s parent=%s", path, parent)
 		logrus.Error(err)
 		return err
 	}
 
-	logrus.Debugf(title+" - succeeded path=%s parent=%s flavour=%d", path, parent)
+	logrus.Debugf(title+"- succeeded path=%s parent=%s", path, parent)
 	return nil
 }

+ 43 - 14
vendor/github.com/containerd/containerd/archive/compression/compression.go

@@ -92,6 +92,36 @@ func (w *writeCloserWrapper) Close() error {
 	return nil
 }
 
+type bufferedReader struct {
+	buf *bufio.Reader
+}
+
+func newBufferedReader(r io.Reader) *bufferedReader {
+	buf := bufioReader32KPool.Get().(*bufio.Reader)
+	buf.Reset(r)
+	return &bufferedReader{buf}
+}
+
+func (r *bufferedReader) Read(p []byte) (n int, err error) {
+	if r.buf == nil {
+		return 0, io.EOF
+	}
+	n, err = r.buf.Read(p)
+	if err == io.EOF {
+		r.buf.Reset(nil)
+		bufioReader32KPool.Put(r.buf)
+		r.buf = nil
+	}
+	return
+}
+
+func (r *bufferedReader) Peek(n int) ([]byte, error) {
+	if r.buf == nil {
+		return nil, io.EOF
+	}
+	return r.buf.Peek(n)
+}
+
 // DetectCompression detects the compression algorithm of the source.
 func DetectCompression(source []byte) Compression {
 	for compression, m := range map[Compression][]byte{
@@ -110,8 +140,7 @@ func DetectCompression(source []byte) Compression {
 
 // 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)
+	buf := newBufferedReader(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
@@ -123,15 +152,12 @@ func DecompressStream(archive io.Reader) (DecompressReadCloser, error) {
 		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
+		return &readCloserWrapper{
+			Reader:      buf,
+			compression: compression,
+		}, nil
 	case Gzip:
 		ctx, cancel := context.WithCancel(context.Background())
 		gzReader, err := gzipDecompress(ctx, buf)
@@ -140,12 +166,15 @@ func DecompressStream(archive io.Reader) (DecompressReadCloser, error) {
 			return nil, err
 		}
 
-		readBufWrapper := &readCloserWrapper{gzReader, compression, func() error {
-			cancel()
-			return closer()
-		}}
+		return &readCloserWrapper{
+			Reader:      gzReader,
+			compression: compression,
+			closer: func() error {
+				cancel()
+				return gzReader.Close()
+			},
+		}, nil
 
-		return readBufWrapper, nil
 	default:
 		return nil, fmt.Errorf("unsupported compression format %s", (&compression).Extension())
 	}

+ 17 - 0
vendor/github.com/containerd/containerd/container_opts.go

@@ -76,6 +76,23 @@ func WithContainerLabels(labels map[string]string) NewContainerOpts {
 	}
 }
 
+// WithImageStopSignal sets a well-known containerd label (StopSignalLabel)
+// on the container for storing the stop signal specified in the OCI image
+// config
+func WithImageStopSignal(image Image, defaultSignal string) NewContainerOpts {
+	return func(ctx context.Context, _ *Client, c *containers.Container) error {
+		if c.Labels == nil {
+			c.Labels = make(map[string]string)
+		}
+		stopSignal, err := GetOCIStopSignal(ctx, image, defaultSignal)
+		if err != nil {
+			return err
+		}
+		c.Labels[StopSignalLabel] = stopSignal
+		return nil
+	}
+}
+
 // WithSnapshotter sets the provided snapshotter for use by the container
 //
 // This option must appear before other snapshotter options to have an effect.

+ 2 - 2
vendor/github.com/containerd/containerd/containers/containers.go

@@ -28,12 +28,12 @@ import (
 //
 // The resources specified in this object are used to create tasks from the container.
 type Container struct {
-	// ID uniquely identifies the container in a nameapace.
+	// ID uniquely identifies the container in a namespace.
 	//
 	// This property is required and cannot be changed after creation.
 	ID string
 
-	// Labels provide metadata extension for a contaienr.
+	// Labels provide metadata extension for a container.
 	//
 	// These are optional and fully mutable.
 	Labels map[string]string

+ 6 - 0
vendor/github.com/containerd/containerd/image.go

@@ -37,6 +37,8 @@ type Image interface {
 	Name() string
 	// Target descriptor for the image content
 	Target() ocispec.Descriptor
+	// Labels of the image
+	Labels() map[string]string
 	// Unpack unpacks the image's content into a snapshot
 	Unpack(context.Context, string) error
 	// RootFS returns the unpacked diffids that make up images rootfs.
@@ -86,6 +88,10 @@ func (i *image) Target() ocispec.Descriptor {
 	return i.i.Target
 }
 
+func (i *image) Labels() map[string]string {
+	return i.i.Labels
+}
+
 func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) {
 	provider := i.client.ContentStore()
 	return i.i.RootFS(ctx, provider, i.platform)

+ 9 - 1
vendor/github.com/containerd/containerd/images/archive/importer.go

@@ -115,6 +115,10 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (oc
 		return idx, nil
 	}
 
+	if mfsts == nil {
+		return ocispec.Descriptor{}, errors.Errorf("unrecognized image format")
+	}
+
 	for name, linkname := range symlinks {
 		desc, ok := blobs[linkname]
 		if !ok {
@@ -123,7 +127,11 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (oc
 		blobs[name] = desc
 	}
 
-	var idx ocispec.Index
+	idx := ocispec.Index{
+		Versioned: specs.Versioned{
+			SchemaVersion: 2,
+		},
+	}
 	for _, mfst := range mfsts {
 		config, ok := blobs[mfst.Config]
 		if !ok {

+ 8 - 1
vendor/github.com/containerd/containerd/images/image.go

@@ -129,6 +129,13 @@ type platformManifest struct {
 
 // Manifest resolves a manifest from the image for the given platform.
 //
+// When a manifest descriptor inside of a manifest index does not have
+// a platform defined, the platform from the image config is considered.
+//
+// If the descriptor points to a non-index manifest, then the manifest is
+// unmarshalled and returned without considering the platform inside of the
+// config.
+//
 // TODO(stevvooe): This violates the current platform agnostic approach to this
 // package by returning a specific manifest type. We'll need to refactor this
 // to return a manifest descriptor or decide that we want to bring the API in
@@ -152,7 +159,7 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc
 				return nil, err
 			}
 
-			if platform != nil {
+			if desc.Digest != image.Digest && platform != nil {
 				if desc.Platform != nil && !platform.Match(*desc.Platform) {
 					return nil, nil
 				}

+ 13 - 4
vendor/github.com/containerd/containerd/metadata/content.go

@@ -553,7 +553,9 @@ func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected dig
 	nw.l.RLock()
 	defer nw.l.RUnlock()
 
-	return update(ctx, nw.db, func(tx *bolt.Tx) error {
+	var innerErr error
+
+	if err := update(ctx, nw.db, func(tx *bolt.Tx) error {
 		bkt := getIngestsBucket(tx, nw.namespace)
 		if bkt != nil {
 			if err := bkt.DeleteBucket([]byte(nw.ref)); err != nil && err != bolt.ErrBucketNotFound {
@@ -562,13 +564,20 @@ func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected dig
 		}
 		dgst, err := nw.commit(ctx, tx, size, expected, opts...)
 		if err != nil {
-			return err
+			if !errdefs.IsAlreadyExists(err) {
+				return err
+			}
+			innerErr = err
 		}
 		if err := removeIngestLease(ctx, tx, nw.ref); err != nil {
 			return err
 		}
 		return addContentLease(ctx, tx, dgst)
-	})
+	}); err != nil {
+		return err
+	}
+
+	return innerErr
 }
 
 func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64, expected digest.Digest, opts ...content.Opt) (digest.Digest, error) {
@@ -611,7 +620,7 @@ func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64,
 	bkt, err := createBlobBucket(tx, nw.namespace, actual)
 	if err != nil {
 		if err == bolt.ErrBucketExists {
-			return "", errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual)
+			return actual, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual)
 		}
 		return "", err
 	}

+ 15 - 0
vendor/github.com/containerd/containerd/oci/spec_opts.go

@@ -654,6 +654,10 @@ func WithUsername(username string) SpecOpts {
 // The passed in user can be either a uid or a username.
 func WithAdditionalGIDs(userstr string) SpecOpts {
 	return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) {
+		// For LCOW additional GID's not supported
+		if s.Windows != nil {
+			return nil
+		}
 		setProcess(s)
 		setAdditionalGids := func(root string) error {
 			var username string
@@ -1011,3 +1015,14 @@ var WithPrivileged = Compose(
 	WithApparmorProfile(""),
 	WithSeccompUnconfined,
 )
+
+// WithWindowsHyperV sets the Windows.HyperV section for HyperV isolation of containers.
+func WithWindowsHyperV(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
+	if s.Windows == nil {
+		s.Windows = &specs.Windows{}
+	}
+	if s.Windows.HyperV == nil {
+		s.Windows.HyperV = &specs.WindowsHyperV{}
+	}
+	return nil
+}

+ 317 - 0
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go

@@ -0,0 +1,317 @@
+/*
+   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 docker
+
+import (
+	"context"
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"strings"
+	"sync"
+	"time"
+
+	"github.com/containerd/containerd/errdefs"
+	"github.com/containerd/containerd/log"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
+	"golang.org/x/net/context/ctxhttp"
+)
+
+type dockerAuthorizer struct {
+	credentials func(string) (string, string, error)
+
+	client *http.Client
+	mu     sync.Mutex
+
+	auth map[string]string
+}
+
+// NewAuthorizer creates a Docker authorizer using the provided function to
+// get credentials for the token server or basic auth.
+func NewAuthorizer(client *http.Client, f func(string) (string, string, error)) Authorizer {
+	if client == nil {
+		client = http.DefaultClient
+	}
+	return &dockerAuthorizer{
+		credentials: f,
+		client:      client,
+		auth:        map[string]string{},
+	}
+}
+
+func (a *dockerAuthorizer) Authorize(ctx context.Context, req *http.Request) error {
+	// TODO: Lookup matching challenge and scope rather than just host
+	if auth := a.getAuth(req.URL.Host); auth != "" {
+		req.Header.Set("Authorization", auth)
+	}
+
+	return nil
+}
+
+func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.Response) error {
+	last := responses[len(responses)-1]
+	host := last.Request.URL.Host
+	for _, c := range parseAuthHeader(last.Header) {
+		if c.scheme == bearerAuth {
+			if err := invalidAuthorization(c, responses); err != nil {
+				// TODO: Clear token
+				a.setAuth(host, "")
+				return err
+			}
+
+			// TODO(dmcg): Store challenge, not token
+			// Move token fetching to authorize
+			if err := a.setTokenAuth(ctx, host, c.parameters); err != nil {
+				return err
+			}
+
+			return nil
+		} else if c.scheme == basicAuth {
+			// TODO: Resolve credentials on authorize
+			username, secret, err := a.credentials(host)
+			if err != nil {
+				return err
+			}
+			if username != "" && secret != "" {
+				auth := username + ":" + secret
+				a.setAuth(host, fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(auth))))
+				return nil
+			}
+		}
+	}
+
+	return errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
+}
+
+func (a *dockerAuthorizer) getAuth(host string) string {
+	a.mu.Lock()
+	defer a.mu.Unlock()
+
+	return a.auth[host]
+}
+
+func (a *dockerAuthorizer) setAuth(host string, auth string) bool {
+	a.mu.Lock()
+	defer a.mu.Unlock()
+
+	changed := a.auth[host] != auth
+	a.auth[host] = auth
+
+	return changed
+}
+
+func (a *dockerAuthorizer) setTokenAuth(ctx context.Context, host string, params map[string]string) error {
+	realm, ok := params["realm"]
+	if !ok {
+		return errors.New("no realm specified for token auth challenge")
+	}
+
+	realmURL, err := url.Parse(realm)
+	if err != nil {
+		return errors.Wrap(err, "invalid token auth challenge realm")
+	}
+
+	to := tokenOptions{
+		realm:   realmURL.String(),
+		service: params["service"],
+	}
+
+	to.scopes = getTokenScopes(ctx, params)
+	if len(to.scopes) == 0 {
+		return errors.Errorf("no scope specified for token auth challenge")
+	}
+
+	if a.credentials != nil {
+		to.username, to.secret, err = a.credentials(host)
+		if err != nil {
+			return err
+		}
+	}
+
+	var token string
+	if to.secret != "" {
+		// Credential information is provided, use oauth POST endpoint
+		token, err = a.fetchTokenWithOAuth(ctx, to)
+		if err != nil {
+			return errors.Wrap(err, "failed to fetch oauth token")
+		}
+	} else {
+		// Do request anonymously
+		token, err = a.fetchToken(ctx, to)
+		if err != nil {
+			return errors.Wrap(err, "failed to fetch anonymous token")
+		}
+	}
+	a.setAuth(host, fmt.Sprintf("Bearer %s", token))
+
+	return nil
+}
+
+type tokenOptions struct {
+	realm    string
+	service  string
+	scopes   []string
+	username string
+	secret   string
+}
+
+type postTokenResponse struct {
+	AccessToken  string    `json:"access_token"`
+	RefreshToken string    `json:"refresh_token"`
+	ExpiresIn    int       `json:"expires_in"`
+	IssuedAt     time.Time `json:"issued_at"`
+	Scope        string    `json:"scope"`
+}
+
+func (a *dockerAuthorizer) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
+	form := url.Values{}
+	form.Set("scope", strings.Join(to.scopes, " "))
+	form.Set("service", to.service)
+	// TODO: Allow setting client_id
+	form.Set("client_id", "containerd-client")
+
+	if to.username == "" {
+		form.Set("grant_type", "refresh_token")
+		form.Set("refresh_token", to.secret)
+	} else {
+		form.Set("grant_type", "password")
+		form.Set("username", to.username)
+		form.Set("password", to.secret)
+	}
+
+	resp, err := ctxhttp.PostForm(ctx, a.client, to.realm, form)
+	if err != nil {
+		return "", err
+	}
+	defer resp.Body.Close()
+
+	// Registries without support for POST may return 404 for POST /v2/token.
+	// As of September 2017, GCR is known to return 404.
+	// As of February 2018, JFrog Artifactory is known to return 401.
+	if (resp.StatusCode == 405 && to.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
+		return a.fetchToken(ctx, to)
+	} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
+		b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
+		log.G(ctx).WithFields(logrus.Fields{
+			"status": resp.Status,
+			"body":   string(b),
+		}).Debugf("token request failed")
+		// TODO: handle error body and write debug output
+		return "", errors.Errorf("unexpected status: %s", resp.Status)
+	}
+
+	decoder := json.NewDecoder(resp.Body)
+
+	var tr postTokenResponse
+	if err = decoder.Decode(&tr); err != nil {
+		return "", fmt.Errorf("unable to decode token response: %s", err)
+	}
+
+	return tr.AccessToken, nil
+}
+
+type getTokenResponse struct {
+	Token        string    `json:"token"`
+	AccessToken  string    `json:"access_token"`
+	ExpiresIn    int       `json:"expires_in"`
+	IssuedAt     time.Time `json:"issued_at"`
+	RefreshToken string    `json:"refresh_token"`
+}
+
+// getToken fetches a token using a GET request
+func (a *dockerAuthorizer) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
+	req, err := http.NewRequest("GET", to.realm, nil)
+	if err != nil {
+		return "", err
+	}
+
+	reqParams := req.URL.Query()
+
+	if to.service != "" {
+		reqParams.Add("service", to.service)
+	}
+
+	for _, scope := range to.scopes {
+		reqParams.Add("scope", scope)
+	}
+
+	if to.secret != "" {
+		req.SetBasicAuth(to.username, to.secret)
+	}
+
+	req.URL.RawQuery = reqParams.Encode()
+
+	resp, err := ctxhttp.Do(ctx, a.client, req)
+	if err != nil {
+		return "", err
+	}
+	defer resp.Body.Close()
+
+	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
+		// TODO: handle error body and write debug output
+		return "", errors.Errorf("unexpected status: %s", resp.Status)
+	}
+
+	decoder := json.NewDecoder(resp.Body)
+
+	var tr getTokenResponse
+	if err = decoder.Decode(&tr); err != nil {
+		return "", fmt.Errorf("unable to decode token response: %s", err)
+	}
+
+	// `access_token` is equivalent to `token` and if both are specified
+	// the choice is undefined.  Canonicalize `access_token` by sticking
+	// things in `token`.
+	if tr.AccessToken != "" {
+		tr.Token = tr.AccessToken
+	}
+
+	if tr.Token == "" {
+		return "", ErrNoToken
+	}
+
+	return tr.Token, nil
+}
+
+func invalidAuthorization(c challenge, responses []*http.Response) error {
+	errStr := c.parameters["error"]
+	if errStr == "" {
+		return nil
+	}
+
+	n := len(responses)
+	if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {
+		return nil
+	}
+
+	return errors.Wrapf(ErrInvalidAuthorization, "server message: %s", errStr)
+}
+
+func sameRequest(r1, r2 *http.Request) bool {
+	if r1.Method != r2.Method {
+		return false
+	}
+	if *r1.URL != *r2.URL {
+		return false
+	}
+	return true
+}

+ 69 - 269
vendor/github.com/containerd/containerd/remotes/docker/resolver.go

@@ -18,18 +18,13 @@ package docker
 
 import (
 	"context"
-	"encoding/json"
-	"fmt"
-	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"path"
 	"strconv"
 	"strings"
-	"sync"
-	"time"
 
+	"github.com/containerd/containerd/errdefs"
 	"github.com/containerd/containerd/images"
 	"github.com/containerd/containerd/log"
 	"github.com/containerd/containerd/reference"
@@ -51,19 +46,37 @@ var (
 	ErrInvalidAuthorization = errors.New("authorization failed")
 )
 
-type dockerResolver struct {
-	credentials func(string) (string, string, error)
-	host        func(string) (string, error)
-	plainHTTP   bool
-	client      *http.Client
-	tracker     StatusTracker
+// Authorizer is used to authorize HTTP requests based on 401 HTTP responses.
+// An Authorizer is responsible for caching tokens or credentials used by
+// requests.
+type Authorizer interface {
+	// Authorize sets the appropriate `Authorization` header on the given
+	// request.
+	//
+	// If no authorization is found for the request, the request remains
+	// unmodified. It may also add an `Authorization` header as
+	//  "bearer <some bearer token>"
+	//  "basic <base64 encoded credentials>"
+	Authorize(context.Context, *http.Request) error
+
+	// AddResponses adds a 401 response for the authorizer to consider when
+	// authorizing requests. The last response should be unauthorized and
+	// the previous requests are used to consider redirects and retries
+	// that may have led to the 401.
+	//
+	// If response is not handled, returns `ErrNotImplemented`
+	AddResponses(context.Context, []*http.Response) error
 }
 
 // ResolverOptions are used to configured a new Docker register resolver
 type ResolverOptions struct {
+	// Authorizer is used to authorize registry requests
+	Authorizer Authorizer
+
 	// Credentials provides username and secret given a host.
 	// If username is empty but a secret is given, that secret
 	// is interpretted as a long lived token.
+	// Deprecated: use Authorizer
 	Credentials func(string) (string, string, error)
 
 	// Host provides the hostname given a namespace.
@@ -89,22 +102,31 @@ func DefaultHost(ns string) (string, error) {
 	return ns, nil
 }
 
+type dockerResolver struct {
+	auth      Authorizer
+	host      func(string) (string, error)
+	plainHTTP bool
+	client    *http.Client
+	tracker   StatusTracker
+}
+
 // NewResolver returns a new resolver to a Docker registry
 func NewResolver(options ResolverOptions) remotes.Resolver {
-	tracker := options.Tracker
-	if tracker == nil {
-		tracker = NewInMemoryTracker()
+	if options.Tracker == nil {
+		options.Tracker = NewInMemoryTracker()
+	}
+	if options.Host == nil {
+		options.Host = DefaultHost
 	}
-	host := options.Host
-	if host == nil {
-		host = DefaultHost
+	if options.Authorizer == nil {
+		options.Authorizer = NewAuthorizer(options.Client, options.Credentials)
 	}
 	return &dockerResolver{
-		credentials: options.Credentials,
-		host:        host,
-		plainHTTP:   options.PlainHTTP,
-		client:      options.Client,
-		tracker:     tracker,
+		auth:      options.Authorizer,
+		host:      options.Host,
+		plainHTTP: options.PlainHTTP,
+		client:    options.Client,
+		tracker:   options.Tracker,
 	}
 }
 
@@ -272,18 +294,14 @@ type dockerBase struct {
 	refspec reference.Spec
 	base    url.URL
 
-	client           *http.Client
-	useBasic         bool
-	username, secret string
-	token            string
-	mu               sync.Mutex
+	client *http.Client
+	auth   Authorizer
 }
 
 func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {
 	var (
-		err              error
-		base             url.URL
-		username, secret string
+		err  error
+		base url.URL
 	)
 
 	host := refspec.Hostname()
@@ -300,61 +318,40 @@ func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {
 		base.Scheme = "http"
 	}
 
-	if r.credentials != nil {
-		username, secret, err = r.credentials(base.Host)
-		if err != nil {
-			return nil, err
-		}
-	}
-
 	prefix := strings.TrimPrefix(refspec.Locator, host+"/")
 	base.Path = path.Join("/v2", prefix)
 
 	return &dockerBase{
-		refspec:  refspec,
-		base:     base,
-		client:   r.client,
-		username: username,
-		secret:   secret,
+		refspec: refspec,
+		base:    base,
+		client:  r.client,
+		auth:    r.auth,
 	}, nil
 }
 
-func (r *dockerBase) getToken() string {
-	r.mu.Lock()
-	defer r.mu.Unlock()
-
-	return r.token
-}
-
-func (r *dockerBase) setToken(token string) bool {
-	r.mu.Lock()
-	defer r.mu.Unlock()
-
-	changed := r.token != token
-	r.token = token
-
-	return changed
-}
-
 func (r *dockerBase) url(ps ...string) string {
 	url := r.base
 	url.Path = path.Join(url.Path, path.Join(ps...))
 	return url.String()
 }
 
-func (r *dockerBase) authorize(req *http.Request) {
-	token := r.getToken()
-	if r.useBasic {
-		req.SetBasicAuth(r.username, r.secret)
-	} else if token != "" {
-		req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
+func (r *dockerBase) authorize(ctx context.Context, req *http.Request) error {
+	// Check if has header for host
+	if r.auth != nil {
+		if err := r.auth.Authorize(ctx, req); err != nil {
+			return err
+		}
 	}
+
+	return nil
 }
 
 func (r *dockerBase) doRequest(ctx context.Context, req *http.Request) (*http.Response, error) {
 	ctx = log.WithLogger(ctx, log.G(ctx).WithField("url", req.URL.String()))
 	log.G(ctx).WithField("request.headers", req.Header).WithField("request.method", req.Method).Debug("do request")
-	r.authorize(req)
+	if err := r.authorize(ctx, req); err != nil {
+		return nil, errors.Wrap(err, "failed to authorize")
+	}
 	resp, err := ctxhttp.Do(ctx, r.client, req)
 	if err != nil {
 		return nil, errors.Wrap(err, "failed to do request")
@@ -392,23 +389,14 @@ func (r *dockerBase) retryRequest(ctx context.Context, req *http.Request, respon
 	last := responses[len(responses)-1]
 	if last.StatusCode == http.StatusUnauthorized {
 		log.G(ctx).WithField("header", last.Header.Get("WWW-Authenticate")).Debug("Unauthorized")
-		for _, c := range parseAuthHeader(last.Header) {
-			if c.scheme == bearerAuth {
-				if err := invalidAuthorization(c, responses); err != nil {
-					r.setToken("")
-					return nil, err
-				}
-				if err := r.setTokenAuth(ctx, c.parameters); err != nil {
-					return nil, err
-				}
-				return copyRequest(req)
-			} else if c.scheme == basicAuth {
-				if r.username != "" && r.secret != "" {
-					r.useBasic = true
-				}
+		if r.auth != nil {
+			if err := r.auth.AddResponses(ctx, responses); err == nil {
 				return copyRequest(req)
+			} else if !errdefs.IsNotImplemented(err) {
+				return nil, err
 			}
 		}
+
 		return nil, nil
 	} else if last.StatusCode == http.StatusMethodNotAllowed && req.Method == http.MethodHead {
 		// Support registries which have not properly implemented the HEAD method for
@@ -424,30 +412,6 @@ func (r *dockerBase) retryRequest(ctx context.Context, req *http.Request, respon
 	return nil, nil
 }
 
-func invalidAuthorization(c challenge, responses []*http.Response) error {
-	errStr := c.parameters["error"]
-	if errStr == "" {
-		return nil
-	}
-
-	n := len(responses)
-	if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {
-		return nil
-	}
-
-	return errors.Wrapf(ErrInvalidAuthorization, "server message: %s", errStr)
-}
-
-func sameRequest(r1, r2 *http.Request) bool {
-	if r1.Method != r2.Method {
-		return false
-	}
-	if *r1.URL != *r2.URL {
-		return false
-	}
-	return true
-}
-
 func copyRequest(req *http.Request) (*http.Request, error) {
 	ireq := *req
 	if ireq.GetBody != nil {
@@ -459,167 +423,3 @@ func copyRequest(req *http.Request) (*http.Request, error) {
 	}
 	return &ireq, nil
 }
-
-func (r *dockerBase) setTokenAuth(ctx context.Context, params map[string]string) error {
-	realm, ok := params["realm"]
-	if !ok {
-		return errors.New("no realm specified for token auth challenge")
-	}
-
-	realmURL, err := url.Parse(realm)
-	if err != nil {
-		return fmt.Errorf("invalid token auth challenge realm: %s", err)
-	}
-
-	to := tokenOptions{
-		realm:   realmURL.String(),
-		service: params["service"],
-	}
-
-	to.scopes = getTokenScopes(ctx, params)
-	if len(to.scopes) == 0 {
-		return errors.Errorf("no scope specified for token auth challenge")
-	}
-
-	var token string
-	if r.secret != "" {
-		// Credential information is provided, use oauth POST endpoint
-		token, err = r.fetchTokenWithOAuth(ctx, to)
-		if err != nil {
-			return errors.Wrap(err, "failed to fetch oauth token")
-		}
-	} else {
-		// Do request anonymously
-		token, err = r.fetchToken(ctx, to)
-		if err != nil {
-			return errors.Wrap(err, "failed to fetch anonymous token")
-		}
-	}
-	r.setToken(token)
-
-	return nil
-}
-
-type tokenOptions struct {
-	realm   string
-	service string
-	scopes  []string
-}
-
-type postTokenResponse struct {
-	AccessToken  string    `json:"access_token"`
-	RefreshToken string    `json:"refresh_token"`
-	ExpiresIn    int       `json:"expires_in"`
-	IssuedAt     time.Time `json:"issued_at"`
-	Scope        string    `json:"scope"`
-}
-
-func (r *dockerBase) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
-	form := url.Values{}
-	form.Set("scope", strings.Join(to.scopes, " "))
-	form.Set("service", to.service)
-	// TODO: Allow setting client_id
-	form.Set("client_id", "containerd-dist-tool")
-
-	if r.username == "" {
-		form.Set("grant_type", "refresh_token")
-		form.Set("refresh_token", r.secret)
-	} else {
-		form.Set("grant_type", "password")
-		form.Set("username", r.username)
-		form.Set("password", r.secret)
-	}
-
-	resp, err := ctxhttp.PostForm(ctx, r.client, to.realm, form)
-	if err != nil {
-		return "", err
-	}
-	defer resp.Body.Close()
-
-	// Registries without support for POST may return 404 for POST /v2/token.
-	// As of September 2017, GCR is known to return 404.
-	// As of February 2018, JFrog Artifactory is known to return 401.
-	if (resp.StatusCode == 405 && r.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
-		return r.fetchToken(ctx, to)
-	} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
-		b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
-		log.G(ctx).WithFields(logrus.Fields{
-			"status": resp.Status,
-			"body":   string(b),
-		}).Debugf("token request failed")
-		// TODO: handle error body and write debug output
-		return "", errors.Errorf("unexpected status: %s", resp.Status)
-	}
-
-	decoder := json.NewDecoder(resp.Body)
-
-	var tr postTokenResponse
-	if err = decoder.Decode(&tr); err != nil {
-		return "", fmt.Errorf("unable to decode token response: %s", err)
-	}
-
-	return tr.AccessToken, nil
-}
-
-type getTokenResponse struct {
-	Token        string    `json:"token"`
-	AccessToken  string    `json:"access_token"`
-	ExpiresIn    int       `json:"expires_in"`
-	IssuedAt     time.Time `json:"issued_at"`
-	RefreshToken string    `json:"refresh_token"`
-}
-
-// getToken fetches a token using a GET request
-func (r *dockerBase) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
-	req, err := http.NewRequest("GET", to.realm, nil)
-	if err != nil {
-		return "", err
-	}
-
-	reqParams := req.URL.Query()
-
-	if to.service != "" {
-		reqParams.Add("service", to.service)
-	}
-
-	for _, scope := range to.scopes {
-		reqParams.Add("scope", scope)
-	}
-
-	if r.secret != "" {
-		req.SetBasicAuth(r.username, r.secret)
-	}
-
-	req.URL.RawQuery = reqParams.Encode()
-
-	resp, err := ctxhttp.Do(ctx, r.client, req)
-	if err != nil {
-		return "", err
-	}
-	defer resp.Body.Close()
-
-	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
-		// TODO: handle error body and write debug output
-		return "", errors.Errorf("unexpected status: %s", resp.Status)
-	}
-
-	decoder := json.NewDecoder(resp.Body)
-
-	var tr getTokenResponse
-	if err = decoder.Decode(&tr); err != nil {
-		return "", fmt.Errorf("unable to decode token response: %s", err)
-	}
-
-	// `access_token` is equivalent to `token` and if both are specified
-	// the choice is undefined.  Canonicalize `access_token` by sticking
-	// things in `token`.
-	if tr.AccessToken != "" {
-		tr.Token = tr.AccessToken
-	}
-
-	if tr.Token == "" {
-		return "", ErrNoToken
-	}
-
-	return tr.Token, nil
-}

+ 3 - 4
vendor/github.com/containerd/containerd/runtime/v1/linux/bundle.go

@@ -46,6 +46,9 @@ func newBundle(id, path, workDir string, spec []byte) (b *bundle, err error) {
 		return nil, err
 	}
 	path = filepath.Join(path, id)
+	if err := os.Mkdir(path, 0711); err != nil {
+		return nil, err
+	}
 	defer func() {
 		if err != nil {
 			os.RemoveAll(path)
@@ -60,10 +63,6 @@ func newBundle(id, path, workDir string, spec []byte) (b *bundle, err error) {
 			os.RemoveAll(workDir)
 		}
 	}()
-
-	if err := os.Mkdir(path, 0711); err != nil {
-		return nil, err
-	}
 	if err := os.Mkdir(filepath.Join(path, "rootfs"), 0711); err != nil {
 		return nil, err
 	}

+ 60 - 0
vendor/github.com/containerd/containerd/signal_map_linux.go

@@ -0,0 +1,60 @@
+/*
+   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 (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var signalMap = map[string]syscall.Signal{
+	"ABRT":   unix.SIGABRT,
+	"ALRM":   unix.SIGALRM,
+	"BUS":    unix.SIGBUS,
+	"CHLD":   unix.SIGCHLD,
+	"CLD":    unix.SIGCLD,
+	"CONT":   unix.SIGCONT,
+	"FPE":    unix.SIGFPE,
+	"HUP":    unix.SIGHUP,
+	"ILL":    unix.SIGILL,
+	"INT":    unix.SIGINT,
+	"IO":     unix.SIGIO,
+	"IOT":    unix.SIGIOT,
+	"KILL":   unix.SIGKILL,
+	"PIPE":   unix.SIGPIPE,
+	"POLL":   unix.SIGPOLL,
+	"PROF":   unix.SIGPROF,
+	"PWR":    unix.SIGPWR,
+	"QUIT":   unix.SIGQUIT,
+	"SEGV":   unix.SIGSEGV,
+	"STKFLT": unix.SIGSTKFLT,
+	"STOP":   unix.SIGSTOP,
+	"SYS":    unix.SIGSYS,
+	"TERM":   unix.SIGTERM,
+	"TRAP":   unix.SIGTRAP,
+	"TSTP":   unix.SIGTSTP,
+	"TTIN":   unix.SIGTTIN,
+	"TTOU":   unix.SIGTTOU,
+	"URG":    unix.SIGURG,
+	"USR1":   unix.SIGUSR1,
+	"USR2":   unix.SIGUSR2,
+	"VTALRM": unix.SIGVTALRM,
+	"WINCH":  unix.SIGWINCH,
+	"XCPU":   unix.SIGXCPU,
+	"XFSZ":   unix.SIGXFSZ,
+}

+ 58 - 0
vendor/github.com/containerd/containerd/signal_map_unix.go

@@ -0,0 +1,58 @@
+// +build darwin freebsd solaris
+
+/*
+   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 (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+var signalMap = map[string]syscall.Signal{
+	"ABRT":   unix.SIGABRT,
+	"ALRM":   unix.SIGALRM,
+	"BUS":    unix.SIGBUS,
+	"CHLD":   unix.SIGCHLD,
+	"CONT":   unix.SIGCONT,
+	"FPE":    unix.SIGFPE,
+	"HUP":    unix.SIGHUP,
+	"ILL":    unix.SIGILL,
+	"INT":    unix.SIGINT,
+	"IO":     unix.SIGIO,
+	"IOT":    unix.SIGIOT,
+	"KILL":   unix.SIGKILL,
+	"PIPE":   unix.SIGPIPE,
+	"PROF":   unix.SIGPROF,
+	"QUIT":   unix.SIGQUIT,
+	"SEGV":   unix.SIGSEGV,
+	"STOP":   unix.SIGSTOP,
+	"SYS":    unix.SIGSYS,
+	"TERM":   unix.SIGTERM,
+	"TRAP":   unix.SIGTRAP,
+	"TSTP":   unix.SIGTSTP,
+	"TTIN":   unix.SIGTTIN,
+	"TTOU":   unix.SIGTTOU,
+	"URG":    unix.SIGURG,
+	"USR1":   unix.SIGUSR1,
+	"USR2":   unix.SIGUSR2,
+	"VTALRM": unix.SIGVTALRM,
+	"WINCH":  unix.SIGWINCH,
+	"XCPU":   unix.SIGXCPU,
+	"XFSZ":   unix.SIGXFSZ,
+}

+ 39 - 0
vendor/github.com/containerd/containerd/signal_map_windows.go

@@ -0,0 +1,39 @@
+/*
+   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 (
+	"syscall"
+
+	"golang.org/x/sys/windows"
+)
+
+var signalMap = map[string]syscall.Signal{
+	"HUP":    syscall.Signal(windows.SIGHUP),
+	"INT":    syscall.Signal(windows.SIGINT),
+	"QUIT":   syscall.Signal(windows.SIGQUIT),
+	"SIGILL": syscall.Signal(windows.SIGILL),
+	"TRAP":   syscall.Signal(windows.SIGTRAP),
+	"ABRT":   syscall.Signal(windows.SIGABRT),
+	"BUS":    syscall.Signal(windows.SIGBUS),
+	"FPE":    syscall.Signal(windows.SIGFPE),
+	"KILL":   syscall.Signal(windows.SIGKILL),
+	"SEGV":   syscall.Signal(windows.SIGSEGV),
+	"PIPE":   syscall.Signal(windows.SIGPIPE),
+	"ALRM":   syscall.Signal(windows.SIGALRM),
+	"TERM":   syscall.Signal(windows.SIGTERM),
+}

+ 105 - 0
vendor/github.com/containerd/containerd/signals.go

@@ -0,0 +1,105 @@
+/*
+   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 (
+	"context"
+	"encoding/json"
+	"fmt"
+	"strconv"
+	"strings"
+	"syscall"
+
+	"github.com/containerd/containerd/content"
+	"github.com/containerd/containerd/images"
+	"github.com/opencontainers/image-spec/specs-go/v1"
+)
+
+// StopSignalLabel is a well-known containerd label for storing the stop
+// signal specified in the OCI image config
+const StopSignalLabel = "io.containerd.image.config.stop-signal"
+
+// GetStopSignal retrieves the container stop signal, specified by the
+// well-known containerd label (StopSignalLabel)
+func GetStopSignal(ctx context.Context, container Container, defaultSignal syscall.Signal) (syscall.Signal, error) {
+	labels, err := container.Labels(ctx)
+	if err != nil {
+		return -1, err
+	}
+
+	if stopSignal, ok := labels[StopSignalLabel]; ok {
+		return ParseSignal(stopSignal)
+	}
+
+	return defaultSignal, nil
+}
+
+// GetOCIStopSignal retrieves the stop signal specified in the OCI image config
+func GetOCIStopSignal(ctx context.Context, image Image, defaultSignal string) (string, error) {
+	_, err := ParseSignal(defaultSignal)
+	if err != nil {
+		return "", err
+	}
+	ic, err := image.Config(ctx)
+	if err != nil {
+		return "", err
+	}
+	var (
+		ociimage v1.Image
+		config   v1.ImageConfig
+	)
+	switch ic.MediaType {
+	case v1.MediaTypeImageConfig, images.MediaTypeDockerSchema2Config:
+		p, err := content.ReadBlob(ctx, image.ContentStore(), ic)
+		if err != nil {
+			return "", err
+		}
+
+		if err := json.Unmarshal(p, &ociimage); err != nil {
+			return "", err
+		}
+		config = ociimage.Config
+	default:
+		return "", fmt.Errorf("unknown image config media type %s", ic.MediaType)
+	}
+
+	if config.StopSignal == "" {
+		return defaultSignal, nil
+	}
+
+	return config.StopSignal, nil
+}
+
+// ParseSignal parses a given string into a syscall.Signal
+// it checks that the signal exists in the platform-appropriate signalMap
+func ParseSignal(rawSignal string) (syscall.Signal, error) {
+	s, err := strconv.Atoi(rawSignal)
+	if err == nil {
+		sig := syscall.Signal(s)
+		for _, msig := range signalMap {
+			if sig == msig {
+				return sig, nil
+			}
+		}
+		return -1, fmt.Errorf("unknown signal %q", rawSignal)
+	}
+	signal, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
+	if !ok {
+		return -1, fmt.Errorf("unknown signal %q", rawSignal)
+	}
+	return signal, nil
+}

+ 4 - 4
vendor/github.com/containerd/containerd/vendor.conf

@@ -4,7 +4,7 @@ github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
 github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244
-github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537
+github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
 github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
 github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
@@ -20,7 +20,7 @@ github.com/gogo/protobuf v1.0.0
 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
 github.com/golang/protobuf v1.1.0
 github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
-github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd
+github.com/opencontainers/runc 00dc70017d222b178a002ed30e9321b12647af2d
 github.com/sirupsen/logrus v1.0.0
 github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
 golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
@@ -33,10 +33,10 @@ golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
 github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
 github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
 github.com/Microsoft/go-winio v0.4.10
-github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55
+github.com/Microsoft/hcsshim v0.7.6
 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
-github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
+github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
 github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
 gotest.tools v2.1.0
 github.com/google/go-cmp v0.1.0

+ 16 - 0
vendor/github.com/containerd/continuity/context.go

@@ -1,3 +1,19 @@
+/*
+   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 continuity
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/devices/devices.go

@@ -1,3 +1,19 @@
+/*
+   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 devices
 
 import "fmt"

+ 16 - 0
vendor/github.com/containerd/continuity/devices/devices_unix.go

@@ -1,5 +1,21 @@
 // +build linux darwin freebsd solaris
 
+/*
+   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 devices
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/devices/devices_windows.go

@@ -1,3 +1,19 @@
+/*
+   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 devices
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/digests.go

@@ -1,3 +1,19 @@
+/*
+   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 continuity
 
 import (

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

@@ -1,3 +1,19 @@
+/*
+   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 driver
 
 import (

+ 26 - 2
vendor/github.com/containerd/continuity/driver/driver_unix.go

@@ -1,5 +1,21 @@
 // +build linux darwin freebsd solaris
 
+/*
+   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 driver
 
 import (
@@ -13,7 +29,11 @@ import (
 )
 
 func (d *driver) Mknod(path string, mode os.FileMode, major, minor int) error {
-	return devices.Mknod(path, mode, major, minor)
+	err := devices.Mknod(path, mode, major, minor)
+	if err != nil {
+		err = &os.PathError{Op: "mknod", Path: path, Err: err}
+	}
+	return err
 }
 
 func (d *driver) Mkfifo(path string, mode os.FileMode) error {
@@ -22,7 +42,11 @@ func (d *driver) Mkfifo(path string, mode os.FileMode) error {
 	}
 	// mknod with a mode that has ModeNamedPipe set creates a fifo, not a
 	// device.
-	return devices.Mknod(path, mode, 0, 0)
+	err := devices.Mknod(path, mode, 0, 0)
+	if err != nil {
+		err = &os.PathError{Op: "mkfifo", Path: path, Err: err}
+	}
+	return err
 }
 
 // Getxattr returns all of the extended attributes for the file at path p.

+ 18 - 3
vendor/github.com/containerd/continuity/driver/driver_windows.go

@@ -1,18 +1,33 @@
+/*
+   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 driver
 
 import (
 	"os"
 
 	"github.com/containerd/continuity/sysx"
-	"github.com/pkg/errors"
 )
 
 func (d *driver) Mknod(path string, mode os.FileMode, major, minor int) error {
-	return errors.Wrap(ErrNotSupported, "cannot create device node on Windows")
+	return &os.PathError{Op: "mknod", Path: path, Err: ErrNotSupported}
 }
 
 func (d *driver) Mkfifo(path string, mode os.FileMode) error {
-	return errors.Wrap(ErrNotSupported, "cannot create fifo on Windows")
+	return &os.PathError{Op: "mkfifo", Path: path, Err: ErrNotSupported}
 }
 
 // Lchmod changes the mode of an file not following symlinks.

+ 21 - 1
vendor/github.com/containerd/continuity/driver/lchmod_linux.go

@@ -1,3 +1,19 @@
+/*
+   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 driver
 
 import (
@@ -15,5 +31,9 @@ func (d *driver) Lchmod(path string, mode os.FileMode) error {
 		return nil
 	}
 
-	return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0)
+	err := unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0)
+	if err != nil {
+		err = &os.PathError{Op: "lchmod", Path: path, Err: err}
+	}
+	return err
 }

+ 21 - 1
vendor/github.com/containerd/continuity/driver/lchmod_unix.go

@@ -1,5 +1,21 @@
 // +build darwin freebsd solaris
 
+/*
+   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 driver
 
 import (
@@ -10,5 +26,9 @@ import (
 
 // 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)
+	err := unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW)
+	if err != nil {
+		err = &os.PathError{Op: "lchmod", Path: path, Err: err}
+	}
+	return err
 }

+ 16 - 0
vendor/github.com/containerd/continuity/driver/utils.go

@@ -1,3 +1,19 @@
+/*
+   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 driver
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/copy.go

@@ -1,3 +1,19 @@
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/copy_linux.go

@@ -1,3 +1,19 @@
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/copy_unix.go

@@ -1,5 +1,21 @@
 // +build solaris darwin freebsd
 
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/copy_windows.go

@@ -1,3 +1,19 @@
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/diff.go

@@ -1,3 +1,19 @@
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/diff_unix.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/diff_windows.go

@@ -1,3 +1,19 @@
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/dtype_linux.go

@@ -1,5 +1,21 @@
 // +build linux
 
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/du.go

@@ -1,3 +1,19 @@
+/*
+   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 fs
 
 import "context"

+ 16 - 0
vendor/github.com/containerd/continuity/fs/du_unix.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/du_windows.go

@@ -1,5 +1,21 @@
 // +build windows
 
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/hardlink.go

@@ -1,3 +1,19 @@
+/*
+   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 fs
 
 import "os"

+ 16 - 0
vendor/github.com/containerd/continuity/fs/hardlink_unix.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/hardlink_windows.go

@@ -1,3 +1,19 @@
+/*
+   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 fs
 
 import "os"

+ 16 - 6
vendor/github.com/containerd/continuity/fs/path.go

@@ -1,3 +1,19 @@
+/*
+   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 fs
 
 import (
@@ -232,12 +248,6 @@ func walkLink(root, path string, linksWalked *int) (newpath string, islink bool,
 	if err != nil {
 		return "", false, err
 	}
-	if filepath.IsAbs(newpath) && strings.HasPrefix(newpath, root) {
-		newpath = newpath[:len(root)]
-		if !strings.HasPrefix(newpath, "/") {
-			newpath = "/" + newpath
-		}
-	}
 	*linksWalked++
 	return newpath, true, nil
 }

+ 16 - 0
vendor/github.com/containerd/continuity/fs/stat_bsd.go

@@ -1,5 +1,21 @@
 // +build darwin freebsd
 
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/stat_linux.go

@@ -1,3 +1,19 @@
+/*
+   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 fs
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/fs/time.go

@@ -1,3 +1,19 @@
+/*
+   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 fs
 
 import "time"

+ 16 - 0
vendor/github.com/containerd/continuity/groups_unix.go

@@ -1,3 +1,19 @@
+/*
+   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 continuity
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/hardlinks.go

@@ -1,3 +1,19 @@
+/*
+   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 continuity
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/hardlinks_unix.go

@@ -1,5 +1,21 @@
 // +build linux darwin freebsd solaris
 
+/*
+   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 continuity
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/hardlinks_windows.go

@@ -1,3 +1,19 @@
+/*
+   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 continuity
 
 import "os"

+ 16 - 0
vendor/github.com/containerd/continuity/ioutils.go

@@ -1,3 +1,19 @@
+/*
+   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 continuity
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/manifest.go

@@ -1,3 +1,19 @@
+/*
+   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 continuity
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/pathdriver/path_driver.go

@@ -1,3 +1,19 @@
+/*
+   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 pathdriver
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/proto/gen.go

@@ -1,3 +1,19 @@
+/*
+   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 proto
 
 //go:generate protoc --go_out=. manifest.proto

+ 16 - 0
vendor/github.com/containerd/continuity/resource.go

@@ -1,3 +1,19 @@
+/*
+   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 continuity
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/resource_unix.go

@@ -1,5 +1,21 @@
 // +build linux darwin freebsd solaris
 
+/*
+   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 continuity
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/resource_windows.go

@@ -1,3 +1,19 @@
+/*
+   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 continuity
 
 import "os"

+ 16 - 0
vendor/github.com/containerd/continuity/syscallx/syscall_unix.go

@@ -1,5 +1,21 @@
 // +build !windows
 
+/*
+   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 syscallx
 
 import "syscall"

+ 16 - 0
vendor/github.com/containerd/continuity/syscallx/syscall_windows.go

@@ -1,3 +1,19 @@
+/*
+   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 syscallx
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/sysx/file_posix.go

@@ -1,3 +1,19 @@
+/*
+   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 sysx
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/sysx/nodata_linux.go

@@ -1,3 +1,19 @@
+/*
+   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 sysx
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/sysx/nodata_solaris.go

@@ -1,3 +1,19 @@
+/*
+   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 sysx
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/sysx/nodata_unix.go

@@ -1,5 +1,21 @@
 // +build darwin freebsd
 
+/*
+   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 sysx
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/sysx/xattr.go

@@ -1,5 +1,21 @@
 // +build linux darwin
 
+/*
+   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 sysx
 
 import (

+ 16 - 0
vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go

@@ -1,5 +1,21 @@
 // +build !linux,!darwin
 
+/*
+   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 sysx
 
 import (

+ 4 - 0
vendor/github.com/containerd/ttrpc/client.go

@@ -110,12 +110,16 @@ func (c *Client) dispatch(ctx context.Context, req *Request, resp *Response) err
 	}
 
 	select {
+	case <-ctx.Done():
+		return ctx.Err()
 	case c.calls <- call:
 	case <-c.done:
 		return c.err
 	}
 
 	select {
+	case <-ctx.Done():
+		return ctx.Err()
 	case err := <-errs:
 		return filterCloseErr(err)
 	case <-c.done:

+ 1 - 1
vendor/github.com/containerd/ttrpc/server.go

@@ -127,13 +127,13 @@ func (s *Server) Serve(ctx context.Context, l net.Listener) error {
 
 func (s *Server) Shutdown(ctx context.Context) error {
 	s.mu.Lock()
-	lnerr := s.closeListeners()
 	select {
 	case <-s.done:
 	default:
 		// protected by mutex
 		close(s.done)
 	}
+	lnerr := s.closeListeners()
 	s.mu.Unlock()
 
 	ticker := time.NewTicker(200 * time.Millisecond)

+ 11 - 9
vendor/github.com/grpc-ecosystem/go-grpc-prometheus/README.md

@@ -3,6 +3,8 @@
 [![Travis Build](https://travis-ci.org/grpc-ecosystem/go-grpc-prometheus.svg)](https://travis-ci.org/grpc-ecosystem/go-grpc-prometheus)
 [![Go Report Card](https://goreportcard.com/badge/github.com/grpc-ecosystem/go-grpc-prometheus)](http://goreportcard.com/report/grpc-ecosystem/go-grpc-prometheus)
 [![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/grpc-ecosystem/go-grpc-prometheus)
+[![SourceGraph](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-prometheus/-/badge.svg)](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-prometheus/?badge)
+[![codecov](https://codecov.io/gh/grpc-ecosystem/go-grpc-prometheus/branch/master/graph/badge.svg)](https://codecov.io/gh/grpc-ecosystem/go-grpc-prometheus)
 [![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
 
 [Prometheus](https://prometheus.io/) monitoring for your [gRPC Go](https://github.com/grpc/grpc-go) servers and clients.
@@ -36,7 +38,7 @@ import "github.com/grpc-ecosystem/go-grpc-prometheus"
     // After all your registrations, make sure all of the Prometheus metrics are initialized.
     grpc_prometheus.Register(myServer)
     // Register Prometheus metrics handler.    
-    http.Handle("/metrics", prometheus.Handler())
+    http.Handle("/metrics", promhttp.Handler())
 ...
 ```
 
@@ -47,8 +49,8 @@ import "github.com/grpc-ecosystem/go-grpc-prometheus"
 ...
    clientConn, err = grpc.Dial(
        address,
-		   grpc.WithUnaryInterceptor(UnaryClientInterceptor),
-		   grpc.WithStreamInterceptor(StreamClientInterceptor)
+		   grpc.WithUnaryInterceptor(grpc_prometheus.UnaryClientInterceptor),
+		   grpc.WithStreamInterceptor(grpc_prometheus.StreamClientInterceptor)
    )
    client = pb_testproto.NewTestServiceClient(clientConn)
    resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"})
@@ -116,7 +118,7 @@ each of the 20 messages sent back, a counter will be incremented:
 grpc_server_msg_sent_total{grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 20
 ```
 
-After the call completes, it's status (`OK` or other [gRPC status code](https://github.com/grpc/grpc-go/blob/master/codes/codes.go)) 
+After the call completes, its status (`OK` or other [gRPC status code](https://github.com/grpc/grpc-go/blob/master/codes/codes.go)) 
 and the relevant call labels increment the `grpc_server_handled_total` counter.
 
 ```jsoniq
@@ -126,8 +128,8 @@ grpc_server_handled_total{grpc_code="OK",grpc_method="PingList",grpc_service="mw
 ## Histograms
 
 [Prometheus histograms](https://prometheus.io/docs/concepts/metric_types/#histogram) are a great way
-to measure latency distributions of your RPCs. However since it is bad practice to have metrics
-of [high cardinality](https://prometheus.io/docs/practices/instrumentation/#do-not-overuse-labels))
+to measure latency distributions of your RPCs. However, since it is bad practice to have metrics
+of [high cardinality](https://prometheus.io/docs/practices/instrumentation/#do-not-overuse-labels)
 the latency monitoring metrics are disabled by default. To enable them please call the following
 in your server initialization code:
 
@@ -135,8 +137,8 @@ in your server initialization code:
 grpc_prometheus.EnableHandlingTimeHistogram()
 ```
 
-After the call completes, it's handling time will be recorded in a [Prometheus histogram](https://prometheus.io/docs/concepts/metric_types/#histogram)
-variable `grpc_server_handling_seconds`. It contains three sub-metrics:
+After the call completes, its handling time will be recorded in a [Prometheus histogram](https://prometheus.io/docs/concepts/metric_types/#histogram)
+variable `grpc_server_handling_seconds`. The histogram variable contains three sub-metrics:
 
  * `grpc_server_handling_seconds_count` - the count of all completed RPCs by status and method 
  * `grpc_server_handling_seconds_sum` - cumulative time of RPCs by status and method, useful for 
@@ -166,7 +168,7 @@ grpc_server_handling_seconds_count{grpc_code="OK",grpc_method="PingList",grpc_se
 
 ## Useful query examples
 
-Prometheus philosophy is to provide the most detailed metrics possible to the monitoring system, and
+Prometheus philosophy is to provide raw metrics to the monitoring system, and
 let the aggregations be handled there. The verbosity of above metrics make it possible to have that
 flexibility. Here's a couple of useful monitoring queries:
 

+ 23 - 56
vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client.go

@@ -6,67 +6,34 @@
 package grpc_prometheus
 
 import (
-	"io"
-
-	"golang.org/x/net/context"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/codes"
+	prom "github.com/prometheus/client_golang/prometheus"
 )
 
-// UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs.
-func UnaryClientInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
-	monitor := newClientReporter(Unary, method)
-	monitor.SentMessage()
-	err := invoker(ctx, method, req, reply, cc, opts...)
-	if err != nil {
-		monitor.ReceivedMessage()
-	}
-	monitor.Handled(grpc.Code(err))
-	return err
-}
+var (
+	// DefaultClientMetrics is the default instance of ClientMetrics. It is
+	// intended to be used in conjunction the default Prometheus metrics
+	// registry.
+	DefaultClientMetrics = NewClientMetrics()
 
-// StreamServerInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs.
-func StreamClientInterceptor(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
-	monitor := newClientReporter(clientStreamType(desc), method)
-	clientStream, err := streamer(ctx, desc, cc, method, opts...)
-	if err != nil {
-		monitor.Handled(grpc.Code(err))
-		return nil, err
-	}
-	return &monitoredClientStream{clientStream, monitor}, nil
-}
+	// UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs.
+	UnaryClientInterceptor = DefaultClientMetrics.UnaryClientInterceptor()
 
-func clientStreamType(desc *grpc.StreamDesc) grpcType {
-	if desc.ClientStreams && !desc.ServerStreams {
-		return ClientStream
-	} else if !desc.ClientStreams && desc.ServerStreams {
-		return ServerStream
-	}
-	return BidiStream
-}
-
-// monitoredClientStream wraps grpc.ClientStream allowing each Sent/Recv of message to increment counters.
-type monitoredClientStream struct {
-	grpc.ClientStream
-	monitor *clientReporter
-}
+	// StreamClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs.
+	StreamClientInterceptor = DefaultClientMetrics.StreamClientInterceptor()
+)
 
-func (s *monitoredClientStream) SendMsg(m interface{}) error {
-	err := s.ClientStream.SendMsg(m)
-	if err == nil {
-		s.monitor.SentMessage()
-	}
-	return err
+func init() {
+	prom.MustRegister(DefaultClientMetrics.clientStartedCounter)
+	prom.MustRegister(DefaultClientMetrics.clientHandledCounter)
+	prom.MustRegister(DefaultClientMetrics.clientStreamMsgReceived)
+	prom.MustRegister(DefaultClientMetrics.clientStreamMsgSent)
 }
 
-func (s *monitoredClientStream) RecvMsg(m interface{}) error {
-	err := s.ClientStream.RecvMsg(m)
-	if err == nil {
-		s.monitor.ReceivedMessage()
-	} else if err == io.EOF {
-		s.monitor.Handled(codes.OK)
-	} else {
-		s.monitor.Handled(grpc.Code(err))
-	}
-	return err
+// EnableClientHandlingTimeHistogram turns on recording of handling time of
+// RPCs. Histogram metrics can be very expensive for Prometheus to retain and
+// query. This function acts on the DefaultClientMetrics variable and the
+// default Prometheus metrics registry.
+func EnableClientHandlingTimeHistogram(opts ...HistogramOption) {
+	DefaultClientMetrics.EnableClientHandlingTimeHistogram(opts...)
+	prom.Register(DefaultClientMetrics.clientHandledHistogram)
 }

+ 170 - 0
vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_metrics.go

@@ -0,0 +1,170 @@
+package grpc_prometheus
+
+import (
+	"io"
+
+	prom "github.com/prometheus/client_golang/prometheus"
+	"golang.org/x/net/context"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+// ClientMetrics represents a collection of metrics to be registered on a
+// Prometheus metrics registry for a gRPC client.
+type ClientMetrics struct {
+	clientStartedCounter          *prom.CounterVec
+	clientHandledCounter          *prom.CounterVec
+	clientStreamMsgReceived       *prom.CounterVec
+	clientStreamMsgSent           *prom.CounterVec
+	clientHandledHistogramEnabled bool
+	clientHandledHistogramOpts    prom.HistogramOpts
+	clientHandledHistogram        *prom.HistogramVec
+}
+
+// NewClientMetrics returns a ClientMetrics object. Use a new instance of
+// ClientMetrics when not using the default Prometheus metrics registry, for
+// example when wanting to control which metrics are added to a registry as
+// opposed to automatically adding metrics via init functions.
+func NewClientMetrics(counterOpts ...CounterOption) *ClientMetrics {
+	opts := counterOptions(counterOpts)
+	return &ClientMetrics{
+		clientStartedCounter: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_client_started_total",
+				Help: "Total number of RPCs started on the client.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+
+		clientHandledCounter: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_client_handled_total",
+				Help: "Total number of RPCs completed by the client, regardless of success or failure.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}),
+
+		clientStreamMsgReceived: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_client_msg_received_total",
+				Help: "Total number of RPC stream messages received by the client.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+
+		clientStreamMsgSent: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_client_msg_sent_total",
+				Help: "Total number of gRPC stream messages sent by the client.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+
+		clientHandledHistogramEnabled: false,
+		clientHandledHistogramOpts: prom.HistogramOpts{
+			Name:    "grpc_client_handling_seconds",
+			Help:    "Histogram of response latency (seconds) of the gRPC until it is finished by the application.",
+			Buckets: prom.DefBuckets,
+		},
+		clientHandledHistogram: nil,
+	}
+}
+
+// Describe sends the super-set of all possible descriptors of metrics
+// collected by this Collector to the provided channel and returns once
+// the last descriptor has been sent.
+func (m *ClientMetrics) Describe(ch chan<- *prom.Desc) {
+	m.clientStartedCounter.Describe(ch)
+	m.clientHandledCounter.Describe(ch)
+	m.clientStreamMsgReceived.Describe(ch)
+	m.clientStreamMsgSent.Describe(ch)
+	if m.clientHandledHistogramEnabled {
+		m.clientHandledHistogram.Describe(ch)
+	}
+}
+
+// Collect is called by the Prometheus registry when collecting
+// metrics. The implementation sends each collected metric via the
+// provided channel and returns once the last metric has been sent.
+func (m *ClientMetrics) Collect(ch chan<- prom.Metric) {
+	m.clientStartedCounter.Collect(ch)
+	m.clientHandledCounter.Collect(ch)
+	m.clientStreamMsgReceived.Collect(ch)
+	m.clientStreamMsgSent.Collect(ch)
+	if m.clientHandledHistogramEnabled {
+		m.clientHandledHistogram.Collect(ch)
+	}
+}
+
+// EnableClientHandlingTimeHistogram turns on recording of handling time of RPCs.
+// Histogram metrics can be very expensive for Prometheus to retain and query.
+func (m *ClientMetrics) EnableClientHandlingTimeHistogram(opts ...HistogramOption) {
+	for _, o := range opts {
+		o(&m.clientHandledHistogramOpts)
+	}
+	if !m.clientHandledHistogramEnabled {
+		m.clientHandledHistogram = prom.NewHistogramVec(
+			m.clientHandledHistogramOpts,
+			[]string{"grpc_type", "grpc_service", "grpc_method"},
+		)
+	}
+	m.clientHandledHistogramEnabled = true
+}
+
+// UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs.
+func (m *ClientMetrics) UnaryClientInterceptor() func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+	return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+		monitor := newClientReporter(m, Unary, method)
+		monitor.SentMessage()
+		err := invoker(ctx, method, req, reply, cc, opts...)
+		if err != nil {
+			monitor.ReceivedMessage()
+		}
+		st, _ := status.FromError(err)
+		monitor.Handled(st.Code())
+		return err
+	}
+}
+
+// StreamClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs.
+func (m *ClientMetrics) StreamClientInterceptor() func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+	return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
+		monitor := newClientReporter(m, clientStreamType(desc), method)
+		clientStream, err := streamer(ctx, desc, cc, method, opts...)
+		if err != nil {
+			st, _ := status.FromError(err)
+			monitor.Handled(st.Code())
+			return nil, err
+		}
+		return &monitoredClientStream{clientStream, monitor}, nil
+	}
+}
+
+func clientStreamType(desc *grpc.StreamDesc) grpcType {
+	if desc.ClientStreams && !desc.ServerStreams {
+		return ClientStream
+	} else if !desc.ClientStreams && desc.ServerStreams {
+		return ServerStream
+	}
+	return BidiStream
+}
+
+// monitoredClientStream wraps grpc.ClientStream allowing each Sent/Recv of message to increment counters.
+type monitoredClientStream struct {
+	grpc.ClientStream
+	monitor *clientReporter
+}
+
+func (s *monitoredClientStream) SendMsg(m interface{}) error {
+	err := s.ClientStream.SendMsg(m)
+	if err == nil {
+		s.monitor.SentMessage()
+	}
+	return err
+}
+
+func (s *monitoredClientStream) RecvMsg(m interface{}) error {
+	err := s.ClientStream.RecvMsg(m)
+	if err == nil {
+		s.monitor.ReceivedMessage()
+	} else if err == io.EOF {
+		s.monitor.Handled(codes.OK)
+	} else {
+		st, _ := status.FromError(err)
+		s.monitor.Handled(st.Code())
+	}
+	return err
+}

+ 13 - 78
vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_reporter.go

@@ -7,105 +7,40 @@ import (
 	"time"
 
 	"google.golang.org/grpc/codes"
-
-	prom "github.com/prometheus/client_golang/prometheus"
-)
-
-var (
-	clientStartedCounter = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "client",
-			Name:      "started_total",
-			Help:      "Total number of RPCs started on the client.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	clientHandledCounter = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "client",
-			Name:      "handled_total",
-			Help:      "Total number of RPCs completed by the client, regardless of success or failure.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"})
-
-	clientStreamMsgReceived = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "client",
-			Name:      "msg_received_total",
-			Help:      "Total number of RPC stream messages received by the client.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	clientStreamMsgSent = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "client",
-			Name:      "msg_sent_total",
-			Help:      "Total number of gRPC stream messages sent by the client.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	clientHandledHistogramEnabled = false
-	clientHandledHistogramOpts    = prom.HistogramOpts{
-		Namespace: "grpc",
-		Subsystem: "client",
-		Name:      "handling_seconds",
-		Help:      "Histogram of response latency (seconds) of the gRPC until it is finished by the application.",
-		Buckets:   prom.DefBuckets,
-	}
-	clientHandledHistogram *prom.HistogramVec
 )
 
-func init() {
-	prom.MustRegister(clientStartedCounter)
-	prom.MustRegister(clientHandledCounter)
-	prom.MustRegister(clientStreamMsgReceived)
-	prom.MustRegister(clientStreamMsgSent)
-}
-
-// EnableClientHandlingTimeHistogram turns on recording of handling time of RPCs.
-// Histogram metrics can be very expensive for Prometheus to retain and query.
-func EnableClientHandlingTimeHistogram(opts ...HistogramOption) {
-	for _, o := range opts {
-		o(&clientHandledHistogramOpts)
-	}
-	if !clientHandledHistogramEnabled {
-		clientHandledHistogram = prom.NewHistogramVec(
-			clientHandledHistogramOpts,
-			[]string{"grpc_type", "grpc_service", "grpc_method"},
-		)
-		prom.Register(clientHandledHistogram)
-	}
-	clientHandledHistogramEnabled = true
-}
-
 type clientReporter struct {
+	metrics     *ClientMetrics
 	rpcType     grpcType
 	serviceName string
 	methodName  string
 	startTime   time.Time
 }
 
-func newClientReporter(rpcType grpcType, fullMethod string) *clientReporter {
-	r := &clientReporter{rpcType: rpcType}
-	if clientHandledHistogramEnabled {
+func newClientReporter(m *ClientMetrics, rpcType grpcType, fullMethod string) *clientReporter {
+	r := &clientReporter{
+		metrics: m,
+		rpcType: rpcType,
+	}
+	if r.metrics.clientHandledHistogramEnabled {
 		r.startTime = time.Now()
 	}
 	r.serviceName, r.methodName = splitMethodName(fullMethod)
-	clientStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.clientStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 	return r
 }
 
 func (r *clientReporter) ReceivedMessage() {
-	clientStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.clientStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 }
 
 func (r *clientReporter) SentMessage() {
-	clientStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.clientStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 }
 
 func (r *clientReporter) Handled(code codes.Code) {
-	clientHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc()
-	if clientHandledHistogramEnabled {
-		clientHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds())
+	r.metrics.clientHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc()
+	if r.metrics.clientHandledHistogramEnabled {
+		r.metrics.clientHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds())
 	}
 }

+ 41 - 0
vendor/github.com/grpc-ecosystem/go-grpc-prometheus/metric_options.go

@@ -0,0 +1,41 @@
+package grpc_prometheus
+
+import (
+	prom "github.com/prometheus/client_golang/prometheus"
+)
+
+// A CounterOption lets you add options to Counter metrics using With* funcs.
+type CounterOption func(*prom.CounterOpts)
+
+type counterOptions []CounterOption
+
+func (co counterOptions) apply(o prom.CounterOpts) prom.CounterOpts {
+	for _, f := range co {
+		f(&o)
+	}
+	return o
+}
+
+// WithConstLabels allows you to add ConstLabels to Counter metrics.
+func WithConstLabels(labels prom.Labels) CounterOption {
+	return func(o *prom.CounterOpts) {
+		o.ConstLabels = labels
+	}
+}
+
+// A HistogramOption lets you add options to Histogram metrics using With*
+// funcs.
+type HistogramOption func(*prom.HistogramOpts)
+
+// WithHistogramBuckets allows you to specify custom bucket ranges for histograms if EnableHandlingTimeHistogram is on.
+func WithHistogramBuckets(buckets []float64) HistogramOption {
+	return func(o *prom.HistogramOpts) { o.Buckets = buckets }
+}
+
+// WithHistogramConstLabels allows you to add custom ConstLabels to
+// histograms metrics.
+func WithHistogramConstLabels(labels prom.Labels) HistogramOption {
+	return func(o *prom.HistogramOpts) {
+		o.ConstLabels = labels
+	}
+}

+ 29 - 55
vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server.go

@@ -6,69 +6,43 @@
 package grpc_prometheus
 
 import (
-	"golang.org/x/net/context"
+	prom "github.com/prometheus/client_golang/prometheus"
 	"google.golang.org/grpc"
 )
 
-// PreregisterServices takes a gRPC server and pre-initializes all counters to 0.
-// This allows for easier monitoring in Prometheus (no missing metrics), and should be called *after* all services have
-// been registered with the server.
-func Register(server *grpc.Server) {
-	serviceInfo := server.GetServiceInfo()
-	for serviceName, info := range serviceInfo {
-		for _, mInfo := range info.Methods {
-			preRegisterMethod(serviceName, &mInfo)
-		}
-	}
-}
-
-// UnaryServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Unary RPCs.
-func UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
-	monitor := newServerReporter(Unary, info.FullMethod)
-	monitor.ReceivedMessage()
-	resp, err := handler(ctx, req)
-	monitor.Handled(grpc.Code(err))
-	if err == nil {
-		monitor.SentMessage()
-	}
-	return resp, err
-}
+var (
+	// DefaultServerMetrics is the default instance of ServerMetrics. It is
+	// intended to be used in conjunction the default Prometheus metrics
+	// registry.
+	DefaultServerMetrics = NewServerMetrics()
 
-// StreamServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Streaming RPCs.
-func StreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
-	monitor := newServerReporter(streamRpcType(info), info.FullMethod)
-	err := handler(srv, &monitoredServerStream{ss, monitor})
-	monitor.Handled(grpc.Code(err))
-	return err
-}
+	// UnaryServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Unary RPCs.
+	UnaryServerInterceptor = DefaultServerMetrics.UnaryServerInterceptor()
 
-func streamRpcType(info *grpc.StreamServerInfo) grpcType {
-	if info.IsClientStream && !info.IsServerStream {
-		return ClientStream
-	} else if !info.IsClientStream && info.IsServerStream {
-		return ServerStream
-	}
-	return BidiStream
-}
+	// StreamServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Streaming RPCs.
+	StreamServerInterceptor = DefaultServerMetrics.StreamServerInterceptor()
+)
 
-// monitoredStream wraps grpc.ServerStream allowing each Sent/Recv of message to increment counters.
-type monitoredServerStream struct {
-	grpc.ServerStream
-	monitor *serverReporter
+func init() {
+	prom.MustRegister(DefaultServerMetrics.serverStartedCounter)
+	prom.MustRegister(DefaultServerMetrics.serverHandledCounter)
+	prom.MustRegister(DefaultServerMetrics.serverStreamMsgReceived)
+	prom.MustRegister(DefaultServerMetrics.serverStreamMsgSent)
 }
 
-func (s *monitoredServerStream) SendMsg(m interface{}) error {
-	err := s.ServerStream.SendMsg(m)
-	if err == nil {
-		s.monitor.SentMessage()
-	}
-	return err
+// Register takes a gRPC server and pre-initializes all counters to 0. This
+// allows for easier monitoring in Prometheus (no missing metrics), and should
+// be called *after* all services have been registered with the server. This
+// function acts on the DefaultServerMetrics variable.
+func Register(server *grpc.Server) {
+	DefaultServerMetrics.InitializeMetrics(server)
 }
 
-func (s *monitoredServerStream) RecvMsg(m interface{}) error {
-	err := s.ServerStream.RecvMsg(m)
-	if err == nil {
-		s.monitor.ReceivedMessage()
-	}
-	return err
+// EnableHandlingTimeHistogram turns on recording of handling time
+// of RPCs. Histogram metrics can be very expensive for Prometheus
+// to retain and query. This function acts on the DefaultServerMetrics
+// variable and the default Prometheus metrics registry.
+func EnableHandlingTimeHistogram(opts ...HistogramOption) {
+	DefaultServerMetrics.EnableHandlingTimeHistogram(opts...)
+	prom.Register(DefaultServerMetrics.serverHandledHistogram)
 }

+ 185 - 0
vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_metrics.go

@@ -0,0 +1,185 @@
+package grpc_prometheus
+
+import (
+	prom "github.com/prometheus/client_golang/prometheus"
+	"golang.org/x/net/context"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/status"
+)
+
+// ServerMetrics represents a collection of metrics to be registered on a
+// Prometheus metrics registry for a gRPC server.
+type ServerMetrics struct {
+	serverStartedCounter          *prom.CounterVec
+	serverHandledCounter          *prom.CounterVec
+	serverStreamMsgReceived       *prom.CounterVec
+	serverStreamMsgSent           *prom.CounterVec
+	serverHandledHistogramEnabled bool
+	serverHandledHistogramOpts    prom.HistogramOpts
+	serverHandledHistogram        *prom.HistogramVec
+}
+
+// NewServerMetrics returns a ServerMetrics object. Use a new instance of
+// ServerMetrics when not using the default Prometheus metrics registry, for
+// example when wanting to control which metrics are added to a registry as
+// opposed to automatically adding metrics via init functions.
+func NewServerMetrics(counterOpts ...CounterOption) *ServerMetrics {
+	opts := counterOptions(counterOpts)
+	return &ServerMetrics{
+		serverStartedCounter: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_server_started_total",
+				Help: "Total number of RPCs started on the server.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+		serverHandledCounter: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_server_handled_total",
+				Help: "Total number of RPCs completed on the server, regardless of success or failure.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}),
+		serverStreamMsgReceived: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_server_msg_received_total",
+				Help: "Total number of RPC stream messages received on the server.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+		serverStreamMsgSent: prom.NewCounterVec(
+			opts.apply(prom.CounterOpts{
+				Name: "grpc_server_msg_sent_total",
+				Help: "Total number of gRPC stream messages sent by the server.",
+			}), []string{"grpc_type", "grpc_service", "grpc_method"}),
+		serverHandledHistogramEnabled: false,
+		serverHandledHistogramOpts: prom.HistogramOpts{
+			Name:    "grpc_server_handling_seconds",
+			Help:    "Histogram of response latency (seconds) of gRPC that had been application-level handled by the server.",
+			Buckets: prom.DefBuckets,
+		},
+		serverHandledHistogram: nil,
+	}
+}
+
+// EnableHandlingTimeHistogram enables histograms being registered when
+// registering the ServerMetrics on a Prometheus registry. Histograms can be
+// expensive on Prometheus servers. It takes options to configure histogram
+// options such as the defined buckets.
+func (m *ServerMetrics) EnableHandlingTimeHistogram(opts ...HistogramOption) {
+	for _, o := range opts {
+		o(&m.serverHandledHistogramOpts)
+	}
+	if !m.serverHandledHistogramEnabled {
+		m.serverHandledHistogram = prom.NewHistogramVec(
+			m.serverHandledHistogramOpts,
+			[]string{"grpc_type", "grpc_service", "grpc_method"},
+		)
+	}
+	m.serverHandledHistogramEnabled = true
+}
+
+// Describe sends the super-set of all possible descriptors of metrics
+// collected by this Collector to the provided channel and returns once
+// the last descriptor has been sent.
+func (m *ServerMetrics) Describe(ch chan<- *prom.Desc) {
+	m.serverStartedCounter.Describe(ch)
+	m.serverHandledCounter.Describe(ch)
+	m.serverStreamMsgReceived.Describe(ch)
+	m.serverStreamMsgSent.Describe(ch)
+	if m.serverHandledHistogramEnabled {
+		m.serverHandledHistogram.Describe(ch)
+	}
+}
+
+// Collect is called by the Prometheus registry when collecting
+// metrics. The implementation sends each collected metric via the
+// provided channel and returns once the last metric has been sent.
+func (m *ServerMetrics) Collect(ch chan<- prom.Metric) {
+	m.serverStartedCounter.Collect(ch)
+	m.serverHandledCounter.Collect(ch)
+	m.serverStreamMsgReceived.Collect(ch)
+	m.serverStreamMsgSent.Collect(ch)
+	if m.serverHandledHistogramEnabled {
+		m.serverHandledHistogram.Collect(ch)
+	}
+}
+
+// UnaryServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Unary RPCs.
+func (m *ServerMetrics) UnaryServerInterceptor() func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
+		monitor := newServerReporter(m, Unary, info.FullMethod)
+		monitor.ReceivedMessage()
+		resp, err := handler(ctx, req)
+		st, _ := status.FromError(err)
+		monitor.Handled(st.Code())
+		if err == nil {
+			monitor.SentMessage()
+		}
+		return resp, err
+	}
+}
+
+// StreamServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Streaming RPCs.
+func (m *ServerMetrics) StreamServerInterceptor() func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+	return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
+		monitor := newServerReporter(m, streamRPCType(info), info.FullMethod)
+		err := handler(srv, &monitoredServerStream{ss, monitor})
+		st, _ := status.FromError(err)
+		monitor.Handled(st.Code())
+		return err
+	}
+}
+
+// InitializeMetrics initializes all metrics, with their appropriate null
+// value, for all gRPC methods registered on a gRPC server. This is useful, to
+// ensure that all metrics exist when collecting and querying.
+func (m *ServerMetrics) InitializeMetrics(server *grpc.Server) {
+	serviceInfo := server.GetServiceInfo()
+	for serviceName, info := range serviceInfo {
+		for _, mInfo := range info.Methods {
+			preRegisterMethod(m, serviceName, &mInfo)
+		}
+	}
+}
+
+func streamRPCType(info *grpc.StreamServerInfo) grpcType {
+	if info.IsClientStream && !info.IsServerStream {
+		return ClientStream
+	} else if !info.IsClientStream && info.IsServerStream {
+		return ServerStream
+	}
+	return BidiStream
+}
+
+// monitoredStream wraps grpc.ServerStream allowing each Sent/Recv of message to increment counters.
+type monitoredServerStream struct {
+	grpc.ServerStream
+	monitor *serverReporter
+}
+
+func (s *monitoredServerStream) SendMsg(m interface{}) error {
+	err := s.ServerStream.SendMsg(m)
+	if err == nil {
+		s.monitor.SentMessage()
+	}
+	return err
+}
+
+func (s *monitoredServerStream) RecvMsg(m interface{}) error {
+	err := s.ServerStream.RecvMsg(m)
+	if err == nil {
+		s.monitor.ReceivedMessage()
+	}
+	return err
+}
+
+// preRegisterMethod is invoked on Register of a Server, allowing all gRPC services labels to be pre-populated.
+func preRegisterMethod(metrics *ServerMetrics, serviceName string, mInfo *grpc.MethodInfo) {
+	methodName := mInfo.Name
+	methodType := string(typeFromMethodInfo(mInfo))
+	// These are just references (no increments), as just referencing will create the labels but not set values.
+	metrics.serverStartedCounter.GetMetricWithLabelValues(methodType, serviceName, methodName)
+	metrics.serverStreamMsgReceived.GetMetricWithLabelValues(methodType, serviceName, methodName)
+	metrics.serverStreamMsgSent.GetMetricWithLabelValues(methodType, serviceName, methodName)
+	if metrics.serverHandledHistogramEnabled {
+		metrics.serverHandledHistogram.GetMetricWithLabelValues(methodType, serviceName, methodName)
+	}
+	for _, code := range allCodes {
+		metrics.serverHandledCounter.GetMetricWithLabelValues(methodType, serviceName, methodName, code.String())
+	}
+}

+ 13 - 124
vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_reporter.go

@@ -7,151 +7,40 @@ import (
 	"time"
 
 	"google.golang.org/grpc/codes"
-
-	prom "github.com/prometheus/client_golang/prometheus"
-	"google.golang.org/grpc"
-)
-
-type grpcType string
-
-const (
-	Unary        grpcType = "unary"
-	ClientStream grpcType = "client_stream"
-	ServerStream grpcType = "server_stream"
-	BidiStream   grpcType = "bidi_stream"
 )
 
-var (
-	serverStartedCounter = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "server",
-			Name:      "started_total",
-			Help:      "Total number of RPCs started on the server.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	serverHandledCounter = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "server",
-			Name:      "handled_total",
-			Help:      "Total number of RPCs completed on the server, regardless of success or failure.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"})
-
-	serverStreamMsgReceived = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "server",
-			Name:      "msg_received_total",
-			Help:      "Total number of RPC stream messages received on the server.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	serverStreamMsgSent = prom.NewCounterVec(
-		prom.CounterOpts{
-			Namespace: "grpc",
-			Subsystem: "server",
-			Name:      "msg_sent_total",
-			Help:      "Total number of gRPC stream messages sent by the server.",
-		}, []string{"grpc_type", "grpc_service", "grpc_method"})
-
-	serverHandledHistogramEnabled = false
-	serverHandledHistogramOpts    = prom.HistogramOpts{
-		Namespace: "grpc",
-		Subsystem: "server",
-		Name:      "handling_seconds",
-		Help:      "Histogram of response latency (seconds) of gRPC that had been application-level handled by the server.",
-		Buckets:   prom.DefBuckets,
-	}
-	serverHandledHistogram *prom.HistogramVec
-)
-
-func init() {
-	prom.MustRegister(serverStartedCounter)
-	prom.MustRegister(serverHandledCounter)
-	prom.MustRegister(serverStreamMsgReceived)
-	prom.MustRegister(serverStreamMsgSent)
-}
-
-type HistogramOption func(*prom.HistogramOpts)
-
-// WithHistogramBuckets allows you to specify custom bucket ranges for histograms if EnableHandlingTimeHistogram is on.
-func WithHistogramBuckets(buckets []float64) HistogramOption {
-	return func(o *prom.HistogramOpts) { o.Buckets = buckets }
-}
-
-// EnableHandlingTimeHistogram turns on recording of handling time of RPCs for server-side interceptors.
-// Histogram metrics can be very expensive for Prometheus to retain and query.
-func EnableHandlingTimeHistogram(opts ...HistogramOption) {
-	for _, o := range opts {
-		o(&serverHandledHistogramOpts)
-	}
-	if !serverHandledHistogramEnabled {
-		serverHandledHistogram = prom.NewHistogramVec(
-			serverHandledHistogramOpts,
-			[]string{"grpc_type", "grpc_service", "grpc_method"},
-		)
-		prom.Register(serverHandledHistogram)
-	}
-	serverHandledHistogramEnabled = true
-}
-
 type serverReporter struct {
+	metrics     *ServerMetrics
 	rpcType     grpcType
 	serviceName string
 	methodName  string
 	startTime   time.Time
 }
 
-func newServerReporter(rpcType grpcType, fullMethod string) *serverReporter {
-	r := &serverReporter{rpcType: rpcType}
-	if serverHandledHistogramEnabled {
+func newServerReporter(m *ServerMetrics, rpcType grpcType, fullMethod string) *serverReporter {
+	r := &serverReporter{
+		metrics: m,
+		rpcType: rpcType,
+	}
+	if r.metrics.serverHandledHistogramEnabled {
 		r.startTime = time.Now()
 	}
 	r.serviceName, r.methodName = splitMethodName(fullMethod)
-	serverStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.serverStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 	return r
 }
 
 func (r *serverReporter) ReceivedMessage() {
-	serverStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.serverStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 }
 
 func (r *serverReporter) SentMessage() {
-	serverStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
+	r.metrics.serverStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc()
 }
 
 func (r *serverReporter) Handled(code codes.Code) {
-	serverHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc()
-	if serverHandledHistogramEnabled {
-		serverHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds())
-	}
-}
-
-// preRegisterMethod is invoked on Register of a Server, allowing all gRPC services labels to be pre-populated.
-func preRegisterMethod(serviceName string, mInfo *grpc.MethodInfo) {
-	methodName := mInfo.Name
-	methodType := string(typeFromMethodInfo(mInfo))
-	// These are just references (no increments), as just referencing will create the labels but not set values.
-	serverStartedCounter.GetMetricWithLabelValues(methodType, serviceName, methodName)
-	serverStreamMsgReceived.GetMetricWithLabelValues(methodType, serviceName, methodName)
-	serverStreamMsgSent.GetMetricWithLabelValues(methodType, serviceName, methodName)
-	if serverHandledHistogramEnabled {
-		serverHandledHistogram.GetMetricWithLabelValues(methodType, serviceName, methodName)
-	}
-	for _, code := range allCodes {
-		serverHandledCounter.GetMetricWithLabelValues(methodType, serviceName, methodName, code.String())
-	}
-}
-
-func typeFromMethodInfo(mInfo *grpc.MethodInfo) grpcType {
-	if mInfo.IsClientStream == false && mInfo.IsServerStream == false {
-		return Unary
-	}
-	if mInfo.IsClientStream == true && mInfo.IsServerStream == false {
-		return ClientStream
-	}
-	if mInfo.IsClientStream == false && mInfo.IsServerStream == true {
-		return ServerStream
+	r.metrics.serverHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc()
+	if r.metrics.serverHandledHistogramEnabled {
+		r.metrics.serverHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds())
 	}
-	return BidiStream
 }

+ 23 - 0
vendor/github.com/grpc-ecosystem/go-grpc-prometheus/util.go

@@ -6,9 +6,19 @@ package grpc_prometheus
 import (
 	"strings"
 
+	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 )
 
+type grpcType string
+
+const (
+	Unary        grpcType = "unary"
+	ClientStream grpcType = "client_stream"
+	ServerStream grpcType = "server_stream"
+	BidiStream   grpcType = "bidi_stream"
+)
+
 var (
 	allCodes = []codes.Code{
 		codes.OK, codes.Canceled, codes.Unknown, codes.InvalidArgument, codes.DeadlineExceeded, codes.NotFound,
@@ -25,3 +35,16 @@ func splitMethodName(fullMethodName string) (string, string) {
 	}
 	return "unknown", "unknown"
 }
+
+func typeFromMethodInfo(mInfo *grpc.MethodInfo) grpcType {
+	if !mInfo.IsClientStream && !mInfo.IsServerStream {
+		return Unary
+	}
+	if mInfo.IsClientStream && !mInfo.IsServerStream {
+		return ClientStream
+	}
+	if !mInfo.IsClientStream && mInfo.IsServerStream {
+		return ServerStream
+	}
+	return BidiStream
+}

+ 12 - 0
vendor/github.com/opencontainers/runc/README.md

@@ -87,6 +87,18 @@ You can run a specific test case by setting the `TESTFLAGS` variable.
 # make test TESTFLAGS="-run=SomeTestFunction"
 ```
 
+You can run a specific integration test by setting the `TESTPATH` variable.
+
+```bash
+# make test TESTPATH="/checkpoint.bats"
+```
+
+You can run a test in your proxy environment by setting `DOCKER_BUILD_PROXY` and `DOCKER_RUN_PROXY` variables.
+
+```bash
+# make test DOCKER_BUILD_PROXY="--build-arg HTTP_PROXY=http://yourproxy/" DOCKER_RUN_PROXY="-e HTTP_PROXY=http://yourproxy/"
+```
+
 ### Dependencies Management
 
 `runc` uses [vndr](https://github.com/LK4D4/vndr) for dependencies management.

+ 13 - 12
vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go

@@ -13,7 +13,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/docker/go-units"
+	units "github.com/docker/go-units"
 )
 
 const (
@@ -103,7 +103,7 @@ func FindCgroupMountpointDir() (string, error) {
 		}
 
 		if postSeparatorFields[0] == "cgroup" {
-			// Check that the mount is properly formated.
+			// Check that the mount is properly formatted.
 			if numPostFields < 3 {
 				return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text)
 			}
@@ -151,19 +151,20 @@ func getCgroupMountsHelper(ss map[string]bool, mi io.Reader, all bool) ([]Mount,
 			Root:       fields[3],
 		}
 		for _, opt := range strings.Split(fields[len(fields)-1], ",") {
-			if !ss[opt] {
+			seen, known := ss[opt]
+			if !known || (!all && seen) {
 				continue
 			}
+			ss[opt] = true
 			if strings.HasPrefix(opt, cgroupNamePrefix) {
-				m.Subsystems = append(m.Subsystems, opt[len(cgroupNamePrefix):])
-			} else {
-				m.Subsystems = append(m.Subsystems, opt)
-			}
-			if !all {
-				numFound++
+				opt = opt[len(cgroupNamePrefix):]
 			}
+			m.Subsystems = append(m.Subsystems, opt)
+			numFound++
+		}
+		if len(m.Subsystems) > 0 || all {
+			res = append(res, m)
 		}
-		res = append(res, m)
 	}
 	if err := scanner.Err(); err != nil {
 		return nil, err
@@ -187,7 +188,7 @@ func GetCgroupMounts(all bool) ([]Mount, error) {
 
 	allMap := make(map[string]bool)
 	for s := range allSubsystems {
-		allMap[s] = true
+		allMap[s] = false
 	}
 	return getCgroupMountsHelper(allMap, f, all)
 }
@@ -262,7 +263,7 @@ func getCgroupPathHelper(subsystem, cgroup string) (string, error) {
 	}
 
 	// This is needed for nested containers, because in /proc/self/cgroup we
-	// see pathes from host, which don't exist in container.
+	// see paths from host, which don't exist in container.
 	relCgroup, err := filepath.Rel(root, cgroup)
 	if err != nil {
 		return "", err

+ 3 - 3
vendor/github.com/opencontainers/runc/libcontainer/nsenter/README.md

@@ -10,8 +10,8 @@ The `nsenter` package will `import "C"` and it uses [cgo](https://golang.org/cmd
 package. In cgo, if the import of "C" is immediately preceded by a comment, that comment, 
 called the preamble, is used as a header when compiling the C parts of the package.
 So every time we  import package `nsenter`, the C code function `nsexec()` would be 
-called. And package `nsenter` is now only imported in `main_unix.go`, so every time
-before we call `cmd.Start` on linux, that C code would run.
+called. And package `nsenter` is only imported in `init.go`, so every time the runc
+`init` command is invoked, that C code is run.
 
 Because `nsexec()` must be run before the Go runtime in order to use the
 Linux kernel namespace, you must `import` this library into a package if
@@ -37,7 +37,7 @@ the parent `nsexec()` will exit and the child `nsexec()` process will
 return to allow the Go runtime take over.
 
 NOTE: We do both `setns(2)` and `clone(2)` even if we don't have any
-CLONE_NEW* clone flags because we must fork a new process in order to
+`CLONE_NEW*` clone flags because we must fork a new process in order to
 enter the PID namespace.
 
 

+ 1 - 1
vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c

@@ -211,7 +211,7 @@ static int try_mapping_tool(const char *app, int pid, char *map, size_t map_len)
 
 	/*
 	 * If @app is NULL, execve will segfault. Just check it here and bail (if
-	 * we're in this path, the caller is already getting desparate and there
+	 * we're in this path, the caller is already getting desperate and there
 	 * isn't a backup to this failing). This usually would be a configuration
 	 * or programming issue.
 	 */

+ 2 - 0
vendor/github.com/opencontainers/runtime-spec/specs-go/config.go

@@ -503,6 +503,8 @@ type WindowsNetwork struct {
 	DNSSearchList []string `json:"DNSSearchList,omitempty"`
 	// Name (ID) of the container that we will share with the network stack.
 	NetworkSharedContainerName string `json:"networkSharedContainerName,omitempty"`
+	// name (ID) of the network namespace that will be used for the container.
+	NetworkNamespace string `json:"networkNamespace,omitempty"`
 }
 
 // WindowsHyperV contains information for configuring a container to run with Hyper-V isolation.

+ 1 - 4
vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go

@@ -87,9 +87,6 @@ func FormatMountLabel(src, mountLabel string) string {
 // SetProcessLabel takes a process label and tells the kernel to assign the
 // label to the next program executed by the current process.
 func SetProcessLabel(processLabel string) error {
-	if processLabel == "" {
-		return nil
-	}
 	return selinux.SetExecLabel(processLabel)
 }
 
@@ -133,7 +130,7 @@ func Relabel(path string, fileLabel string, shared bool) error {
 		return nil
 	}
 
-	exclude_paths := map[string]bool{"/": true, "/usr": true, "/etc": true}
+	exclude_paths := map[string]bool{"/": true, "/usr": true, "/etc": true, "/tmp": true, "/home": true, "/run": true, "/var": true, "/root": true}
 	if exclude_paths[path] {
 		return fmt.Errorf("SELinux relabeling of %s is not allowed", path)
 	}

+ 201 - 73
vendor/github.com/opencontainers/selinux/go-selinux/selinux.go → vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go

@@ -1,13 +1,16 @@
-// +build linux
+// +build selinux,linux
 
 package selinux
 
 import (
 	"bufio"
+	"bytes"
 	"crypto/rand"
 	"encoding/binary"
+	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"regexp"
@@ -23,14 +26,16 @@ const (
 	// Permissive constant to indicate SELinux is in permissive mode
 	Permissive = 0
 	// Disabled constant to indicate SELinux is disabled
-	Disabled         = -1
+	Disabled = -1
+
 	selinuxDir       = "/etc/selinux/"
 	selinuxConfig    = selinuxDir + "config"
+	selinuxfsMount   = "/sys/fs/selinux"
 	selinuxTypeTag   = "SELINUXTYPE"
 	selinuxTag       = "SELINUX"
-	selinuxPath      = "/sys/fs/selinux"
 	xattrNameSelinux = "security.selinux"
 	stRdOnly         = 0x01
+	selinuxfsMagic   = 0xf97cff8c
 )
 
 type selinuxState struct {
@@ -43,7 +48,13 @@ type selinuxState struct {
 }
 
 var (
+	// ErrMCSAlreadyExists is returned when trying to allocate a duplicate MCS.
+	ErrMCSAlreadyExists = errors.New("MCS label already exists")
+	// ErrEmptyPath is returned when an empty path has been specified.
+	ErrEmptyPath = errors.New("empty path")
+
 	assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`)
+	roFileLabel string
 	state       = selinuxState{
 		mcsList: make(map[string]bool),
 	}
@@ -91,49 +102,93 @@ func (s *selinuxState) setSELinuxfs(selinuxfs string) string {
 	return s.selinuxfs
 }
 
-func (s *selinuxState) getSELinuxfs() string {
-	s.Lock()
-	selinuxfs := s.selinuxfs
-	selinuxfsSet := s.selinuxfsSet
-	s.Unlock()
-	if selinuxfsSet {
-		return selinuxfs
+func verifySELinuxfsMount(mnt string) bool {
+	var buf syscall.Statfs_t
+	for {
+		err := syscall.Statfs(mnt, &buf)
+		if err == nil {
+			break
+		}
+		if err == syscall.EAGAIN {
+			continue
+		}
+		return false
+	}
+	if uint32(buf.Type) != uint32(selinuxfsMagic) {
+		return false
+	}
+	if (buf.Flags & stRdOnly) != 0 {
+		return false
+	}
+
+	return true
+}
+
+func findSELinuxfs() string {
+	// fast path: check the default mount first
+	if verifySELinuxfsMount(selinuxfsMount) {
+		return selinuxfsMount
+	}
+
+	// check if selinuxfs is available before going the slow path
+	fs, err := ioutil.ReadFile("/proc/filesystems")
+	if err != nil {
+		return ""
+	}
+	if !bytes.Contains(fs, []byte("\tselinuxfs\n")) {
+		return ""
 	}
 
-	selinuxfs = ""
+	// slow path: try to find among the mounts
 	f, err := os.Open("/proc/self/mountinfo")
 	if err != nil {
-		return selinuxfs
+		return ""
 	}
 	defer f.Close()
 
 	scanner := bufio.NewScanner(f)
-	for scanner.Scan() {
-		txt := scanner.Text()
-		// Safe as mountinfo encodes mountpoints with spaces as \040.
-		sepIdx := strings.Index(txt, " - ")
-		if sepIdx == -1 {
-			continue
+	for {
+		mnt := findSELinuxfsMount(scanner)
+		if mnt == "" { // error or not found
+			return ""
+		}
+		if verifySELinuxfsMount(mnt) {
+			return mnt
 		}
-		if !strings.Contains(txt[sepIdx:], "selinuxfs") {
+	}
+}
+
+// findSELinuxfsMount returns a next selinuxfs mount point found,
+// if there is one, or an empty string in case of EOF or error.
+func findSELinuxfsMount(s *bufio.Scanner) string {
+	for s.Scan() {
+		txt := s.Text()
+		// The first field after - is fs type.
+		// Safe as spaces in mountpoints are encoded as \040
+		if !strings.Contains(txt, " - selinuxfs ") {
 			continue
 		}
-		fields := strings.Split(txt, " ")
-		if len(fields) < 5 {
+		const mPos = 5 // mount point is 5th field
+		fields := strings.SplitN(txt, " ", mPos+1)
+		if len(fields) < mPos+1 {
 			continue
 		}
-		selinuxfs = fields[4]
-		break
+		return fields[mPos-1]
 	}
 
-	if selinuxfs != "" {
-		var buf syscall.Statfs_t
-		syscall.Statfs(selinuxfs, &buf)
-		if (buf.Flags & stRdOnly) == 1 {
-			selinuxfs = ""
-		}
+	return ""
+}
+
+func (s *selinuxState) getSELinuxfs() string {
+	s.Lock()
+	selinuxfs := s.selinuxfs
+	selinuxfsSet := s.selinuxfsSet
+	s.Unlock()
+	if selinuxfsSet {
+		return selinuxfs
 	}
-	return s.setSELinuxfs(selinuxfs)
+
+	return s.setSELinuxfs(findSELinuxfs())
 }
 
 // getSelinuxMountPoint returns the path to the mountpoint of an selinuxfs
@@ -150,7 +205,7 @@ func GetEnabled() bool {
 	return state.getEnabled()
 }
 
-func readConfig(target string) (value string) {
+func readConfig(target string) string {
 	var (
 		val, key string
 		bufin    *bufio.Reader
@@ -192,30 +247,42 @@ func readConfig(target string) (value string) {
 }
 
 func getSELinuxPolicyRoot() string {
-	return selinuxDir + readConfig(selinuxTypeTag)
+	return filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
 }
 
-func readCon(name string) (string, error) {
-	var val string
+func readCon(fpath string) (string, error) {
+	if fpath == "" {
+		return "", ErrEmptyPath
+	}
 
-	in, err := os.Open(name)
+	in, err := os.Open(fpath)
 	if err != nil {
 		return "", err
 	}
 	defer in.Close()
 
-	_, err = fmt.Fscanf(in, "%s", &val)
-	return val, err
+	var retval string
+	if _, err := fmt.Fscanf(in, "%s", &retval); err != nil {
+		return "", err
+	}
+	return strings.Trim(retval, "\x00"), nil
 }
 
 // SetFileLabel sets the SELinux label for this path or returns an error.
-func SetFileLabel(path string, label string) error {
-	return lsetxattr(path, xattrNameSelinux, []byte(label), 0)
+func SetFileLabel(fpath string, label string) error {
+	if fpath == "" {
+		return ErrEmptyPath
+	}
+	return lsetxattr(fpath, xattrNameSelinux, []byte(label), 0)
 }
 
 // FileLabel returns the SELinux label for this path or returns an error.
-func FileLabel(path string) (string, error) {
-	label, err := lgetxattr(path, xattrNameSelinux)
+func FileLabel(fpath string) (string, error) {
+	if fpath == "" {
+		return "", ErrEmptyPath
+	}
+
+	label, err := lgetxattr(fpath, xattrNameSelinux)
 	if err != nil {
 		return "", err
 	}
@@ -260,8 +327,12 @@ func ExecLabel() (string, error) {
 	return readCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid()))
 }
 
-func writeCon(name string, val string) error {
-	out, err := os.OpenFile(name, os.O_WRONLY, 0)
+func writeCon(fpath string, val string) error {
+	if fpath == "" {
+		return ErrEmptyPath
+	}
+
+	out, err := os.OpenFile(fpath, os.O_WRONLY, 0)
 	if err != nil {
 		return err
 	}
@@ -275,6 +346,37 @@ func writeCon(name string, val string) error {
 	return err
 }
 
+/*
+CanonicalizeContext takes a context string and writes it to the kernel
+the function then returns the context that the kernel will use.  This function
+can be used to see if two contexts are equivalent
+*/
+func CanonicalizeContext(val string) (string, error) {
+	return readWriteCon(filepath.Join(getSelinuxMountPoint(), "context"), val)
+}
+
+func readWriteCon(fpath string, val string) (string, error) {
+	if fpath == "" {
+		return "", ErrEmptyPath
+	}
+	f, err := os.OpenFile(fpath, os.O_RDWR, 0)
+	if err != nil {
+		return "", err
+	}
+	defer f.Close()
+
+	_, err = f.Write([]byte(val))
+	if err != nil {
+		return "", err
+	}
+
+	var retval string
+	if _, err := fmt.Fscanf(f, "%s", &retval); err != nil {
+		return "", err
+	}
+	return strings.Trim(retval, "\x00"), nil
+}
+
 /*
 SetExecLabel sets the SELinux label that the kernel will use for any programs
 that are executed by the current process thread, or an error.
@@ -285,7 +387,10 @@ func SetExecLabel(label string) error {
 
 // Get returns the Context as a string
 func (c Context) Get() string {
-	return fmt.Sprintf("%s:%s:%s:%s", c["user"], c["role"], c["type"], c["level"])
+	if c["level"] != "" {
+		return fmt.Sprintf("%s:%s:%s:%s", c["user"], c["role"], c["type"], c["level"])
+	}
+	return fmt.Sprintf("%s:%s:%s", c["user"], c["role"], c["type"])
 }
 
 // NewContext creates a new Context struct from the specified label
@@ -297,7 +402,9 @@ func NewContext(label string) Context {
 		c["user"] = con[0]
 		c["role"] = con[1]
 		c["type"] = con[2]
-		c["level"] = con[3]
+		if len(con) > 3 {
+			c["level"] = con[3]
+		}
 	}
 	return c
 }
@@ -306,12 +413,14 @@ func NewContext(label string) Context {
 func ReserveLabel(label string) {
 	if len(label) != 0 {
 		con := strings.SplitN(label, ":", 4)
-		mcsAdd(con[3])
+		if len(con) > 3 {
+			mcsAdd(con[3])
+		}
 	}
 }
 
 func selinuxEnforcePath() string {
-	return fmt.Sprintf("%s/enforce", selinuxPath)
+	return fmt.Sprintf("%s/enforce", getSelinuxMountPoint())
 }
 
 // EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
@@ -354,16 +463,22 @@ func DefaultEnforceMode() int {
 }
 
 func mcsAdd(mcs string) error {
+	if mcs == "" {
+		return nil
+	}
 	state.Lock()
 	defer state.Unlock()
 	if state.mcsList[mcs] {
-		return fmt.Errorf("MCS Label already exists")
+		return ErrMCSAlreadyExists
 	}
 	state.mcsList[mcs] = true
 	return nil
 }
 
 func mcsDelete(mcs string) {
+	if mcs == "" {
+		return
+	}
 	state.Lock()
 	defer state.Unlock()
 	state.mcsList[mcs] = false
@@ -424,14 +539,14 @@ Allowing it to be used by another process.
 func ReleaseLabel(label string) {
 	if len(label) != 0 {
 		con := strings.SplitN(label, ":", 4)
-		mcsDelete(con[3])
+		if len(con) > 3 {
+			mcsDelete(con[3])
+		}
 	}
 }
 
-var roFileLabel string
-
 // ROFileLabel returns the specified SELinux readonly file label
-func ROFileLabel() (fileLabel string) {
+func ROFileLabel() string {
 	return roFileLabel
 }
 
@@ -497,23 +612,25 @@ func ContainerLabels() (processLabel string, fileLabel string) {
 		roFileLabel = fileLabel
 	}
 exit:
-	mcs := uniqMcs(1024)
 	scon := NewContext(processLabel)
-	scon["level"] = mcs
-	processLabel = scon.Get()
-	scon = NewContext(fileLabel)
-	scon["level"] = mcs
-	fileLabel = scon.Get()
+	if scon["level"] != "" {
+		mcs := uniqMcs(1024)
+		scon["level"] = mcs
+		processLabel = scon.Get()
+		scon = NewContext(fileLabel)
+		scon["level"] = mcs
+		fileLabel = scon.Get()
+	}
 	return processLabel, fileLabel
 }
 
 // SecurityCheckContext validates that the SELinux label is understood by the kernel
 func SecurityCheckContext(val string) error {
-	return writeCon(fmt.Sprintf("%s.context", selinuxPath), val)
+	return writeCon(fmt.Sprintf("%s/context", getSelinuxMountPoint()), val)
 }
 
 /*
-CopyLevel returns a label with the MLS/MCS level from src label replaces on
+CopyLevel returns a label with the MLS/MCS level from src label replaced on
 the dest label.
 */
 func CopyLevel(src, dest string) (string, error) {
@@ -536,20 +653,26 @@ func CopyLevel(src, dest string) (string, error) {
 
 // Prevent users from relabing system files
 func badPrefix(fpath string) error {
-	var badprefixes = []string{"/usr"}
+	if fpath == "" {
+		return ErrEmptyPath
+	}
 
-	for _, prefix := range badprefixes {
-		if fpath == prefix || strings.HasPrefix(fpath, fmt.Sprintf("%s/", prefix)) {
+	badPrefixes := []string{"/usr"}
+	for _, prefix := range badPrefixes {
+		if strings.HasPrefix(fpath, prefix) {
 			return fmt.Errorf("relabeling content in %s is not allowed", prefix)
 		}
 	}
 	return nil
 }
 
-// Chcon changes the fpath file object to the SELinux label label.
-// If the fpath is a directory and recurse is true Chcon will walk the
-// directory tree setting the label
+// Chcon changes the `fpath` file object to the SELinux label `label`.
+// If `fpath` is a directory and `recurse`` is true, Chcon will walk the
+// directory tree setting the label.
 func Chcon(fpath string, label string, recurse bool) error {
+	if fpath == "" {
+		return ErrEmptyPath
+	}
 	if label == "" {
 		return nil
 	}
@@ -568,7 +691,7 @@ func Chcon(fpath string, label string, recurse bool) error {
 }
 
 // DupSecOpt takes an SELinux process label and returns security options that
-// can will set the SELinux Type and Level for future container processes
+// can be used to set the SELinux Type and Level for future container processes.
 func DupSecOpt(src string) []string {
 	if src == "" {
 		return nil
@@ -576,18 +699,23 @@ func DupSecOpt(src string) []string {
 	con := NewContext(src)
 	if con["user"] == "" ||
 		con["role"] == "" ||
-		con["type"] == "" ||
-		con["level"] == "" {
+		con["type"] == "" {
 		return nil
 	}
-	return []string{"user:" + con["user"],
+	dup := []string{"user:" + con["user"],
 		"role:" + con["role"],
 		"type:" + con["type"],
-		"level:" + con["level"]}
+	}
+
+	if con["level"] != "" {
+		dup = append(dup, "level:"+con["level"])
+	}
+
+	return dup
 }
 
-// DisableSecOpt returns a security opt that can be used to disabling SELinux
-// labeling support for future container processes
+// DisableSecOpt returns a security opt that can be used to disable SELinux
+// labeling support for future container processes.
 func DisableSecOpt() []string {
 	return []string{"disable"}
 }

+ 188 - 0
vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go

@@ -0,0 +1,188 @@
+// +build !selinux
+
+package selinux
+
+import (
+	"errors"
+)
+
+const (
+	// Enforcing constant indicate SELinux is in enforcing mode
+	Enforcing = 1
+	// Permissive constant to indicate SELinux is in permissive mode
+	Permissive = 0
+	// Disabled constant to indicate SELinux is disabled
+	Disabled = -1
+)
+
+var (
+	// ErrMCSAlreadyExists is returned when trying to allocate a duplicate MCS.
+	ErrMCSAlreadyExists = errors.New("MCS label already exists")
+	// ErrEmptyPath is returned when an empty path has been specified.
+	ErrEmptyPath = errors.New("empty path")
+)
+
+// Context is a representation of the SELinux label broken into 4 parts
+type Context map[string]string
+
+// SetDisabled disables selinux support for the package
+func SetDisabled() {
+	return
+}
+
+// GetEnabled returns whether selinux is currently enabled.
+func GetEnabled() bool {
+	return false
+}
+
+// SetFileLabel sets the SELinux label for this path or returns an error.
+func SetFileLabel(fpath string, label string) error {
+	return nil
+}
+
+// FileLabel returns the SELinux label for this path or returns an error.
+func FileLabel(fpath string) (string, error) {
+	return "", nil
+}
+
+/*
+SetFSCreateLabel tells kernel the label to create all file system objects
+created by this task. Setting label="" to return to default.
+*/
+func SetFSCreateLabel(label string) error {
+	return nil
+}
+
+/*
+FSCreateLabel returns the default label the kernel which the kernel is using
+for file system objects created by this task. "" indicates default.
+*/
+func FSCreateLabel() (string, error) {
+	return "", nil
+}
+
+// CurrentLabel returns the SELinux label of the current process thread, or an error.
+func CurrentLabel() (string, error) {
+	return "", nil
+}
+
+// PidLabel returns the SELinux label of the given pid, or an error.
+func PidLabel(pid int) (string, error) {
+	return "", nil
+}
+
+/*
+ExecLabel returns the SELinux label that the kernel will use for any programs
+that are executed by the current process thread, or an error.
+*/
+func ExecLabel() (string, error) {
+	return "", nil
+}
+
+/*
+CanonicalizeContext takes a context string and writes it to the kernel
+the function then returns the context that the kernel will use.  This function
+can be used to see if two contexts are equivalent
+*/
+func CanonicalizeContext(val string) (string, error) {
+	return "", nil
+}
+
+/*
+SetExecLabel sets the SELinux label that the kernel will use for any programs
+that are executed by the current process thread, or an error.
+*/
+func SetExecLabel(label string) error {
+	return nil
+}
+
+// Get returns the Context as a string
+func (c Context) Get() string {
+	return ""
+}
+
+// NewContext creates a new Context struct from the specified label
+func NewContext(label string) Context {
+	c := make(Context)
+	return c
+}
+
+// ReserveLabel reserves the MLS/MCS level component of the specified label
+func ReserveLabel(label string) {
+	return
+}
+
+// EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
+func EnforceMode() int {
+	return Disabled
+}
+
+/*
+SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
+Disabled is not valid, since this needs to be set at boot time.
+*/
+func SetEnforceMode(mode int) error {
+	return nil
+}
+
+/*
+DefaultEnforceMode returns the systems default SELinux mode Enforcing,
+Permissive or Disabled. Note this is is just the default at boot time.
+EnforceMode tells you the systems current mode.
+*/
+func DefaultEnforceMode() int {
+	return Disabled
+}
+
+/*
+ReleaseLabel will unreserve the MLS/MCS Level field of the specified label.
+Allowing it to be used by another process.
+*/
+func ReleaseLabel(label string) {
+	return
+}
+
+// ROFileLabel returns the specified SELinux readonly file label
+func ROFileLabel() string {
+	return ""
+}
+
+/*
+ContainerLabels returns an allocated processLabel and fileLabel to be used for
+container labeling by the calling process.
+*/
+func ContainerLabels() (processLabel string, fileLabel string) {
+	return "", ""
+}
+
+// SecurityCheckContext validates that the SELinux label is understood by the kernel
+func SecurityCheckContext(val string) error {
+	return nil
+}
+
+/*
+CopyLevel returns a label with the MLS/MCS level from src label replaced on
+the dest label.
+*/
+func CopyLevel(src, dest string) (string, error) {
+	return "", nil
+}
+
+// Chcon changes the `fpath` file object to the SELinux label `label`.
+// If `fpath` is a directory and `recurse`` is true, Chcon will walk the
+// directory tree setting the label.
+func Chcon(fpath string, label string, recurse bool) error {
+	return nil
+}
+
+// DupSecOpt takes an SELinux process label and returns security options that
+// can be used to set the SELinux Type and Level for future container processes.
+func DupSecOpt(src string) []string {
+	return nil
+}
+
+// DisableSecOpt returns a security opt that can be used to disable SELinux
+// labeling support for future container processes.
+func DisableSecOpt() []string {
+	return []string{"disable"}
+}

+ 1 - 1
vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go

@@ -1,4 +1,4 @@
-// +build linux
+// +build selinux,linux
 
 package selinux