vendor: github.com/containerd/containerd v1.5.2
full diff: 19ee068f93
...v1.5.2
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
989cd6e8f6
commit
7c1c123555
76 changed files with 1554 additions and 742 deletions
|
@ -421,7 +421,7 @@ func (pm *Manager) Push(ctx context.Context, name string, metaHeader http.Header
|
|||
|
||||
// Make sure we can authenticate the request since the auth scope for plugin repos is different than a normal repo.
|
||||
ctx = docker.WithScope(ctx, scope(ref, true))
|
||||
if err := remotes.PushContent(ctx, pusher, desc, pm.blobStore, nil, func(h images.Handler) images.Handler {
|
||||
if err := remotes.PushContent(ctx, pusher, desc, pm.blobStore, nil, nil, func(h images.Handler) images.Handler {
|
||||
return images.Handlers(progressHandler, h)
|
||||
}); err != nil {
|
||||
// Try fallback to http.
|
||||
|
@ -433,7 +433,7 @@ func (pm *Manager) Push(ctx context.Context, name string, metaHeader http.Header
|
|||
pusher, _ := resolver.Pusher(ctx, ref.String())
|
||||
if pusher != nil {
|
||||
logrus.WithField("ref", ref).Debug("Re-attmpting push with http-fallback")
|
||||
err2 := remotes.PushContent(ctx, pusher, desc, pm.blobStore, nil, func(h images.Handler) images.Handler {
|
||||
err2 := remotes.PushContent(ctx, pusher, desc, pm.blobStore, nil, nil, func(h images.Handler) images.Handler {
|
||||
return images.Handlers(progressHandler, h)
|
||||
})
|
||||
if err2 == nil {
|
||||
|
|
|
@ -132,7 +132,7 @@ github.com/googleapis/gax-go bd5b16380fd03dc758d11cef74ba
|
|||
google.golang.org/genproto 3f1135a288c9a07e340ae8ba4cc6c7065a3160e8
|
||||
|
||||
# containerd
|
||||
github.com/containerd/containerd 19ee068f93c91f7b9b2a858457f1af2cabc7bc06 # master (v1.5.0-dev)
|
||||
github.com/containerd/containerd 36cc874494a56a253cd181a1a685b44b58a2e34a # v1.5.2
|
||||
github.com/containerd/fifo 650e8a8a179d040123db61f016cb133143e7a581 # v1.0.0
|
||||
github.com/containerd/continuity bce1c3f9669b6f3e7f6656ee715b0b4d75fa64a6 # v0.1.0
|
||||
github.com/containerd/cgroups b9de8a2212026c07cec67baf3323f1fc0121e048 # v1.0.1
|
||||
|
|
88
vendor/github.com/Microsoft/hcsshim/pkg/ociwclayer/export.go
generated
vendored
Normal file
88
vendor/github.com/Microsoft/hcsshim/pkg/ociwclayer/export.go
generated
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
// Package ociwclayer provides functions for importing and exporting Windows
|
||||
// container layers from and to their OCI tar representation.
|
||||
package ociwclayer
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
"io"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/Microsoft/go-winio/backuptar"
|
||||
"github.com/Microsoft/hcsshim"
|
||||
)
|
||||
|
||||
var driverInfo = hcsshim.DriverInfo{}
|
||||
|
||||
// ExportLayerToTar writes an OCI layer tar stream from the provided on-disk layer.
|
||||
// The caller must specify the parent layers, if any, ordered from lowest to
|
||||
// highest layer.
|
||||
//
|
||||
// The layer will be mounted for this process, so the caller should ensure that
|
||||
// it is not currently mounted.
|
||||
func ExportLayerToTar(ctx context.Context, w io.Writer, path string, parentLayerPaths []string) error {
|
||||
err := hcsshim.ActivateLayer(driverInfo, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = hcsshim.DeactivateLayer(driverInfo, path)
|
||||
}()
|
||||
|
||||
// Prepare and unprepare the layer to ensure that it has been initialized.
|
||||
err = hcsshim.PrepareLayer(driverInfo, path, parentLayerPaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = hcsshim.UnprepareLayer(driverInfo, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := hcsshim.NewLayerReader(driverInfo, path, parentLayerPaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeTarFromLayer(ctx, r, w)
|
||||
cerr := r.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cerr
|
||||
}
|
||||
|
||||
func writeTarFromLayer(ctx context.Context, r hcsshim.LayerReader, w io.Writer) error {
|
||||
t := tar.NewWriter(w)
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
name, size, fileInfo, err := r.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if fileInfo == nil {
|
||||
// Write a whiteout file.
|
||||
hdr := &tar.Header{
|
||||
Name: filepath.ToSlash(filepath.Join(filepath.Dir(name), whiteoutPrefix+filepath.Base(name))),
|
||||
}
|
||||
err := t.WriteHeader(hdr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = backuptar.WriteTarFileFromBackupStream(t, r, name, size, fileInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return t.Close()
|
||||
}
|
148
vendor/github.com/Microsoft/hcsshim/pkg/ociwclayer/import.go
generated
vendored
Normal file
148
vendor/github.com/Microsoft/hcsshim/pkg/ociwclayer/import.go
generated
vendored
Normal file
|
@ -0,0 +1,148 @@
|
|||
package ociwclayer
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bufio"
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
winio "github.com/Microsoft/go-winio"
|
||||
"github.com/Microsoft/go-winio/backuptar"
|
||||
"github.com/Microsoft/hcsshim"
|
||||
)
|
||||
|
||||
const whiteoutPrefix = ".wh."
|
||||
|
||||
var (
|
||||
// mutatedFiles is a list of files that are mutated by the import process
|
||||
// and must be backed up and restored.
|
||||
mutatedFiles = map[string]string{
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD": "bcd.bak",
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG": "bcd.log.bak",
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG1": "bcd.log1.bak",
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG2": "bcd.log2.bak",
|
||||
}
|
||||
)
|
||||
|
||||
// ImportLayerFromTar reads a layer from an OCI layer tar stream and extracts it to the
|
||||
// specified path. The caller must specify the parent layers, if any, ordered
|
||||
// from lowest to highest layer.
|
||||
//
|
||||
// The caller must ensure that the thread or process has acquired backup and
|
||||
// restore privileges.
|
||||
//
|
||||
// This function returns the total size of the layer's files, in bytes.
|
||||
func ImportLayerFromTar(ctx context.Context, r io.Reader, path string, parentLayerPaths []string) (int64, error) {
|
||||
err := os.MkdirAll(path, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
w, err := hcsshim.NewLayerWriter(hcsshim.DriverInfo{}, path, parentLayerPaths)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
n, err := writeLayerFromTar(ctx, r, w, path)
|
||||
cerr := w.Close()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if cerr != nil {
|
||||
return 0, cerr
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func writeLayerFromTar(ctx context.Context, r io.Reader, w hcsshim.LayerWriter, root string) (int64, error) {
|
||||
t := tar.NewReader(r)
|
||||
hdr, err := t.Next()
|
||||
totalSize := int64(0)
|
||||
buf := bufio.NewWriter(nil)
|
||||
for err == nil {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return 0, ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
base := path.Base(hdr.Name)
|
||||
if strings.HasPrefix(base, whiteoutPrefix) {
|
||||
name := path.Join(path.Dir(hdr.Name), base[len(whiteoutPrefix):])
|
||||
err = w.Remove(filepath.FromSlash(name))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
hdr, err = t.Next()
|
||||
} else if hdr.Typeflag == tar.TypeLink {
|
||||
err = w.AddLink(filepath.FromSlash(hdr.Name), filepath.FromSlash(hdr.Linkname))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
hdr, err = t.Next()
|
||||
} else {
|
||||
var (
|
||||
name string
|
||||
size int64
|
||||
fileInfo *winio.FileBasicInfo
|
||||
)
|
||||
name, size, fileInfo, err = backuptar.FileInfoFromHeader(hdr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
err = w.Add(filepath.FromSlash(name), fileInfo)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
hdr, err = writeBackupStreamFromTarAndSaveMutatedFiles(buf, w, t, hdr, root)
|
||||
totalSize += size
|
||||
}
|
||||
}
|
||||
if err != io.EOF {
|
||||
return 0, err
|
||||
}
|
||||
return totalSize, nil
|
||||
}
|
||||
|
||||
// writeBackupStreamFromTarAndSaveMutatedFiles reads data from a tar stream and
|
||||
// writes it to a backup stream, and also saves any files that will be mutated
|
||||
// by the import layer process to a backup location.
|
||||
func writeBackupStreamFromTarAndSaveMutatedFiles(buf *bufio.Writer, w io.Writer, t *tar.Reader, hdr *tar.Header, root string) (nextHdr *tar.Header, err error) {
|
||||
var bcdBackup *os.File
|
||||
var bcdBackupWriter *winio.BackupFileWriter
|
||||
if backupPath, ok := mutatedFiles[hdr.Name]; ok {
|
||||
bcdBackup, err = os.Create(filepath.Join(root, backupPath))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
cerr := bcdBackup.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
|
||||
bcdBackupWriter = winio.NewBackupFileWriter(bcdBackup, false)
|
||||
defer func() {
|
||||
cerr := bcdBackupWriter.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
|
||||
buf.Reset(io.MultiWriter(w, bcdBackupWriter))
|
||||
} else {
|
||||
buf.Reset(w)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
ferr := buf.Flush()
|
||||
if err == nil {
|
||||
err = ferr
|
||||
}
|
||||
}()
|
||||
|
||||
return backuptar.WriteBackupStreamFromTarFile(buf, t, hdr)
|
||||
}
|
3
vendor/github.com/containerd/containerd/README.md
generated
vendored
3
vendor/github.com/containerd/containerd/README.md
generated
vendored
|
@ -49,7 +49,8 @@ Please be aware: nightly builds might have critical bugs, it's not recommended f
|
|||
|
||||
Runtime requirements for containerd are very minimal. Most interactions with
|
||||
the Linux and Windows container feature sets are handled via [runc](https://github.com/opencontainers/runc) and/or
|
||||
OS-specific libraries (e.g. [hcsshim](https://github.com/Microsoft/hcsshim) for Microsoft). The current required version of `runc` is always listed in [RUNC.md](/docs/RUNC.md).
|
||||
OS-specific libraries (e.g. [hcsshim](https://github.com/Microsoft/hcsshim) for Microsoft).
|
||||
The current required version of `runc` is described in [RUNC.md](docs/RUNC.md).
|
||||
|
||||
There are specific features
|
||||
used by containerd core code and snapshotters that will require a minimum kernel
|
||||
|
|
25
vendor/github.com/containerd/containerd/archive/tar.go
generated
vendored
25
vendor/github.com/containerd/containerd/archive/tar.go
generated
vendored
|
@ -63,13 +63,34 @@ func Diff(ctx context.Context, a, b string) io.ReadCloser {
|
|||
}
|
||||
|
||||
// WriteDiff writes a tar stream of the computed difference between the
|
||||
// provided directories.
|
||||
// provided paths.
|
||||
//
|
||||
// Produces a tar using OCI style file markers for deletions. Deleted
|
||||
// files will be prepended with the prefix ".wh.". This style is
|
||||
// based off AUFS whiteouts.
|
||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md
|
||||
func WriteDiff(ctx context.Context, w io.Writer, a, b string) error {
|
||||
func WriteDiff(ctx context.Context, w io.Writer, a, b string, opts ...WriteDiffOpt) error {
|
||||
var options WriteDiffOptions
|
||||
for _, opt := range opts {
|
||||
if err := opt(&options); err != nil {
|
||||
return errors.Wrap(err, "failed to apply option")
|
||||
}
|
||||
}
|
||||
if options.writeDiffFunc == nil {
|
||||
options.writeDiffFunc = writeDiffNaive
|
||||
}
|
||||
|
||||
return options.writeDiffFunc(ctx, w, a, b, options)
|
||||
}
|
||||
|
||||
// writeDiffNaive writes a tar stream of the computed difference between the
|
||||
// provided directories on disk.
|
||||
//
|
||||
// Produces a tar using OCI style file markers for deletions. Deleted
|
||||
// files will be prepended with the prefix ".wh.". This style is
|
||||
// based off AUFS whiteouts.
|
||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md
|
||||
func writeDiffNaive(ctx context.Context, w io.Writer, a, b string, _ WriteDiffOptions) error {
|
||||
cw := newChangeWriter(w, b)
|
||||
err := fs.Changes(ctx, a, b, cw.HandleChange)
|
||||
if err != nil {
|
||||
|
|
2
vendor/github.com/containerd/containerd/archive/tar_freebsd.go
generated
vendored
2
vendor/github.com/containerd/containerd/archive/tar_freebsd.go
generated
vendored
|
@ -29,7 +29,7 @@ func mknod(path string, mode uint32, dev uint64) error {
|
|||
// lsetxattrCreate wraps unix.Lsetxattr with FreeBSD-specific flags and errors
|
||||
func lsetxattrCreate(link string, attr string, data []byte) error {
|
||||
err := unix.Lsetxattr(link, attr, data, 0)
|
||||
if err == unix.ENOTSUP|| err == unix.EEXIST {
|
||||
if err == unix.ENOTSUP || err == unix.EEXIST {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
|
|
10
vendor/github.com/containerd/containerd/archive/tar_opts.go
generated
vendored
10
vendor/github.com/containerd/containerd/archive/tar_opts.go
generated
vendored
|
@ -73,3 +73,13 @@ func WithParents(p []string) ApplyOpt {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WriteDiffOptions provides additional options for a WriteDiff operation
|
||||
type WriteDiffOptions struct {
|
||||
ParentLayers []string // Windows needs the full list of parent layers
|
||||
|
||||
writeDiffFunc func(context.Context, io.Writer, string, string, WriteDiffOptions) error
|
||||
}
|
||||
|
||||
// WriteDiffOpt allows setting mutable archive write properties on creation
|
||||
type WriteDiffOpt func(options *WriteDiffOptions) error
|
||||
|
|
43
vendor/github.com/containerd/containerd/archive/tar_opts_windows.go
generated
vendored
43
vendor/github.com/containerd/containerd/archive/tar_opts_windows.go
generated
vendored
|
@ -18,6 +18,19 @@
|
|||
|
||||
package archive
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/Microsoft/hcsshim/pkg/ociwclayer"
|
||||
)
|
||||
|
||||
// applyWindowsLayer applies a tar stream of an OCI style diff tar of a Windows layer
|
||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
|
||||
func applyWindowsLayer(ctx context.Context, root string, r io.Reader, options ApplyOptions) (size int64, err error) {
|
||||
return ociwclayer.ImportLayerFromTar(ctx, r, root, options.Parents)
|
||||
}
|
||||
|
||||
// AsWindowsContainerLayer indicates that the tar stream to apply is that of
|
||||
// a Windows Container Layer. The caller must be holding SeBackupPrivilege and
|
||||
// SeRestorePrivilege.
|
||||
|
@ -27,3 +40,33 @@ func AsWindowsContainerLayer() ApplyOpt {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// writeDiffWindowsLayers writes a tar stream of the computed difference between the
|
||||
// provided Windows layers
|
||||
//
|
||||
// Produces a tar using OCI style file markers for deletions. Deleted
|
||||
// files will be prepended with the prefix ".wh.". This style is
|
||||
// based off AUFS whiteouts.
|
||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md
|
||||
func writeDiffWindowsLayers(ctx context.Context, w io.Writer, _, layer string, options WriteDiffOptions) error {
|
||||
return ociwclayer.ExportLayerToTar(ctx, w, layer, options.ParentLayers)
|
||||
}
|
||||
|
||||
// AsWindowsContainerLayerPair indicates that the paths to diff are a pair of
|
||||
// Windows Container Layers. The caller must be holding SeBackupPrivilege.
|
||||
func AsWindowsContainerLayerPair() WriteDiffOpt {
|
||||
return func(options *WriteDiffOptions) error {
|
||||
options.writeDiffFunc = writeDiffWindowsLayers
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithParentLayers provides the Windows Container Layers that are the parents
|
||||
// of the target (right-hand, "upper") layer, if any. The source (left-hand, "lower")
|
||||
// layer passed to WriteDiff should be "" in this case.
|
||||
func WithParentLayers(p []string) WriteDiffOpt {
|
||||
return func(options *WriteDiffOptions) error {
|
||||
options.ParentLayers = p
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
4
vendor/github.com/containerd/containerd/archive/tar_unix.go
generated
vendored
4
vendor/github.com/containerd/containerd/archive/tar_unix.go
generated
vendored
|
@ -24,7 +24,7 @@ import (
|
|||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/containerd/sys"
|
||||
"github.com/containerd/containerd/pkg/userns"
|
||||
"github.com/containerd/continuity/fs"
|
||||
"github.com/containerd/continuity/sysx"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -87,7 +87,7 @@ func skipFile(hdr *tar.Header) bool {
|
|||
switch hdr.Typeflag {
|
||||
case tar.TypeBlock, tar.TypeChar:
|
||||
// cannot create a device if running in user namespace
|
||||
return sys.RunningInUserNS()
|
||||
return userns.RunningInUserNS()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
|
137
vendor/github.com/containerd/containerd/archive/tar_windows.go
generated
vendored
137
vendor/github.com/containerd/containerd/archive/tar_windows.go
generated
vendored
|
@ -20,33 +20,14 @@ package archive
|
|||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
"github.com/Microsoft/go-winio/backuptar"
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/containerd/containerd/sys"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// mutatedFiles is a list of files that are mutated by the import process
|
||||
// and must be backed up and restored.
|
||||
mutatedFiles = map[string]string{
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD": "bcd.bak",
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG": "bcd.log.bak",
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG1": "bcd.log1.bak",
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG2": "bcd.log2.bak",
|
||||
}
|
||||
)
|
||||
|
||||
// tarName returns platform-specific filepath
|
||||
// to canonical posix-style path for tar archival. p is relative
|
||||
// path.
|
||||
|
@ -141,121 +122,3 @@ func copyDirInfo(fi os.FileInfo, path string) error {
|
|||
func copyUpXAttrs(dst, src string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// applyWindowsLayer applies a tar stream of an OCI style diff tar of a Windows
|
||||
// layer using the hcsshim layer writer and backup streams.
|
||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
|
||||
func applyWindowsLayer(ctx context.Context, root string, r io.Reader, options ApplyOptions) (size int64, err error) {
|
||||
home, id := filepath.Split(root)
|
||||
info := hcsshim.DriverInfo{
|
||||
HomeDir: home,
|
||||
}
|
||||
|
||||
w, err := hcsshim.NewLayerWriter(info, id, options.Parents)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer func() {
|
||||
if err2 := w.Close(); err2 != nil {
|
||||
// This error should not be discarded as a failure here
|
||||
// could result in an invalid layer on disk
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
tr := tar.NewReader(r)
|
||||
buf := bufio.NewWriter(nil)
|
||||
hdr, nextErr := tr.Next()
|
||||
// Iterate through the files in the archive.
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return 0, ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
if nextErr == io.EOF {
|
||||
// end of tar archive
|
||||
break
|
||||
}
|
||||
if nextErr != nil {
|
||||
return 0, nextErr
|
||||
}
|
||||
|
||||
// Note: path is used instead of filepath to prevent OS specific handling
|
||||
// of the tar path
|
||||
base := path.Base(hdr.Name)
|
||||
if strings.HasPrefix(base, whiteoutPrefix) {
|
||||
dir := path.Dir(hdr.Name)
|
||||
originalBase := base[len(whiteoutPrefix):]
|
||||
originalPath := path.Join(dir, originalBase)
|
||||
if err := w.Remove(filepath.FromSlash(originalPath)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
hdr, nextErr = tr.Next()
|
||||
} else if hdr.Typeflag == tar.TypeLink {
|
||||
err := w.AddLink(filepath.FromSlash(hdr.Name), filepath.FromSlash(hdr.Linkname))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
hdr, nextErr = tr.Next()
|
||||
} else {
|
||||
name, fileSize, fileInfo, err := backuptar.FileInfoFromHeader(hdr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := w.Add(filepath.FromSlash(name), fileInfo); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
size += fileSize
|
||||
hdr, nextErr = tarToBackupStreamWithMutatedFiles(buf, w, tr, hdr, root)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// tarToBackupStreamWithMutatedFiles reads data from a tar stream and
|
||||
// writes it to a backup stream, and also saves any files that will be mutated
|
||||
// by the import layer process to a backup location.
|
||||
func tarToBackupStreamWithMutatedFiles(buf *bufio.Writer, w io.Writer, t *tar.Reader, hdr *tar.Header, root string) (nextHdr *tar.Header, err error) {
|
||||
var (
|
||||
bcdBackup *os.File
|
||||
bcdBackupWriter *winio.BackupFileWriter
|
||||
)
|
||||
if backupPath, ok := mutatedFiles[hdr.Name]; ok {
|
||||
bcdBackup, err = os.Create(filepath.Join(root, backupPath))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
cerr := bcdBackup.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
|
||||
bcdBackupWriter = winio.NewBackupFileWriter(bcdBackup, false)
|
||||
defer func() {
|
||||
cerr := bcdBackupWriter.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
|
||||
buf.Reset(io.MultiWriter(w, bcdBackupWriter))
|
||||
} else {
|
||||
buf.Reset(w)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
ferr := buf.Flush()
|
||||
if err == nil {
|
||||
err = ferr
|
||||
}
|
||||
}()
|
||||
|
||||
return backuptar.WriteBackupStreamFromTarFile(buf, t, hdr)
|
||||
}
|
||||
|
|
2
vendor/github.com/containerd/containerd/cio/io.go
generated
vendored
2
vendor/github.com/containerd/containerd/cio/io.go
generated
vendored
|
@ -80,7 +80,7 @@ type FIFOSet struct {
|
|||
|
||||
// Close the FIFOSet
|
||||
func (f *FIFOSet) Close() error {
|
||||
if f.close != nil {
|
||||
if f != nil && f.close != nil {
|
||||
return f.close()
|
||||
}
|
||||
return nil
|
||||
|
|
22
vendor/github.com/containerd/containerd/cio/io_unix.go
generated
vendored
22
vendor/github.com/containerd/containerd/cio/io_unix.go
generated
vendored
|
@ -103,38 +103,36 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func openFifos(ctx context.Context, fifos *FIFOSet) (pipes, error) {
|
||||
var err error
|
||||
func openFifos(ctx context.Context, fifos *FIFOSet) (f pipes, retErr error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if retErr != nil {
|
||||
fifos.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
var f pipes
|
||||
if fifos.Stdin != "" {
|
||||
if f.Stdin, err = fifo.OpenFifo(ctx, fifos.Stdin, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
|
||||
return f, errors.Wrapf(err, "failed to open stdin fifo")
|
||||
if f.Stdin, retErr = fifo.OpenFifo(ctx, fifos.Stdin, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); retErr != nil {
|
||||
return f, errors.Wrapf(retErr, "failed to open stdin fifo")
|
||||
}
|
||||
defer func() {
|
||||
if err != nil && f.Stdin != nil {
|
||||
if retErr != nil && f.Stdin != nil {
|
||||
f.Stdin.Close()
|
||||
}
|
||||
}()
|
||||
}
|
||||
if fifos.Stdout != "" {
|
||||
if f.Stdout, err = fifo.OpenFifo(ctx, fifos.Stdout, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
|
||||
return f, errors.Wrapf(err, "failed to open stdout fifo")
|
||||
if f.Stdout, retErr = fifo.OpenFifo(ctx, fifos.Stdout, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); retErr != nil {
|
||||
return f, errors.Wrapf(retErr, "failed to open stdout fifo")
|
||||
}
|
||||
defer func() {
|
||||
if err != nil && f.Stdout != nil {
|
||||
if retErr != nil && f.Stdout != nil {
|
||||
f.Stdout.Close()
|
||||
}
|
||||
}()
|
||||
}
|
||||
if !fifos.Terminal && fifos.Stderr != "" {
|
||||
if f.Stderr, err = fifo.OpenFifo(ctx, fifos.Stderr, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
|
||||
return f, errors.Wrapf(err, "failed to open stderr fifo")
|
||||
if f.Stderr, retErr = fifo.OpenFifo(ctx, fifos.Stderr, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); retErr != nil {
|
||||
return f, errors.Wrapf(retErr, "failed to open stderr fifo")
|
||||
}
|
||||
}
|
||||
return f, nil
|
||||
|
|
36
vendor/github.com/containerd/containerd/cio/io_windows.go
generated
vendored
36
vendor/github.com/containerd/containerd/cio/io_windows.go
generated
vendored
|
@ -20,7 +20,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
winio "github.com/Microsoft/go-winio"
|
||||
"github.com/containerd/containerd/log"
|
||||
|
@ -43,22 +42,21 @@ func NewFIFOSetInDir(_, id string, terminal bool) (*FIFOSet, error) {
|
|||
}, nil), nil
|
||||
}
|
||||
|
||||
func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
|
||||
var (
|
||||
set []io.Closer
|
||||
)
|
||||
func copyIO(fifos *FIFOSet, ioset *Streams) (_ *cio, retErr error) {
|
||||
cios := &cio{config: fifos.Config}
|
||||
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
_ = cios.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if fifos.Stdin != "" {
|
||||
l, err := winio.ListenPipe(fifos.Stdin, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create stdin pipe %s", fifos.Stdin)
|
||||
}
|
||||
defer func(l net.Listener) {
|
||||
if err != nil {
|
||||
l.Close()
|
||||
}
|
||||
}(l)
|
||||
set = append(set, l)
|
||||
cios.closers = append(cios.closers, l)
|
||||
|
||||
go func() {
|
||||
c, err := l.Accept()
|
||||
|
@ -81,12 +79,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
|
|||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create stdout pipe %s", fifos.Stdout)
|
||||
}
|
||||
defer func(l net.Listener) {
|
||||
if err != nil {
|
||||
l.Close()
|
||||
}
|
||||
}(l)
|
||||
set = append(set, l)
|
||||
cios.closers = append(cios.closers, l)
|
||||
|
||||
go func() {
|
||||
c, err := l.Accept()
|
||||
|
@ -109,12 +102,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
|
|||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create stderr pipe %s", fifos.Stderr)
|
||||
}
|
||||
defer func(l net.Listener) {
|
||||
if err != nil {
|
||||
l.Close()
|
||||
}
|
||||
}(l)
|
||||
set = append(set, l)
|
||||
cios.closers = append(cios.closers, l)
|
||||
|
||||
go func() {
|
||||
c, err := l.Accept()
|
||||
|
@ -132,7 +120,7 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
|
|||
}()
|
||||
}
|
||||
|
||||
return &cio{config: fifos.Config, closers: set}, nil
|
||||
return cios, nil
|
||||
}
|
||||
|
||||
// NewDirectIO returns an IO implementation that exposes the IO streams as io.ReadCloser
|
||||
|
|
20
vendor/github.com/containerd/containerd/client.go
generated
vendored
20
vendor/github.com/containerd/containerd/client.go
generated
vendored
|
@ -63,6 +63,7 @@ import (
|
|||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/semaphore"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/backoff"
|
||||
"google.golang.org/grpc/health/grpc_health_v1"
|
||||
|
@ -226,6 +227,11 @@ func (c *Client) Reconnect() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Runtime returns the name of the runtime being used
|
||||
func (c *Client) Runtime() string {
|
||||
return c.runtime
|
||||
}
|
||||
|
||||
// IsServing returns true if the client can successfully connect to the
|
||||
// containerd daemon and the healthcheck service returns the SERVING
|
||||
// response.
|
||||
|
@ -350,6 +356,9 @@ type RemoteContext struct {
|
|||
// MaxConcurrentDownloads is the max concurrent content downloads for each pull.
|
||||
MaxConcurrentDownloads int
|
||||
|
||||
// MaxConcurrentUploadedLayers is the max concurrent uploaded layers for each push.
|
||||
MaxConcurrentUploadedLayers int
|
||||
|
||||
// AllMetadata downloads all manifests and known-configuration files
|
||||
AllMetadata bool
|
||||
|
||||
|
@ -458,7 +467,12 @@ func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor,
|
|||
wrapper = pushCtx.HandlerWrapper
|
||||
}
|
||||
|
||||
return remotes.PushContent(ctx, pusher, desc, c.ContentStore(), pushCtx.PlatformMatcher, wrapper)
|
||||
var limiter *semaphore.Weighted
|
||||
if pushCtx.MaxConcurrentUploadedLayers > 0 {
|
||||
limiter = semaphore.NewWeighted(int64(pushCtx.MaxConcurrentUploadedLayers))
|
||||
}
|
||||
|
||||
return remotes.PushContent(ctx, pusher, desc, c.ContentStore(), limiter, pushCtx.PlatformMatcher, wrapper)
|
||||
}
|
||||
|
||||
// GetImage returns an existing image
|
||||
|
@ -715,10 +729,12 @@ func (c *Client) Version(ctx context.Context) (Version, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// ServerInfo represents the introspected server information
|
||||
type ServerInfo struct {
|
||||
UUID string
|
||||
}
|
||||
|
||||
// Server returns server information from the introspection service
|
||||
func (c *Client) Server(ctx context.Context) (ServerInfo, error) {
|
||||
c.connMu.Lock()
|
||||
if c.conn == nil {
|
||||
|
@ -784,6 +800,8 @@ func CheckRuntime(current, expected string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// GetSnapshotterSupportedPlatforms returns a platform matchers which represents the
|
||||
// supported platforms for the given snapshotters
|
||||
func (c *Client) GetSnapshotterSupportedPlatforms(ctx context.Context, snapshotterName string) (platforms.MatchComparer, error) {
|
||||
filters := []string{fmt.Sprintf("type==%s, id==%s", plugin.SnapshotPlugin, snapshotterName)}
|
||||
in := c.IntrospectionService()
|
||||
|
|
8
vendor/github.com/containerd/containerd/client_opts.go
generated
vendored
8
vendor/github.com/containerd/containerd/client_opts.go
generated
vendored
|
@ -228,6 +228,14 @@ func WithMaxConcurrentDownloads(max int) RemoteOpt {
|
|||
}
|
||||
}
|
||||
|
||||
// WithMaxConcurrentUploadedLayers sets max concurrent uploaded layer limit.
|
||||
func WithMaxConcurrentUploadedLayers(max int) RemoteOpt {
|
||||
return func(client *Client, c *RemoteContext) error {
|
||||
c.MaxConcurrentUploadedLayers = max
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithAllMetadata downloads all manifests and known-configuration files
|
||||
func WithAllMetadata() RemoteOpt {
|
||||
return func(_ *Client, c *RemoteContext) error {
|
||||
|
|
10
vendor/github.com/containerd/containerd/container.go
generated
vendored
10
vendor/github.com/containerd/containerd/container.go
generated
vendored
|
@ -32,7 +32,7 @@ import (
|
|||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/oci"
|
||||
"github.com/containerd/containerd/runtime/v2/runc/options"
|
||||
"github.com/containerd/containerd/sys"
|
||||
"github.com/containerd/fifo"
|
||||
"github.com/containerd/typeurl"
|
||||
prototypes "github.com/gogo/protobuf/types"
|
||||
ver "github.com/opencontainers/image-spec/specs-go"
|
||||
|
@ -435,12 +435,12 @@ func loadFifos(response *tasks.GetResponse) *cio.FIFOSet {
|
|||
err error
|
||||
dirs = map[string]struct{}{}
|
||||
)
|
||||
for _, fifo := range fifos {
|
||||
if isFifo, _ := sys.IsFifo(fifo); isFifo {
|
||||
if rerr := os.Remove(fifo); err == nil {
|
||||
for _, f := range fifos {
|
||||
if isFifo, _ := fifo.IsFifo(f); isFifo {
|
||||
if rerr := os.Remove(f); err == nil {
|
||||
err = rerr
|
||||
}
|
||||
dirs[filepath.Dir(fifo)] = struct{}{}
|
||||
dirs[filepath.Dir(f)] = struct{}{}
|
||||
}
|
||||
}
|
||||
for dir := range dirs {
|
||||
|
|
2
vendor/github.com/containerd/containerd/content/adaptor.go
generated
vendored
2
vendor/github.com/containerd/containerd/content/adaptor.go
generated
vendored
|
@ -22,7 +22,7 @@ import (
|
|||
"github.com/containerd/containerd/filters"
|
||||
)
|
||||
|
||||
// AdoptInfo returns `filters.Adaptor` that handles `content.Info`.
|
||||
// AdaptInfo returns `filters.Adaptor` that handles `content.Info`.
|
||||
func AdaptInfo(info Info) filters.Adaptor {
|
||||
return filters.AdapterFunc(func(fieldpath []string) (string, bool) {
|
||||
if len(fieldpath) == 0 {
|
||||
|
|
2
vendor/github.com/containerd/containerd/content/content.go
generated
vendored
2
vendor/github.com/containerd/containerd/content/content.go
generated
vendored
|
@ -37,7 +37,7 @@ type Provider interface {
|
|||
// ReaderAt only requires desc.Digest to be set.
|
||||
// Other fields in the descriptor may be used internally for resolving
|
||||
// the location of the actual data.
|
||||
ReaderAt(ctx context.Context, dec ocispec.Descriptor) (ReaderAt, error)
|
||||
ReaderAt(ctx context.Context, desc ocispec.Descriptor) (ReaderAt, error)
|
||||
}
|
||||
|
||||
// Ingester writes content
|
||||
|
|
28
vendor/github.com/containerd/containerd/content/local/readerat.go
generated
vendored
28
vendor/github.com/containerd/containerd/content/local/readerat.go
generated
vendored
|
@ -18,6 +18,11 @@ package local
|
|||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
)
|
||||
|
||||
// readerat implements io.ReaderAt in a completely stateless manner by opening
|
||||
|
@ -27,6 +32,29 @@ type sizeReaderAt struct {
|
|||
fp *os.File
|
||||
}
|
||||
|
||||
// OpenReader creates ReaderAt from a file
|
||||
func OpenReader(p string) (content.ReaderAt, error) {
|
||||
fi, err := os.Stat(p)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, errors.Wrap(errdefs.ErrNotFound, "blob not found")
|
||||
}
|
||||
|
||||
fp, err := os.Open(p)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, errors.Wrap(errdefs.ErrNotFound, "blob not found")
|
||||
}
|
||||
|
||||
return sizeReaderAt{size: fi.Size(), fp: fp}, nil
|
||||
}
|
||||
|
||||
func (ra sizeReaderAt) ReadAt(p []byte, offset int64) (int, error) {
|
||||
return ra.fp.ReadAt(p, offset)
|
||||
}
|
||||
|
|
22
vendor/github.com/containerd/containerd/content/local/store.go
generated
vendored
22
vendor/github.com/containerd/containerd/content/local/store.go
generated
vendored
|
@ -131,25 +131,13 @@ func (s *store) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.
|
|||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "calculating blob path for ReaderAt")
|
||||
}
|
||||
fi, err := os.Stat(p)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, errors.Wrapf(errdefs.ErrNotFound, "blob %s expected at %s", desc.Digest, p)
|
||||
reader, err := OpenReader(p)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "blob %s expected at %s", desc.Digest, p)
|
||||
}
|
||||
|
||||
fp, err := os.Open(p)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, errors.Wrapf(errdefs.ErrNotFound, "blob %s expected at %s", desc.Digest, p)
|
||||
}
|
||||
|
||||
return sizeReaderAt{size: fi.Size(), fp: fp}, nil
|
||||
return reader, nil
|
||||
}
|
||||
|
||||
// Delete removes a blob by its digest.
|
||||
|
@ -477,7 +465,6 @@ func (s *store) Writer(ctx context.Context, opts ...content.WriterOpt) (content.
|
|||
}
|
||||
var lockErr error
|
||||
for count := uint64(0); count < 10; count++ {
|
||||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(1<<count)))
|
||||
if err := tryLock(wOpts.Ref); err != nil {
|
||||
if !errdefs.IsUnavailable(err) {
|
||||
return nil, err
|
||||
|
@ -488,6 +475,7 @@ func (s *store) Writer(ctx context.Context, opts ...content.WriterOpt) (content.
|
|||
lockErr = nil
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(1<<count)))
|
||||
}
|
||||
|
||||
if lockErr != nil {
|
||||
|
|
9
vendor/github.com/containerd/containerd/content/proxy/content_writer.go
generated
vendored
9
vendor/github.com/containerd/containerd/content/proxy/content_writer.go
generated
vendored
|
@ -97,7 +97,14 @@ func (rw *remoteWriter) Write(p []byte) (n int, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
|
||||
func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) (err error) {
|
||||
defer func() {
|
||||
err1 := rw.Close()
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
}()
|
||||
|
||||
var base content.Info
|
||||
for _, opt := range opts {
|
||||
if err := opt(&base); err != nil {
|
||||
|
|
2
vendor/github.com/containerd/containerd/defaults/defaults_unix.go
generated
vendored
2
vendor/github.com/containerd/containerd/defaults/defaults_unix.go
generated
vendored
|
@ -34,4 +34,6 @@ const (
|
|||
DefaultFIFODir = "/run/containerd/fifo"
|
||||
// DefaultRuntime is the default linux runtime
|
||||
DefaultRuntime = "io.containerd.runc.v2"
|
||||
// DefaultConfigDir is the default location for config files.
|
||||
DefaultConfigDir = "/etc/containerd"
|
||||
)
|
||||
|
|
3
vendor/github.com/containerd/containerd/defaults/defaults_windows.go
generated
vendored
3
vendor/github.com/containerd/containerd/defaults/defaults_windows.go
generated
vendored
|
@ -30,6 +30,9 @@ var (
|
|||
// DefaultStateDir is the default location used by containerd to store
|
||||
// transient data
|
||||
DefaultStateDir = filepath.Join(os.Getenv("ProgramData"), "containerd", "state")
|
||||
|
||||
// DefaultConfigDir is the default location for config files.
|
||||
DefaultConfigDir = filepath.Join(os.Getenv("programfiles"), "containerd")
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
4
vendor/github.com/containerd/containerd/diff/stream.go
generated
vendored
4
vendor/github.com/containerd/containerd/diff/stream.go
generated
vendored
|
@ -168,6 +168,10 @@ func (c *compressedProcessor) Close() error {
|
|||
return c.rc.Close()
|
||||
}
|
||||
|
||||
// BinaryHandler creates a new stream processor handler which calls out to the given binary.
|
||||
// The id is used to identify the stream processor and allows the caller to send
|
||||
// payloads specific for that stream processor (i.e. decryption keys for decrypt stream processor).
|
||||
// The binary will be called for the provided mediaTypes and return the given media type.
|
||||
func BinaryHandler(id, returnsMediaType string, mediaTypes []string, path string, args, env []string) Handler {
|
||||
set := make(map[string]struct{}, len(mediaTypes))
|
||||
for _, m := range mediaTypes {
|
||||
|
|
79
vendor/github.com/containerd/containerd/go.mod
generated
vendored
79
vendor/github.com/containerd/containerd/go.mod
generated
vendored
|
@ -1,26 +1,24 @@
|
|||
module github.com/containerd/containerd
|
||||
|
||||
go 1.15
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/Microsoft/go-winio v0.4.16
|
||||
github.com/Microsoft/hcsshim v0.8.14
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da
|
||||
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4
|
||||
github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e
|
||||
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102
|
||||
github.com/containerd/console v1.0.1
|
||||
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7
|
||||
github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c
|
||||
github.com/containerd/go-cni v1.0.1
|
||||
github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328
|
||||
github.com/containerd/imgcrypt v1.0.1
|
||||
github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164
|
||||
github.com/Microsoft/go-winio v0.4.17
|
||||
github.com/Microsoft/hcsshim v0.8.16
|
||||
github.com/containerd/aufs v1.0.0
|
||||
github.com/containerd/btrfs v1.0.0
|
||||
github.com/containerd/cgroups v1.0.1
|
||||
github.com/containerd/console v1.0.2
|
||||
github.com/containerd/continuity v0.1.0
|
||||
github.com/containerd/fifo v1.0.0
|
||||
github.com/containerd/go-cni v1.0.2
|
||||
github.com/containerd/go-runc v1.0.0
|
||||
github.com/containerd/imgcrypt v1.1.1
|
||||
github.com/containerd/nri v0.1.0
|
||||
github.com/containerd/ttrpc v1.0.2
|
||||
github.com/containerd/typeurl v1.0.1
|
||||
github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2
|
||||
github.com/containernetworking/plugins v0.8.6
|
||||
github.com/containerd/typeurl v1.0.2
|
||||
github.com/containerd/zfs v1.0.0
|
||||
github.com/containernetworking/plugins v0.9.1
|
||||
github.com/coreos/go-systemd/v22 v22.1.0
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c
|
||||
|
@ -31,43 +29,50 @@ require (
|
|||
github.com/gogo/googleapis v1.4.0
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/protobuf v1.4.3
|
||||
github.com/google/go-cmp v0.5.2
|
||||
github.com/google/uuid v1.1.2
|
||||
github.com/google/go-cmp v0.5.4
|
||||
github.com/google/uuid v1.2.0
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
||||
github.com/hashicorp/go-multierror v1.0.0
|
||||
github.com/imdario/mergo v0.3.10
|
||||
github.com/klauspost/compress v1.11.3
|
||||
github.com/moby/sys/mountinfo v0.4.0
|
||||
github.com/imdario/mergo v0.3.11
|
||||
github.com/klauspost/compress v1.11.13
|
||||
github.com/moby/locker v1.0.1
|
||||
github.com/moby/sys/mountinfo v0.4.1
|
||||
github.com/moby/sys/symlink v0.1.0
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/opencontainers/image-spec v1.0.1
|
||||
github.com/opencontainers/runc v1.0.0-rc92
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6
|
||||
github.com/opencontainers/runc v1.0.0-rc93
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d
|
||||
github.com/opencontainers/selinux v1.8.0
|
||||
github.com/pelletier/go-toml v1.8.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.7.1
|
||||
github.com/prometheus/procfs v0.6.0 // indirect; temporarily force v0.6.0, which was previously defined in imgcrypt as explicit version
|
||||
github.com/satori/go.uuid v1.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
|
||||
github.com/tchap/go-patricia v2.2.6+incompatible
|
||||
github.com/urfave/cli v1.22.2
|
||||
go.etcd.io/bbolt v1.3.5
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435
|
||||
google.golang.org/grpc v1.30.0
|
||||
gotest.tools/v3 v3.0.2
|
||||
k8s.io/api v0.20.1
|
||||
k8s.io/apimachinery v0.20.1
|
||||
k8s.io/apiserver v0.20.1
|
||||
k8s.io/client-go v0.20.1
|
||||
k8s.io/component-base v0.20.1
|
||||
k8s.io/cri-api v0.20.1
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492
|
||||
google.golang.org/grpc v1.33.2
|
||||
gotest.tools/v3 v3.0.3
|
||||
k8s.io/api v0.20.6
|
||||
k8s.io/apimachinery v0.20.6
|
||||
k8s.io/apiserver v0.20.6
|
||||
k8s.io/client-go v0.20.6
|
||||
k8s.io/component-base v0.20.6
|
||||
k8s.io/cri-api v0.20.6
|
||||
k8s.io/klog/v2 v2.4.0
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
|
||||
)
|
||||
|
||||
// When updating replace rules, make sure to also update the rules in integration/client/go.mod
|
||||
replace (
|
||||
// prevent transitional dependencies due to containerd having a circular
|
||||
// dependency on itself through plugins. see .empty-mod/go.mod for details
|
||||
github.com/containerd/containerd => ./.empty-mod/
|
||||
github.com/gogo/googleapis => github.com/gogo/googleapis v1.3.2
|
||||
github.com/golang/protobuf => github.com/golang/protobuf v1.3.5
|
||||
// urfave/cli must be <= v1.22.1 due to a regression: https://github.com/urfave/cli/issues/1092
|
||||
|
|
7
vendor/github.com/containerd/containerd/images/diffid.go
generated
vendored
7
vendor/github.com/containerd/containerd/images/diffid.go
generated
vendored
|
@ -17,10 +17,10 @@
|
|||
package images
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/containerd/containerd/archive/compression"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/labels"
|
||||
"github.com/opencontainers/go-digest"
|
||||
|
@ -55,13 +55,14 @@ func GetDiffID(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (
|
|||
}
|
||||
defer ra.Close()
|
||||
r := content.NewReader(ra)
|
||||
gzR, err := gzip.NewReader(r)
|
||||
uR, err := compression.DecompressStream(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer uR.Close()
|
||||
digester := digest.Canonical.Digester()
|
||||
hashW := digester.Hash()
|
||||
if _, err := io.Copy(hashW, gzR); err != nil {
|
||||
if _, err := io.Copy(hashW, uR); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := ra.Close(); err != nil {
|
||||
|
|
3
vendor/github.com/containerd/containerd/images/mediatypes.go
generated
vendored
3
vendor/github.com/containerd/containerd/images/mediatypes.go
generated
vendored
|
@ -49,6 +49,9 @@ const (
|
|||
MediaTypeContainerd1CheckpointRuntimeOptions = "application/vnd.containerd.container.checkpoint.runtime.options+proto"
|
||||
// Legacy Docker schema1 manifest
|
||||
MediaTypeDockerSchema1Manifest = "application/vnd.docker.distribution.manifest.v1+prettyjws"
|
||||
// Encypted media types
|
||||
MediaTypeImageLayerEncrypted = ocispec.MediaTypeImageLayer + "+encrypted"
|
||||
MediaTypeImageLayerGzipEncrypted = ocispec.MediaTypeImageLayerGzip + "+encrypted"
|
||||
)
|
||||
|
||||
// DiffCompression returns the compression as defined by the layer diff media
|
||||
|
|
88
vendor/github.com/containerd/containerd/metadata/boltutil/helpers.go
generated
vendored
88
vendor/github.com/containerd/containerd/metadata/boltutil/helpers.go
generated
vendored
|
@ -19,6 +19,8 @@ package boltutil
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/pkg/errors"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
@ -28,6 +30,7 @@ var (
|
|||
bucketKeyLabels = []byte("labels")
|
||||
bucketKeyCreatedAt = []byte("createdat")
|
||||
bucketKeyUpdatedAt = []byte("updatedat")
|
||||
bucketKeyExtensions = []byte("extensions")
|
||||
)
|
||||
|
||||
// ReadLabels reads the labels key from the bucket
|
||||
|
@ -145,3 +148,88 @@ func WriteTimestamps(bkt *bolt.Bucket, created, updated time.Time) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteExtensions will write a KV map to the given bucket,
|
||||
// where `K` is a string key and `V` is a protobuf's Any type that represents a generic extension.
|
||||
func WriteExtensions(bkt *bolt.Bucket, extensions map[string]types.Any) error {
|
||||
if len(extensions) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ebkt, err := bkt.CreateBucketIfNotExists(bucketKeyExtensions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for name, ext := range extensions {
|
||||
p, err := proto.Marshal(&ext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ebkt.Put([]byte(name), p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadExtensions will read back a map of extensions from the given bucket, previously written by WriteExtensions
|
||||
func ReadExtensions(bkt *bolt.Bucket) (map[string]types.Any, error) {
|
||||
var (
|
||||
extensions = make(map[string]types.Any)
|
||||
ebkt = bkt.Bucket(bucketKeyExtensions)
|
||||
)
|
||||
|
||||
if ebkt == nil {
|
||||
return extensions, nil
|
||||
}
|
||||
|
||||
if err := ebkt.ForEach(func(k, v []byte) error {
|
||||
var t types.Any
|
||||
if err := proto.Unmarshal(v, &t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
extensions[string(k)] = t
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return extensions, nil
|
||||
}
|
||||
|
||||
// WriteAny write a protobuf's Any type to the bucket
|
||||
func WriteAny(bkt *bolt.Bucket, name []byte, any *types.Any) error {
|
||||
if any == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
data, err := proto.Marshal(any)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := bkt.Put(name, data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadAny reads back protobuf's Any type from the bucket
|
||||
func ReadAny(bkt *bolt.Bucket, name []byte) (*types.Any, error) {
|
||||
bytes := bkt.Get(name)
|
||||
if bytes == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
out := types.Any{}
|
||||
if err := proto.Unmarshal(bytes, &out); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal any")
|
||||
}
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
|
69
vendor/github.com/containerd/containerd/metadata/containers.go
generated
vendored
69
vendor/github.com/containerd/containerd/metadata/containers.go
generated
vendored
|
@ -336,16 +336,11 @@ func readContainer(container *containers.Container, bkt *bolt.Bucket) error {
|
|||
container.Runtime.Name = string(n)
|
||||
}
|
||||
|
||||
obkt := rbkt.Get(bucketKeyOptions)
|
||||
if obkt == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var any types.Any
|
||||
if err := proto.Unmarshal(obkt, &any); err != nil {
|
||||
any, err := boltutil.ReadAny(rbkt, bucketKeyOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
container.Runtime.Options = &any
|
||||
container.Runtime.Options = any
|
||||
case string(bucketKeySpec):
|
||||
var any types.Any
|
||||
if err := proto.Unmarshal(v, &any); err != nil {
|
||||
|
@ -357,22 +352,8 @@ func readContainer(container *containers.Container, bkt *bolt.Bucket) error {
|
|||
case string(bucketKeySnapshotter):
|
||||
container.Snapshotter = string(v)
|
||||
case string(bucketKeyExtensions):
|
||||
ebkt := bkt.Bucket(bucketKeyExtensions)
|
||||
if ebkt == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
extensions := make(map[string]types.Any)
|
||||
if err := ebkt.ForEach(func(k, v []byte) error {
|
||||
var a types.Any
|
||||
if err := proto.Unmarshal(v, &a); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
extensions[string(k)] = a
|
||||
return nil
|
||||
}); err != nil {
|
||||
|
||||
extensions, err := boltutil.ReadExtensions(bkt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -388,15 +369,8 @@ func writeContainer(bkt *bolt.Bucket, container *containers.Container) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if container.Spec != nil {
|
||||
spec, err := container.Spec.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := bkt.Put(bucketKeySpec, spec); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := boltutil.WriteAny(bkt, bucketKeySpec, container.Spec); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range [][2][]byte{
|
||||
|
@ -424,33 +398,12 @@ func writeContainer(bkt *bolt.Bucket, container *containers.Container) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if len(container.Extensions) > 0 {
|
||||
ebkt, err := bkt.CreateBucketIfNotExists(bucketKeyExtensions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for name, ext := range container.Extensions {
|
||||
p, err := proto.Marshal(&ext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ebkt.Put([]byte(name), p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := boltutil.WriteExtensions(bkt, container.Extensions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if container.Runtime.Options != nil {
|
||||
data, err := proto.Marshal(container.Runtime.Options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := rbkt.Put(bucketKeyOptions, data); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := boltutil.WriteAny(rbkt, bucketKeyOptions, container.Runtime.Options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return boltutil.WriteLabels(bkt, container.Labels)
|
||||
|
|
49
vendor/github.com/containerd/containerd/metadata/namespaces.go
generated
vendored
49
vendor/github.com/containerd/containerd/metadata/namespaces.go
generated
vendored
|
@ -18,6 +18,7 @@ package metadata
|
|||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/identifiers"
|
||||
|
@ -140,10 +141,17 @@ func (s *namespaceStore) Delete(ctx context.Context, namespace string, opts ...n
|
|||
}
|
||||
}
|
||||
bkt := getBucket(s.tx, bucketKeyVersion)
|
||||
if empty, err := s.namespaceEmpty(ctx, namespace); err != nil {
|
||||
types, err := s.listNs(namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !empty {
|
||||
return errors.Wrapf(errdefs.ErrFailedPrecondition, "namespace %q must be empty", namespace)
|
||||
}
|
||||
|
||||
if len(types) > 0 {
|
||||
return errors.Wrapf(
|
||||
errdefs.ErrFailedPrecondition,
|
||||
"namespace %q must be empty, but it still has %s",
|
||||
namespace, strings.Join(types, ", "),
|
||||
)
|
||||
}
|
||||
|
||||
if err := bkt.DeleteBucket([]byte(namespace)); err != nil {
|
||||
|
@ -157,32 +165,35 @@ func (s *namespaceStore) Delete(ctx context.Context, namespace string, opts ...n
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *namespaceStore) namespaceEmpty(ctx context.Context, namespace string) (bool, error) {
|
||||
// Get all data buckets
|
||||
buckets := []*bolt.Bucket{
|
||||
getImagesBucket(s.tx, namespace),
|
||||
getBlobsBucket(s.tx, namespace),
|
||||
getContainersBucket(s.tx, namespace),
|
||||
// listNs returns the types of the remaining objects inside the given namespace.
|
||||
// It doesn't return exact objects due to performance concerns.
|
||||
func (s *namespaceStore) listNs(namespace string) ([]string, error) {
|
||||
var out []string
|
||||
|
||||
if !isBucketEmpty(getImagesBucket(s.tx, namespace)) {
|
||||
out = append(out, "images")
|
||||
}
|
||||
if !isBucketEmpty(getBlobsBucket(s.tx, namespace)) {
|
||||
out = append(out, "blobs")
|
||||
}
|
||||
if !isBucketEmpty(getContainersBucket(s.tx, namespace)) {
|
||||
out = append(out, "containers")
|
||||
}
|
||||
|
||||
if snbkt := getSnapshottersBucket(s.tx, namespace); snbkt != nil {
|
||||
if err := snbkt.ForEach(func(k, v []byte) error {
|
||||
if v == nil {
|
||||
buckets = append(buckets, snbkt.Bucket(k))
|
||||
if !isBucketEmpty(snbkt.Bucket(k)) {
|
||||
out = append(out, "snapshot-"+string(k))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return false, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure data buckets are empty
|
||||
for _, bkt := range buckets {
|
||||
if !isBucketEmpty(bkt) {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func isBucketEmpty(bkt *bolt.Bucket) bool {
|
||||
|
|
48
vendor/github.com/containerd/containerd/mount/losetup_linux.go
generated
vendored
48
vendor/github.com/containerd/containerd/mount/losetup_linux.go
generated
vendored
|
@ -69,7 +69,10 @@ func getFreeLoopDev() (uint32, error) {
|
|||
return uint32(num), nil
|
||||
}
|
||||
|
||||
func setupLoopDev(backingFile, loopDev string, param LoopParams) error {
|
||||
// setupLoopDev attaches the backing file to the loop device and returns
|
||||
// the file handle for the loop device. The caller is responsible for
|
||||
// closing the file handle.
|
||||
func setupLoopDev(backingFile, loopDev string, param LoopParams) (_ *os.File, retErr error) {
|
||||
// 1. Open backing file and loop device
|
||||
flags := os.O_RDWR
|
||||
if param.Readonly {
|
||||
|
@ -78,19 +81,23 @@ func setupLoopDev(backingFile, loopDev string, param LoopParams) error {
|
|||
|
||||
back, err := os.OpenFile(backingFile, flags, 0)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not open backing file: %s", backingFile)
|
||||
return nil, errors.Wrapf(err, "could not open backing file: %s", backingFile)
|
||||
}
|
||||
defer back.Close()
|
||||
|
||||
loop, err := os.OpenFile(loopDev, flags, 0)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not open loop device: %s", loopDev)
|
||||
return nil, errors.Wrapf(err, "could not open loop device: %s", loopDev)
|
||||
}
|
||||
defer loop.Close()
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
loop.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// 2. Set FD
|
||||
if _, _, err = ioctl(loop.Fd(), unix.LOOP_SET_FD, back.Fd()); err != nil {
|
||||
return errors.Wrapf(err, "could not set loop fd for device: %s", loopDev)
|
||||
return nil, errors.Wrapf(err, "could not set loop fd for device: %s", loopDev)
|
||||
}
|
||||
|
||||
// 3. Set Info
|
||||
|
@ -110,7 +117,7 @@ func setupLoopDev(backingFile, loopDev string, param LoopParams) error {
|
|||
|
||||
_, _, err = ioctl(loop.Fd(), unix.LOOP_SET_STATUS64, uintptr(unsafe.Pointer(&info)))
|
||||
if err == nil {
|
||||
return nil
|
||||
return loop, nil
|
||||
}
|
||||
|
||||
if param.Direct {
|
||||
|
@ -119,13 +126,12 @@ func setupLoopDev(backingFile, loopDev string, param LoopParams) error {
|
|||
info.Flags &= ^(uint32(unix.LO_FLAGS_DIRECT_IO))
|
||||
_, _, err = ioctl(loop.Fd(), unix.LOOP_SET_STATUS64, uintptr(unsafe.Pointer(&info)))
|
||||
if err == nil {
|
||||
return nil
|
||||
return loop, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup loop fd and return error
|
||||
_, _, _ = ioctl(loop.Fd(), unix.LOOP_CLR_FD, 0)
|
||||
return errors.Errorf("failed to set loop device info: %v", err)
|
||||
return nil, errors.Errorf("failed to set loop device info: %v", err)
|
||||
}
|
||||
|
||||
// setupLoop looks for (and possibly creates) a free loop device, and
|
||||
|
@ -142,15 +148,16 @@ func setupLoopDev(backingFile, loopDev string, param LoopParams) error {
|
|||
// the loop device when done with it.
|
||||
//
|
||||
// Upon success, the file handle to the loop device is returned.
|
||||
func setupLoop(backingFile string, param LoopParams) (string, error) {
|
||||
func setupLoop(backingFile string, param LoopParams) (*os.File, error) {
|
||||
for retry := 1; retry < 100; retry++ {
|
||||
num, err := getFreeLoopDev()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
loopDev := fmt.Sprintf(loopDevFormat, num)
|
||||
if err := setupLoopDev(backingFile, loopDev, param); err != nil {
|
||||
file, err := setupLoopDev(backingFile, loopDev, param)
|
||||
if err != nil {
|
||||
// Per util-linux/sys-utils/losetup.c:create_loop(),
|
||||
// free loop device can race and we end up failing
|
||||
// with EBUSY when trying to set it up.
|
||||
|
@ -159,13 +166,13 @@ func setupLoop(backingFile string, param LoopParams) (string, error) {
|
|||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(retry*10)))
|
||||
continue
|
||||
}
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return loopDev, nil
|
||||
return file, nil
|
||||
}
|
||||
|
||||
return "", errors.New("timeout creating new loopback device")
|
||||
return nil, errors.New("timeout creating new loopback device")
|
||||
}
|
||||
|
||||
func removeLoop(loopdev string) error {
|
||||
|
@ -179,12 +186,17 @@ func removeLoop(loopdev string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Attach a specified backing file to a loop device
|
||||
// AttachLoopDevice attaches a specified backing file to a loop device
|
||||
func AttachLoopDevice(backingFile string) (string, error) {
|
||||
return setupLoop(backingFile, LoopParams{})
|
||||
file, err := setupLoop(backingFile, LoopParams{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
return file.Name(), nil
|
||||
}
|
||||
|
||||
// Detach a loop device
|
||||
// DetachLoopDevice detaches the provided loop devices
|
||||
func DetachLoopDevice(devices ...string) error {
|
||||
for _, dev := range devices {
|
||||
if err := removeLoop(dev); err != nil {
|
||||
|
|
6
vendor/github.com/containerd/containerd/mount/mount_linux.go
generated
vendored
6
vendor/github.com/containerd/containerd/mount/mount_linux.go
generated
vendored
|
@ -79,14 +79,16 @@ func (m *Mount) Mount(target string) (err error) {
|
|||
// or remount with changed data
|
||||
source := m.Source
|
||||
if losetup {
|
||||
devFile, err := setupLoop(m.Source, LoopParams{
|
||||
loFile, err := setupLoop(m.Source, LoopParams{
|
||||
Readonly: oflags&unix.MS_RDONLY == unix.MS_RDONLY,
|
||||
Autoclear: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer loFile.Close()
|
||||
|
||||
// Mount the loop device instead
|
||||
source = devFile
|
||||
source = loFile.Name()
|
||||
}
|
||||
if err := mountAt(chdir, source, target, m.Type, uintptr(oflags), data); err != nil {
|
||||
return err
|
||||
|
|
75
vendor/github.com/containerd/containerd/oci/spec_opts.go
generated
vendored
75
vendor/github.com/containerd/containerd/oci/spec_opts.go
generated
vendored
|
@ -38,7 +38,6 @@ import (
|
|||
"github.com/opencontainers/runc/libcontainer/user"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/syndtr/gocapability/capability"
|
||||
)
|
||||
|
||||
// SpecOpts sets spec specific information to a newly generated OCI spec
|
||||
|
@ -274,6 +273,28 @@ func WithMounts(mounts []specs.Mount) SpecOpts {
|
|||
}
|
||||
}
|
||||
|
||||
// WithoutMounts removes mounts
|
||||
func WithoutMounts(dests ...string) SpecOpts {
|
||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
var (
|
||||
mounts []specs.Mount
|
||||
current = s.Mounts
|
||||
)
|
||||
mLoop:
|
||||
for _, m := range current {
|
||||
mDestination := filepath.Clean(m.Destination)
|
||||
for _, dest := range dests {
|
||||
if mDestination == dest {
|
||||
continue mLoop
|
||||
}
|
||||
}
|
||||
mounts = append(mounts, m)
|
||||
}
|
||||
s.Mounts = mounts
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithHostNamespace allows a task to run inside the host's linux namespace
|
||||
func WithHostNamespace(ns specs.LinuxNamespaceType) SpecOpts {
|
||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
|
@ -295,10 +316,7 @@ func WithLinuxNamespace(ns specs.LinuxNamespace) SpecOpts {
|
|||
setLinux(s)
|
||||
for i, n := range s.Linux.Namespaces {
|
||||
if n.Type == ns.Type {
|
||||
before := s.Linux.Namespaces[:i]
|
||||
after := s.Linux.Namespaces[i+1:]
|
||||
s.Linux.Namespaces = append(before, ns)
|
||||
s.Linux.Namespaces = append(s.Linux.Namespaces, after...)
|
||||
s.Linux.Namespaces[i] = ns
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -776,29 +794,6 @@ func WithCapabilities(caps []string) SpecOpts {
|
|||
}
|
||||
}
|
||||
|
||||
// WithAllCapabilities sets all linux capabilities for the process
|
||||
var WithAllCapabilities = func(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
|
||||
return WithCapabilities(GetAllCapabilities())(ctx, client, c, s)
|
||||
}
|
||||
|
||||
// GetAllCapabilities returns all caps up to CAP_LAST_CAP
|
||||
// or CAP_BLOCK_SUSPEND on RHEL6
|
||||
func GetAllCapabilities() []string {
|
||||
last := capability.CAP_LAST_CAP
|
||||
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
|
||||
if last == capability.Cap(63) {
|
||||
last = capability.CAP_BLOCK_SUSPEND
|
||||
}
|
||||
var caps []string
|
||||
for _, cap := range capability.List() {
|
||||
if cap > last {
|
||||
continue
|
||||
}
|
||||
caps = append(caps, "CAP_"+strings.ToUpper(cap.String()))
|
||||
}
|
||||
return caps
|
||||
}
|
||||
|
||||
func capsContain(caps []string, s string) bool {
|
||||
for _, c := range caps {
|
||||
if c == s {
|
||||
|
@ -954,16 +949,13 @@ func WithReadonlyPaths(paths []string) SpecOpts {
|
|||
|
||||
// WithWriteableSysfs makes any sysfs mounts writeable
|
||||
func WithWriteableSysfs(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
for i, m := range s.Mounts {
|
||||
for _, m := range s.Mounts {
|
||||
if m.Type == "sysfs" {
|
||||
var options []string
|
||||
for _, o := range m.Options {
|
||||
for i, o := range m.Options {
|
||||
if o == "ro" {
|
||||
o = "rw"
|
||||
m.Options[i] = "rw"
|
||||
}
|
||||
options = append(options, o)
|
||||
}
|
||||
s.Mounts[i].Options = options
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -971,16 +963,13 @@ func WithWriteableSysfs(_ context.Context, _ Client, _ *containers.Container, s
|
|||
|
||||
// WithWriteableCgroupfs makes any cgroup mounts writeable
|
||||
func WithWriteableCgroupfs(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
for i, m := range s.Mounts {
|
||||
for _, m := range s.Mounts {
|
||||
if m.Type == "cgroup" {
|
||||
var options []string
|
||||
for _, o := range m.Options {
|
||||
for i, o := range m.Options {
|
||||
if o == "ro" {
|
||||
o = "rw"
|
||||
m.Options[i] = "rw"
|
||||
}
|
||||
options = append(options, o)
|
||||
}
|
||||
s.Mounts[i].Options = options
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -1132,7 +1121,7 @@ func WithDefaultUnixDevices(_ context.Context, _ Client, _ *containers.Container
|
|||
|
||||
// WithPrivileged sets up options for a privileged container
|
||||
var WithPrivileged = Compose(
|
||||
WithAllCapabilities,
|
||||
WithAllCurrentCapabilities,
|
||||
WithMaskedPaths(nil),
|
||||
WithReadonlyPaths(nil),
|
||||
WithWriteableSysfs,
|
||||
|
@ -1205,15 +1194,13 @@ func WithLinuxDevices(devices []specs.LinuxDevice) SpecOpts {
|
|||
}
|
||||
}
|
||||
|
||||
var ErrNotADevice = errors.New("not a device node")
|
||||
|
||||
// WithLinuxDevice adds the device specified by path to the spec
|
||||
func WithLinuxDevice(path, permissions string) SpecOpts {
|
||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
setLinux(s)
|
||||
setResources(s)
|
||||
|
||||
dev, err := deviceFromPath(path, permissions)
|
||||
dev, err := deviceFromPath(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
121
vendor/github.com/containerd/containerd/oci/spec_opts_linux.go
generated
vendored
121
vendor/github.com/containerd/containerd/oci/spec_opts_linux.go
generated
vendored
|
@ -20,20 +20,17 @@ package oci
|
|||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/pkg/cap"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// WithHostDevices adds all the hosts device nodes to the container's spec
|
||||
func WithHostDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
setLinux(s)
|
||||
|
||||
devs, err := getDevices("/dev")
|
||||
devs, err := HostDevices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -41,83 +38,28 @@ func WithHostDevices(_ context.Context, _ Client, _ *containers.Container, s *Sp
|
|||
return nil
|
||||
}
|
||||
|
||||
func getDevices(path string) ([]specs.LinuxDevice, error) {
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []specs.LinuxDevice
|
||||
for _, f := range files {
|
||||
switch {
|
||||
case f.IsDir():
|
||||
switch f.Name() {
|
||||
// ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
|
||||
// ".udev" added to address https://github.com/opencontainers/runc/issues/2093
|
||||
case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts", ".udev":
|
||||
continue
|
||||
default:
|
||||
sub, err := getDevices(filepath.Join(path, f.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, sub...)
|
||||
continue
|
||||
}
|
||||
case f.Name() == "console":
|
||||
continue
|
||||
}
|
||||
device, err := deviceFromPath(filepath.Join(path, f.Name()), "rwm")
|
||||
// WithDevices recursively adds devices from the passed in path and associated cgroup rules for that device.
|
||||
// If devicePath is a dir it traverses the dir to add all devices in that dir.
|
||||
// If devicePath is not a dir, it attempts to add the single device.
|
||||
// If containerPath is not set then the device path is used for the container path.
|
||||
func WithDevices(devicePath, containerPath, permissions string) SpecOpts {
|
||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
devs, err := getDevices(devicePath, containerPath)
|
||||
if err != nil {
|
||||
if err == ErrNotADevice {
|
||||
continue
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
out = append(out, *device)
|
||||
for _, dev := range devs {
|
||||
s.Linux.Devices = append(s.Linux.Devices, dev)
|
||||
s.Linux.Resources.Devices = append(s.Linux.Resources.Devices, specs.LinuxDeviceCgroup{
|
||||
Allow: true,
|
||||
Type: dev.Type,
|
||||
Major: &dev.Major,
|
||||
Minor: &dev.Minor,
|
||||
Access: permissions,
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func deviceFromPath(path, permissions string) (*specs.LinuxDevice, error) {
|
||||
var stat unix.Stat_t
|
||||
if err := unix.Lstat(path, &stat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
// The type is 32bit on mips.
|
||||
devNumber = uint64(stat.Rdev) // nolint: unconvert
|
||||
major = unix.Major(devNumber)
|
||||
minor = unix.Minor(devNumber)
|
||||
)
|
||||
if major == 0 {
|
||||
return nil, ErrNotADevice
|
||||
}
|
||||
|
||||
var (
|
||||
devType string
|
||||
mode = stat.Mode
|
||||
)
|
||||
switch {
|
||||
case mode&unix.S_IFBLK == unix.S_IFBLK:
|
||||
devType = "b"
|
||||
case mode&unix.S_IFCHR == unix.S_IFCHR:
|
||||
devType = "c"
|
||||
}
|
||||
fm := os.FileMode(mode)
|
||||
return &specs.LinuxDevice{
|
||||
Type: devType,
|
||||
Path: path,
|
||||
Major: int64(major),
|
||||
Minor: int64(minor),
|
||||
FileMode: &fm,
|
||||
UID: &stat.Uid,
|
||||
GID: &stat.Gid,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// WithMemorySwap sets the container's swap in bytes
|
||||
|
@ -180,3 +122,24 @@ func WithCPUCFS(quota int64, period uint64) SpecOpts {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithAllCurrentCapabilities propagates the effective capabilities of the caller process to the container process.
|
||||
// The capability set may differ from WithAllKnownCapabilities when running in a container.
|
||||
var WithAllCurrentCapabilities = func(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
|
||||
caps, err := cap.Current()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return WithCapabilities(caps)(ctx, client, c, s)
|
||||
}
|
||||
|
||||
// WithAllKnownCapabilities sets all the the known linux capabilities for the container process
|
||||
var WithAllKnownCapabilities = func(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
|
||||
caps := cap.Known()
|
||||
return WithCapabilities(caps)(ctx, client, c, s)
|
||||
}
|
||||
|
||||
// WithoutRunMount removes the `/run` inside the spec
|
||||
func WithoutRunMount(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
|
||||
return WithoutMounts("/run")(ctx, client, c, s)
|
||||
}
|
||||
|
|
38
vendor/github.com/containerd/containerd/oci/spec_opts_nonlinux.go
generated
vendored
Normal file
38
vendor/github.com/containerd/containerd/oci/spec_opts_nonlinux.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
// +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 oci
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containerd/containerd/containers"
|
||||
)
|
||||
|
||||
// WithAllCurrentCapabilities propagates the effective capabilities of the caller process to the container process.
|
||||
// The capability set may differ from WithAllKnownCapabilities when running in a container.
|
||||
//nolint: deadcode, unused
|
||||
var WithAllCurrentCapabilities = func(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
|
||||
return WithCapabilities(nil)(ctx, client, c, s)
|
||||
}
|
||||
|
||||
// WithAllKnownCapabilities sets all the the known linux capabilities for the container process
|
||||
//nolint: deadcode, unused
|
||||
var WithAllKnownCapabilities = func(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
|
||||
return WithCapabilities(nil)(ctx, client, c, s)
|
||||
}
|
89
vendor/github.com/containerd/containerd/oci/spec_opts_unix.go
generated
vendored
89
vendor/github.com/containerd/containerd/oci/spec_opts_unix.go
generated
vendored
|
@ -20,20 +20,15 @@ package oci
|
|||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containerd/containerd/containers"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// WithHostDevices adds all the hosts device nodes to the container's spec
|
||||
func WithHostDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
setLinux(s)
|
||||
|
||||
devs, err := getDevices("/dev")
|
||||
devs, err := HostDevices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -41,82 +36,18 @@ func WithHostDevices(_ context.Context, _ Client, _ *containers.Container, s *Sp
|
|||
return nil
|
||||
}
|
||||
|
||||
func getDevices(path string) ([]specs.LinuxDevice, error) {
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []specs.LinuxDevice
|
||||
for _, f := range files {
|
||||
switch {
|
||||
case f.IsDir():
|
||||
switch f.Name() {
|
||||
// ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
|
||||
// ".udev" added to address https://github.com/opencontainers/runc/issues/2093
|
||||
case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts", ".udev":
|
||||
continue
|
||||
default:
|
||||
sub, err := getDevices(filepath.Join(path, f.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, sub...)
|
||||
continue
|
||||
}
|
||||
case f.Name() == "console":
|
||||
continue
|
||||
}
|
||||
device, err := deviceFromPath(filepath.Join(path, f.Name()), "rwm")
|
||||
// WithDevices recursively adds devices from the passed in path and associated cgroup rules for that device.
|
||||
// If devicePath is a dir it traverses the dir to add all devices in that dir.
|
||||
// If devicePath is not a dir, it attempts to add the single device.
|
||||
func WithDevices(devicePath, containerPath, permissions string) SpecOpts {
|
||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
devs, err := getDevices(devicePath, containerPath)
|
||||
if err != nil {
|
||||
if err == ErrNotADevice {
|
||||
continue
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
out = append(out, *device)
|
||||
s.Linux.Devices = append(s.Linux.Devices, devs...)
|
||||
return nil
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func deviceFromPath(path, permissions string) (*specs.LinuxDevice, error) {
|
||||
var stat unix.Stat_t
|
||||
if err := unix.Lstat(path, &stat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
devNumber = uint64(stat.Rdev)
|
||||
major = unix.Major(devNumber)
|
||||
minor = unix.Minor(devNumber)
|
||||
)
|
||||
if major == 0 {
|
||||
return nil, ErrNotADevice
|
||||
}
|
||||
|
||||
var (
|
||||
devType string
|
||||
mode = stat.Mode
|
||||
)
|
||||
switch {
|
||||
case mode&unix.S_IFBLK == unix.S_IFBLK:
|
||||
devType = "b"
|
||||
case mode&unix.S_IFCHR == unix.S_IFCHR:
|
||||
devType = "c"
|
||||
}
|
||||
fm := os.FileMode(mode)
|
||||
return &specs.LinuxDevice{
|
||||
Type: devType,
|
||||
Path: path,
|
||||
Major: int64(major),
|
||||
Minor: int64(minor),
|
||||
FileMode: &fm,
|
||||
UID: &stat.Uid,
|
||||
GID: &stat.Gid,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// WithCPUCFS sets the container's Completely fair scheduling (CFS) quota and period
|
||||
|
|
2
vendor/github.com/containerd/containerd/oci/spec_opts_windows.go
generated
vendored
2
vendor/github.com/containerd/containerd/oci/spec_opts_windows.go
generated
vendored
|
@ -74,6 +74,6 @@ func WithHostDevices(_ context.Context, _ Client, _ *containers.Container, s *Sp
|
|||
return nil
|
||||
}
|
||||
|
||||
func deviceFromPath(path, permissions string) (*specs.LinuxDevice, error) {
|
||||
func deviceFromPath(path string) (*specs.LinuxDevice, error) {
|
||||
return nil, errors.New("device from path not supported on Windows")
|
||||
}
|
||||
|
|
137
vendor/github.com/containerd/containerd/oci/utils_unix.go
generated
vendored
Normal file
137
vendor/github.com/containerd/containerd/oci/utils_unix.go
generated
vendored
Normal file
|
@ -0,0 +1,137 @@
|
|||
// +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 oci
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var errNotADevice = errors.New("not a device node")
|
||||
|
||||
// HostDevices returns all devices that can be found under /dev directory.
|
||||
func HostDevices() ([]specs.LinuxDevice, error) {
|
||||
return getDevices("/dev", "")
|
||||
}
|
||||
|
||||
func getDevices(path, containerPath string) ([]specs.LinuxDevice, error) {
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error stating device path")
|
||||
}
|
||||
|
||||
if !stat.IsDir() {
|
||||
dev, err := deviceFromPath(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if containerPath != "" {
|
||||
dev.Path = containerPath
|
||||
}
|
||||
return []specs.LinuxDevice{*dev}, nil
|
||||
}
|
||||
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []specs.LinuxDevice
|
||||
for _, f := range files {
|
||||
switch {
|
||||
case f.IsDir():
|
||||
switch f.Name() {
|
||||
// ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
|
||||
// ".udev" added to address https://github.com/opencontainers/runc/issues/2093
|
||||
case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts", ".udev":
|
||||
continue
|
||||
default:
|
||||
var cp string
|
||||
if containerPath != "" {
|
||||
cp = filepath.Join(containerPath, filepath.Base(f.Name()))
|
||||
}
|
||||
sub, err := getDevices(filepath.Join(path, f.Name()), cp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, sub...)
|
||||
continue
|
||||
}
|
||||
case f.Name() == "console":
|
||||
continue
|
||||
}
|
||||
device, err := deviceFromPath(filepath.Join(path, f.Name()))
|
||||
if err != nil {
|
||||
if err == errNotADevice {
|
||||
continue
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if containerPath != "" {
|
||||
device.Path = filepath.Join(containerPath, filepath.Base(f.Name()))
|
||||
}
|
||||
out = append(out, *device)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func deviceFromPath(path string) (*specs.LinuxDevice, error) {
|
||||
var stat unix.Stat_t
|
||||
if err := unix.Lstat(path, &stat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
devNumber = uint64(stat.Rdev) //nolint: unconvert // the type is 32bit on mips.
|
||||
major = unix.Major(devNumber)
|
||||
minor = unix.Minor(devNumber)
|
||||
)
|
||||
if major == 0 {
|
||||
return nil, errNotADevice
|
||||
}
|
||||
|
||||
var (
|
||||
devType string
|
||||
mode = stat.Mode
|
||||
)
|
||||
switch {
|
||||
case mode&unix.S_IFBLK == unix.S_IFBLK:
|
||||
devType = "b"
|
||||
case mode&unix.S_IFCHR == unix.S_IFCHR:
|
||||
devType = "c"
|
||||
}
|
||||
fm := os.FileMode(mode &^ unix.S_IFMT)
|
||||
return &specs.LinuxDevice{
|
||||
Type: devType,
|
||||
Path: path,
|
||||
Major: int64(major),
|
||||
Minor: int64(minor),
|
||||
FileMode: &fm,
|
||||
UID: &stat.Uid,
|
||||
GID: &stat.Gid,
|
||||
}, nil
|
||||
}
|
33
vendor/github.com/containerd/containerd/pkg/apparmor/apparmor.go
generated
vendored
33
vendor/github.com/containerd/containerd/pkg/apparmor/apparmor.go
generated
vendored
|
@ -1,5 +1,3 @@
|
|||
// +build linux
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
|
@ -18,31 +16,12 @@
|
|||
|
||||
package apparmor
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
appArmorSupported bool
|
||||
checkAppArmor sync.Once
|
||||
)
|
||||
|
||||
// HostSupports returns true if apparmor is enabled for the host, if
|
||||
// apparmor_parser is enabled, and if we are not running docker-in-docker.
|
||||
// HostSupports returns true if apparmor is enabled for the host, // On non-Linux returns false
|
||||
// On Linux returns true if apparmor_parser is enabled, and if we
|
||||
// are not running docker-in-docker.
|
||||
//
|
||||
// It is a modified version of libcontainer/apparmor.IsEnabled(), which does not
|
||||
// check for apparmor_parser to be present, or if we're running docker-in-docker.
|
||||
// It is a modified version of libcontainer/apparmor.IsEnabled(), which does not
|
||||
// check for apparmor_parser to be present, or if we're running docker-in-docker.
|
||||
func HostSupports() bool {
|
||||
checkAppArmor.Do(func() {
|
||||
// see https://github.com/docker/docker/commit/de191e86321f7d3136ff42ff75826b8107399497
|
||||
if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil && os.Getenv("container") == "" {
|
||||
if _, err = os.Stat("/sbin/apparmor_parser"); err == nil {
|
||||
buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
|
||||
appArmorSupported = err == nil && len(buf) > 1 && buf[0] == 'Y'
|
||||
}
|
||||
}
|
||||
})
|
||||
return appArmorSupported
|
||||
return hostSupports()
|
||||
}
|
||||
|
|
48
vendor/github.com/containerd/containerd/pkg/apparmor/apparmor_linux.go
generated
vendored
Normal file
48
vendor/github.com/containerd/containerd/pkg/apparmor/apparmor_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
// +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 apparmor
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
appArmorSupported bool
|
||||
checkAppArmor sync.Once
|
||||
)
|
||||
|
||||
// hostSupports returns true if apparmor is enabled for the host, if
|
||||
// apparmor_parser is enabled, and if we are not running docker-in-docker.
|
||||
//
|
||||
// It is a modified version of libcontainer/apparmor.IsEnabled(), which does not
|
||||
// check for apparmor_parser to be present, or if we're running docker-in-docker.
|
||||
func hostSupports() bool {
|
||||
checkAppArmor.Do(func() {
|
||||
// see https://github.com/docker/docker/commit/de191e86321f7d3136ff42ff75826b8107399497
|
||||
if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil && os.Getenv("container") == "" {
|
||||
if _, err = os.Stat("/sbin/apparmor_parser"); err == nil {
|
||||
buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
|
||||
appArmorSupported = err == nil && len(buf) > 1 && buf[0] == 'Y'
|
||||
}
|
||||
}
|
||||
})
|
||||
return appArmorSupported
|
||||
}
|
3
vendor/github.com/containerd/containerd/pkg/apparmor/apparmor_unsupported.go
generated
vendored
3
vendor/github.com/containerd/containerd/pkg/apparmor/apparmor_unsupported.go
generated
vendored
|
@ -18,7 +18,6 @@
|
|||
|
||||
package apparmor
|
||||
|
||||
//nolint: deadcode, unused
|
||||
func HostSupports() bool {
|
||||
func hostSupports() bool {
|
||||
return false
|
||||
}
|
||||
|
|
192
vendor/github.com/containerd/containerd/pkg/cap/cap_linux.go
generated
vendored
Normal file
192
vendor/github.com/containerd/containerd/pkg/cap/cap_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
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 cap provides Linux capability utility
|
||||
package cap
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// FromNumber returns a cap string like "CAP_SYS_ADMIN"
|
||||
// that corresponds to the given number like 21.
|
||||
//
|
||||
// FromNumber returns an empty string for unknown cap number.
|
||||
func FromNumber(num int) string {
|
||||
if num < 0 || num > len(capsLatest)-1 {
|
||||
return ""
|
||||
}
|
||||
return capsLatest[num]
|
||||
}
|
||||
|
||||
// FromBitmap parses an uint64 bitmap into string slice like
|
||||
// []{"CAP_SYS_ADMIN", ...}.
|
||||
//
|
||||
// Unknown cap numbers are returned as []int.
|
||||
func FromBitmap(v uint64) ([]string, []int) {
|
||||
var (
|
||||
res []string
|
||||
unknown []int
|
||||
)
|
||||
for i := 0; i <= 63; i++ {
|
||||
if b := (v >> i) & 0x1; b == 0x1 {
|
||||
if s := FromNumber(i); s != "" {
|
||||
res = append(res, s)
|
||||
} else {
|
||||
unknown = append(unknown, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
return res, unknown
|
||||
}
|
||||
|
||||
// Type is the type of capability
|
||||
type Type int
|
||||
|
||||
const (
|
||||
// Effective is CapEff
|
||||
Effective Type = 1 << iota
|
||||
// Permitted is CapPrm
|
||||
Permitted
|
||||
// Inheritable is CapInh
|
||||
Inheritable
|
||||
// Bounding is CapBnd
|
||||
Bounding
|
||||
// Ambient is CapAmb
|
||||
Ambient
|
||||
)
|
||||
|
||||
// ParseProcPIDStatus returns uint64 bitmap value from /proc/<PID>/status file
|
||||
func ParseProcPIDStatus(r io.Reader) (map[Type]uint64, error) {
|
||||
res := make(map[Type]uint64)
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
pair := strings.SplitN(line, ":", 2)
|
||||
if len(pair) != 2 {
|
||||
continue
|
||||
}
|
||||
k := strings.TrimSpace(pair[0])
|
||||
v := strings.TrimSpace(pair[1])
|
||||
switch k {
|
||||
case "CapInh", "CapPrm", "CapEff", "CapBnd", "CapAmb":
|
||||
ui64, err := strconv.ParseUint(v, 16, 64)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("failed to parse line %q", line)
|
||||
}
|
||||
switch k {
|
||||
case "CapInh":
|
||||
res[Inheritable] = ui64
|
||||
case "CapPrm":
|
||||
res[Permitted] = ui64
|
||||
case "CapEff":
|
||||
res[Effective] = ui64
|
||||
case "CapBnd":
|
||||
res[Bounding] = ui64
|
||||
case "CapAmb":
|
||||
res[Ambient] = ui64
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Current returns the list of the effective and the known caps of
|
||||
// the current process.
|
||||
//
|
||||
// The result is like []string{"CAP_SYS_ADMIN", ...}.
|
||||
//
|
||||
// The result does not contain caps that are not recognized by
|
||||
// the "github.com/syndtr/gocapability" library.
|
||||
func Current() ([]string, error) {
|
||||
f, err := os.Open("/proc/self/status")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
caps, err := ParseProcPIDStatus(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
capEff := caps[Effective]
|
||||
names, _ := FromBitmap(capEff)
|
||||
return names, nil
|
||||
}
|
||||
|
||||
var (
|
||||
// caps35 is the caps of kernel 3.5 (37 entries)
|
||||
caps35 = []string{
|
||||
"CAP_CHOWN", // 2.2
|
||||
"CAP_DAC_OVERRIDE", // 2.2
|
||||
"CAP_DAC_READ_SEARCH", // 2.2
|
||||
"CAP_FOWNER", // 2.2
|
||||
"CAP_FSETID", // 2.2
|
||||
"CAP_KILL", // 2.2
|
||||
"CAP_SETGID", // 2.2
|
||||
"CAP_SETUID", // 2.2
|
||||
"CAP_SETPCAP", // 2.2
|
||||
"CAP_LINUX_IMMUTABLE", // 2.2
|
||||
"CAP_NET_BIND_SERVICE", // 2.2
|
||||
"CAP_NET_BROADCAST", // 2.2
|
||||
"CAP_NET_ADMIN", // 2.2
|
||||
"CAP_NET_RAW", // 2.2
|
||||
"CAP_IPC_LOCK", // 2.2
|
||||
"CAP_IPC_OWNER", // 2.2
|
||||
"CAP_SYS_MODULE", // 2.2
|
||||
"CAP_SYS_RAWIO", // 2.2
|
||||
"CAP_SYS_CHROOT", // 2.2
|
||||
"CAP_SYS_PTRACE", // 2.2
|
||||
"CAP_SYS_PACCT", // 2.2
|
||||
"CAP_SYS_ADMIN", // 2.2
|
||||
"CAP_SYS_BOOT", // 2.2
|
||||
"CAP_SYS_NICE", // 2.2
|
||||
"CAP_SYS_RESOURCE", // 2.2
|
||||
"CAP_SYS_TIME", // 2.2
|
||||
"CAP_SYS_TTY_CONFIG", // 2.2
|
||||
"CAP_MKNOD", // 2.4
|
||||
"CAP_LEASE", // 2.4
|
||||
"CAP_AUDIT_WRITE", // 2.6.11
|
||||
"CAP_AUDIT_CONTROL", // 2.6.11
|
||||
"CAP_SETFCAP", // 2.6.24
|
||||
"CAP_MAC_OVERRIDE", // 2.6.25
|
||||
"CAP_MAC_ADMIN", // 2.6.25
|
||||
"CAP_SYSLOG", // 2.6.37
|
||||
"CAP_WAKE_ALARM", // 3.0
|
||||
"CAP_BLOCK_SUSPEND", // 3.5
|
||||
}
|
||||
// caps316 is the caps of kernel 3.16 (38 entries)
|
||||
caps316 = append(caps35, "CAP_AUDIT_READ")
|
||||
// caps58 is the caps of kernel 5.8 (40 entries)
|
||||
caps58 = append(caps316, []string{"CAP_PERFMON", "CAP_BPF"}...)
|
||||
// caps59 is the caps of kernel 5.9 (41 entries)
|
||||
caps59 = append(caps58, "CAP_CHECKPOINT_RESTORE")
|
||||
capsLatest = caps59
|
||||
)
|
||||
|
||||
// Known returns the known cap strings of the latest kernel.
|
||||
// The current latest kernel is 5.9.
|
||||
func Known() []string {
|
||||
return capsLatest
|
||||
}
|
8
vendor/github.com/containerd/containerd/pkg/process/init.go
generated
vendored
8
vendor/github.com/containerd/containerd/pkg/process/init.go
generated
vendored
|
@ -193,11 +193,15 @@ func (p *Init) createCheckpointedState(r *CreateConfig, pidFile *pidFile) error
|
|||
ParentPath: r.ParentCheckpoint,
|
||||
},
|
||||
PidFile: pidFile.Path(),
|
||||
IO: p.io.IO(),
|
||||
NoPivot: p.NoPivotRoot,
|
||||
Detach: true,
|
||||
NoSubreaper: true,
|
||||
}
|
||||
|
||||
if p.io != nil {
|
||||
opts.IO = p.io.IO()
|
||||
}
|
||||
|
||||
p.initState = &createdCheckpointState{
|
||||
p: p,
|
||||
opts: opts,
|
||||
|
@ -441,7 +445,7 @@ func (p *Init) checkpoint(ctx context.Context, r *CheckpointConfig) error {
|
|||
}, actions...); err != nil {
|
||||
dumpLog := filepath.Join(p.Bundle, "criu-dump.log")
|
||||
if cerr := copyFile(dumpLog, filepath.Join(work, "dump.log")); cerr != nil {
|
||||
log.G(ctx).Error(err)
|
||||
log.G(ctx).WithError(cerr).Error("failed to copy dump.log to criu-dump.log")
|
||||
}
|
||||
return fmt.Errorf("%s path= %s", criuError(err), dumpLog)
|
||||
}
|
||||
|
|
18
vendor/github.com/containerd/containerd/pkg/process/io.go
generated
vendored
18
vendor/github.com/containerd/containerd/pkg/process/io.go
generated
vendored
|
@ -34,7 +34,6 @@ import (
|
|||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/containerd/containerd/pkg/stdio"
|
||||
"github.com/containerd/containerd/sys"
|
||||
"github.com/containerd/fifo"
|
||||
runc "github.com/containerd/go-runc"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
@ -179,7 +178,7 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
|
|||
},
|
||||
},
|
||||
} {
|
||||
ok, err := sys.IsFifo(i.name)
|
||||
ok, err := fifo.IsFifo(i.name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -252,14 +251,6 @@ func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (_ runc.IO, err e
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var args []string
|
||||
for k, vs := range uri.Query() {
|
||||
args = append(args, k)
|
||||
if len(vs) > 0 {
|
||||
args = append(args, vs[0])
|
||||
}
|
||||
}
|
||||
|
||||
var closers []func() error
|
||||
defer func() {
|
||||
if err == nil {
|
||||
|
@ -290,12 +281,7 @@ func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (_ runc.IO, err e
|
|||
}
|
||||
closers = append(closers, r.Close, w.Close)
|
||||
|
||||
cmd := exec.Command(uri.Path, args...)
|
||||
cmd.Env = append(cmd.Env,
|
||||
"CONTAINER_ID="+id,
|
||||
"CONTAINER_NAMESPACE="+ns,
|
||||
)
|
||||
|
||||
cmd := NewBinaryCmd(uri, id, ns)
|
||||
cmd.ExtraFiles = append(cmd.ExtraFiles, out.r, serr.r, w)
|
||||
// don't need to register this with the reaper or wait when
|
||||
// running inside a shim
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package runtime
|
||||
package process
|
||||
|
||||
import (
|
||||
"net/url"
|
2
vendor/github.com/containerd/containerd/pkg/process/utils.go
generated
vendored
2
vendor/github.com/containerd/containerd/pkg/process/utils.go
generated
vendored
|
@ -172,7 +172,7 @@ func (p *pidFile) Read() (int, error) {
|
|||
func waitTimeout(ctx context.Context, wg *sync.WaitGroup, timeout time.Duration) error {
|
||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
done := make(chan struct{}, 1)
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(done)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sys
|
||||
package userns
|
||||
|
||||
import (
|
||||
"bufio"
|
|
@ -16,7 +16,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sys
|
||||
package userns
|
||||
|
||||
// RunningInUserNS is a stub for non-Linux systems
|
||||
// Always returns false
|
60
vendor/github.com/containerd/containerd/platforms/defaults_windows.go
generated
vendored
60
vendor/github.com/containerd/containerd/platforms/defaults_windows.go
generated
vendored
|
@ -19,15 +19,63 @@
|
|||
package platforms
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// Default returns the default matcher for the platform.
|
||||
func Default() MatchComparer {
|
||||
return Ordered(DefaultSpec(), specs.Platform{
|
||||
OS: "linux",
|
||||
Architecture: runtime.GOARCH,
|
||||
})
|
||||
type matchComparer struct {
|
||||
defaults Matcher
|
||||
osVersionPrefix string
|
||||
}
|
||||
|
||||
// Match matches platform with the same windows major, minor
|
||||
// and build version.
|
||||
func (m matchComparer) Match(p imagespec.Platform) bool {
|
||||
if m.defaults.Match(p) {
|
||||
// TODO(windows): Figure out whether OSVersion is deprecated.
|
||||
return strings.HasPrefix(p.OSVersion, m.osVersionPrefix)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Less sorts matched platforms in front of other platforms.
|
||||
// For matched platforms, it puts platforms with larger revision
|
||||
// number in front.
|
||||
func (m matchComparer) Less(p1, p2 imagespec.Platform) bool {
|
||||
m1, m2 := m.Match(p1), m.Match(p2)
|
||||
if m1 && m2 {
|
||||
r1, r2 := revision(p1.OSVersion), revision(p2.OSVersion)
|
||||
return r1 > r2
|
||||
}
|
||||
return m1 && !m2
|
||||
}
|
||||
|
||||
func revision(v string) int {
|
||||
parts := strings.Split(v, ".")
|
||||
if len(parts) < 4 {
|
||||
return 0
|
||||
}
|
||||
r, err := strconv.Atoi(parts[3])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Default returns the current platform's default platform specification.
|
||||
func Default() MatchComparer {
|
||||
major, minor, build := windows.RtlGetNtVersionNumbers()
|
||||
return matchComparer{
|
||||
defaults: Ordered(DefaultSpec(), specs.Platform{
|
||||
OS: "linux",
|
||||
Architecture: runtime.GOARCH,
|
||||
}),
|
||||
osVersionPrefix: fmt.Sprintf("%d.%d.%d", major, minor, build),
|
||||
}
|
||||
}
|
||||
|
|
52
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
52
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
|
@ -44,17 +44,47 @@ type dockerPusher struct {
|
|||
tracker StatusTracker
|
||||
}
|
||||
|
||||
// Writer implements Ingester API of content store. This allows the client
|
||||
// to receive ErrUnavailable when there is already an on-going upload.
|
||||
// Note that the tracker MUST implement StatusTrackLocker interface to avoid
|
||||
// race condition on StatusTracker.
|
||||
func (p dockerPusher) Writer(ctx context.Context, opts ...content.WriterOpt) (content.Writer, error) {
|
||||
var wOpts content.WriterOpts
|
||||
for _, opt := range opts {
|
||||
if err := opt(&wOpts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if wOpts.Ref == "" {
|
||||
return nil, errors.Wrap(errdefs.ErrInvalidArgument, "ref must not be empty")
|
||||
}
|
||||
return p.push(ctx, wOpts.Desc, wOpts.Ref, true)
|
||||
}
|
||||
|
||||
func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (content.Writer, error) {
|
||||
return p.push(ctx, desc, remotes.MakeRefKey(ctx, desc), false)
|
||||
}
|
||||
|
||||
func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref string, unavailableOnFail bool) (content.Writer, error) {
|
||||
if l, ok := p.tracker.(StatusTrackLocker); ok {
|
||||
l.Lock(ref)
|
||||
defer l.Unlock(ref)
|
||||
}
|
||||
ctx, err := ContextWithRepositoryScope(ctx, p.refspec, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ref := remotes.MakeRefKey(ctx, desc)
|
||||
status, err := p.tracker.GetStatus(ref)
|
||||
if err == nil {
|
||||
if status.Offset == status.Total {
|
||||
if status.Committed && status.Offset == status.Total {
|
||||
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "ref %v", ref)
|
||||
}
|
||||
if unavailableOnFail {
|
||||
// Another push of this ref is happening elsewhere. The rest of function
|
||||
// will continue only when `errdefs.IsNotFound(err) == true` (i.e. there
|
||||
// is no actively-tracked ref already).
|
||||
return nil, errors.Wrap(errdefs.ErrUnavailable, "push is on-going")
|
||||
}
|
||||
// TODO: Handle incomplete status
|
||||
} else if !errdefs.IsNotFound(err) {
|
||||
return nil, errors.Wrap(err, "failed to get status")
|
||||
|
@ -105,8 +135,11 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
|||
|
||||
if exists {
|
||||
p.tracker.SetStatus(ref, Status{
|
||||
Committed: true,
|
||||
Status: content.Status{
|
||||
Ref: ref,
|
||||
Ref: ref,
|
||||
Total: desc.Size,
|
||||
Offset: desc.Size,
|
||||
// TODO: Set updated time?
|
||||
},
|
||||
})
|
||||
|
@ -162,8 +195,11 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
|||
case http.StatusOK, http.StatusAccepted, http.StatusNoContent:
|
||||
case http.StatusCreated:
|
||||
p.tracker.SetStatus(ref, Status{
|
||||
Committed: true,
|
||||
Status: content.Status{
|
||||
Ref: ref,
|
||||
Ref: ref,
|
||||
Total: desc.Size,
|
||||
Offset: desc.Size,
|
||||
},
|
||||
})
|
||||
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v on remote", desc.Digest)
|
||||
|
@ -341,8 +377,6 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di
|
|||
if err := pw.pipe.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Update status to determine committing
|
||||
|
||||
// TODO: timeout waiting for response
|
||||
resp := <-pw.responseC
|
||||
if resp.err != nil {
|
||||
|
@ -354,7 +388,7 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di
|
|||
switch resp.StatusCode {
|
||||
case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:
|
||||
default:
|
||||
return errors.Errorf("unexpected status: %s", resp.Status)
|
||||
return remoteserrors.NewUnexpectedStatusErr(resp.Response)
|
||||
}
|
||||
|
||||
status, err := pw.tracker.GetStatus(pw.ref)
|
||||
|
@ -379,6 +413,10 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di
|
|||
return errors.Errorf("got digest %s, expected %s", actual, expected)
|
||||
}
|
||||
|
||||
status.Committed = true
|
||||
status.UpdatedAt = time.Now()
|
||||
pw.tracker.SetStatus(pw.ref, status)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
43
vendor/github.com/containerd/containerd/remotes/docker/registry.go
generated
vendored
43
vendor/github.com/containerd/containerd/remotes/docker/registry.go
generated
vendored
|
@ -17,7 +17,10 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// HostCapabilities represent the capabilities of the registry
|
||||
|
@ -56,6 +59,7 @@ const (
|
|||
// Reserved for future capabilities (i.e. search, catalog, remove)
|
||||
)
|
||||
|
||||
// Has checks whether the capabilities list has the provide capability
|
||||
func (c HostCapabilities) Has(t HostCapabilities) bool {
|
||||
return c&t == t
|
||||
}
|
||||
|
@ -201,12 +205,41 @@ func MatchAllHosts(string) (bool, error) {
|
|||
|
||||
// MatchLocalhost is a host match function which returns true for
|
||||
// localhost.
|
||||
//
|
||||
// Note: this does not handle matching of ip addresses in octal,
|
||||
// decimal or hex form.
|
||||
func MatchLocalhost(host string) (bool, error) {
|
||||
for _, s := range []string{"localhost", "127.0.0.1", "[::1]"} {
|
||||
if len(host) >= len(s) && host[0:len(s)] == s && (len(host) == len(s) || host[len(s)] == ':') {
|
||||
return true, nil
|
||||
}
|
||||
switch {
|
||||
case host == "::1":
|
||||
return true, nil
|
||||
case host == "[::1]":
|
||||
return true, nil
|
||||
}
|
||||
return host == "::1", nil
|
||||
h, p, err := net.SplitHostPort(host)
|
||||
|
||||
// addrError helps distinguish between errors of form
|
||||
// "no colon in address" and "too many colons in address".
|
||||
// The former is fine as the host string need not have a
|
||||
// port. Latter needs to be handled.
|
||||
addrError := &net.AddrError{
|
||||
Err: "missing port in address",
|
||||
Addr: host,
|
||||
}
|
||||
if err != nil {
|
||||
if err.Error() != addrError.Error() {
|
||||
return false, err
|
||||
}
|
||||
// host string without any port specified
|
||||
h = host
|
||||
} else if len(p) == 0 {
|
||||
return false, errors.New("invalid host name format")
|
||||
}
|
||||
|
||||
// use ipv4 dotted decimal for further checking
|
||||
if h == "localhost" {
|
||||
h = "127.0.0.1"
|
||||
}
|
||||
ip := net.ParseIP(h)
|
||||
|
||||
return ip.IsLoopback(), nil
|
||||
}
|
||||
|
|
2
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
2
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
|
@ -286,12 +286,14 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp
|
|||
if lastErr == nil {
|
||||
lastErr = err
|
||||
}
|
||||
log.G(ctx).WithError(err).Info("trying next host")
|
||||
continue // try another host
|
||||
}
|
||||
resp.Body.Close() // don't care about body contents.
|
||||
|
||||
if resp.StatusCode > 299 {
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
log.G(ctx).Info("trying next host - response was http.StatusNotFound")
|
||||
continue
|
||||
}
|
||||
return "", ocispec.Descriptor{}, errors.Errorf("unexpected status code %v: %v", u, resp.Status)
|
||||
|
|
22
vendor/github.com/containerd/containerd/remotes/docker/status.go
generated
vendored
22
vendor/github.com/containerd/containerd/remotes/docker/status.go
generated
vendored
|
@ -21,6 +21,7 @@ import (
|
|||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/moby/locker"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -28,6 +29,8 @@ import (
|
|||
type Status struct {
|
||||
content.Status
|
||||
|
||||
Committed bool
|
||||
|
||||
// UploadUUID is used by the Docker registry to reference blob uploads
|
||||
UploadUUID string
|
||||
}
|
||||
|
@ -38,15 +41,24 @@ type StatusTracker interface {
|
|||
SetStatus(string, Status)
|
||||
}
|
||||
|
||||
// StatusTrackLocker to track status of operations with lock
|
||||
type StatusTrackLocker interface {
|
||||
StatusTracker
|
||||
Lock(string)
|
||||
Unlock(string)
|
||||
}
|
||||
|
||||
type memoryStatusTracker struct {
|
||||
statuses map[string]Status
|
||||
m sync.Mutex
|
||||
locker *locker.Locker
|
||||
}
|
||||
|
||||
// NewInMemoryTracker returns a StatusTracker that tracks content status in-memory
|
||||
func NewInMemoryTracker() StatusTracker {
|
||||
func NewInMemoryTracker() StatusTrackLocker {
|
||||
return &memoryStatusTracker{
|
||||
statuses: map[string]Status{},
|
||||
locker: locker.New(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,3 +77,11 @@ func (t *memoryStatusTracker) SetStatus(ref string, status Status) {
|
|||
t.statuses[ref] = status
|
||||
t.m.Unlock()
|
||||
}
|
||||
|
||||
func (t *memoryStatusTracker) Lock(ref string) {
|
||||
t.locker.Lock(ref)
|
||||
}
|
||||
|
||||
func (t *memoryStatusTracker) Unlock(ref string) {
|
||||
t.locker.Unlock(ref)
|
||||
}
|
||||
|
|
18
vendor/github.com/containerd/containerd/remotes/errors/errors.go
generated
vendored
18
vendor/github.com/containerd/containerd/remotes/errors/errors.go
generated
vendored
|
@ -27,9 +27,10 @@ var _ error = ErrUnexpectedStatus{}
|
|||
|
||||
// ErrUnexpectedStatus is returned if a registry API request returned with unexpected HTTP status
|
||||
type ErrUnexpectedStatus struct {
|
||||
Status string
|
||||
StatusCode int
|
||||
Body []byte
|
||||
Status string
|
||||
StatusCode int
|
||||
Body []byte
|
||||
RequestURL, RequestMethod string
|
||||
}
|
||||
|
||||
func (e ErrUnexpectedStatus) Error() string {
|
||||
|
@ -42,5 +43,14 @@ func NewUnexpectedStatusErr(resp *http.Response) error {
|
|||
if resp.Body != nil {
|
||||
b, _ = ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
|
||||
}
|
||||
return ErrUnexpectedStatus{Status: resp.Status, StatusCode: resp.StatusCode, Body: b}
|
||||
err := ErrUnexpectedStatus{
|
||||
Body: b,
|
||||
Status: resp.Status,
|
||||
StatusCode: resp.StatusCode,
|
||||
RequestMethod: resp.Request.Method,
|
||||
}
|
||||
if resp.Request.URL != nil {
|
||||
err.RequestURL = resp.Request.URL.String()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
41
vendor/github.com/containerd/containerd/remotes/handlers.go
generated
vendored
41
vendor/github.com/containerd/containerd/remotes/handlers.go
generated
vendored
|
@ -31,6 +31,7 @@ import (
|
|||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
type refKeyPrefix struct{}
|
||||
|
@ -55,25 +56,32 @@ func WithMediaTypeKeyPrefix(ctx context.Context, mediaType, prefix string) conte
|
|||
// used to lookup ongoing processes related to the descriptor. This function
|
||||
// may look to the context to namespace the reference appropriately.
|
||||
func MakeRefKey(ctx context.Context, desc ocispec.Descriptor) string {
|
||||
key := desc.Digest.String()
|
||||
if desc.Annotations != nil {
|
||||
if name, ok := desc.Annotations[ocispec.AnnotationRefName]; ok {
|
||||
key = fmt.Sprintf("%s@%s", name, desc.Digest.String())
|
||||
}
|
||||
}
|
||||
|
||||
if v := ctx.Value(refKeyPrefix{}); v != nil {
|
||||
values := v.(map[string]string)
|
||||
if prefix := values[desc.MediaType]; prefix != "" {
|
||||
return prefix + "-" + desc.Digest.String()
|
||||
return prefix + "-" + key
|
||||
}
|
||||
}
|
||||
|
||||
switch mt := desc.MediaType; {
|
||||
case mt == images.MediaTypeDockerSchema2Manifest || mt == ocispec.MediaTypeImageManifest:
|
||||
return "manifest-" + desc.Digest.String()
|
||||
return "manifest-" + key
|
||||
case mt == images.MediaTypeDockerSchema2ManifestList || mt == ocispec.MediaTypeImageIndex:
|
||||
return "index-" + desc.Digest.String()
|
||||
return "index-" + key
|
||||
case images.IsLayerType(mt):
|
||||
return "layer-" + desc.Digest.String()
|
||||
return "layer-" + key
|
||||
case images.IsKnownConfig(mt):
|
||||
return "config-" + desc.Digest.String()
|
||||
return "config-" + key
|
||||
default:
|
||||
log.G(ctx).Warnf("reference for unknown type: %s", mt)
|
||||
return "unknown-" + desc.Digest.String()
|
||||
return "unknown-" + key
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,6 +123,12 @@ func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc
|
|||
return err
|
||||
}
|
||||
|
||||
if desc.Size == 0 {
|
||||
// most likely a poorly configured registry/web front end which responded with no
|
||||
// Content-Length header; unable (not to mention useless) to commit a 0-length entry
|
||||
// into the content store. Error out here otherwise the error sent back is confusing
|
||||
return errors.Wrapf(errdefs.ErrInvalidArgument, "unable to fetch descriptor (%s) which reports content size of zero", desc.Digest)
|
||||
}
|
||||
if ws.Offset == desc.Size {
|
||||
// If writer is already complete, commit and return
|
||||
err := cw.Commit(ctx, desc.Size, desc.Digest)
|
||||
|
@ -151,7 +165,15 @@ func PushHandler(pusher Pusher, provider content.Provider) images.HandlerFunc {
|
|||
func push(ctx context.Context, provider content.Provider, pusher Pusher, desc ocispec.Descriptor) error {
|
||||
log.G(ctx).Debug("push")
|
||||
|
||||
cw, err := pusher.Push(ctx, desc)
|
||||
var (
|
||||
cw content.Writer
|
||||
err error
|
||||
)
|
||||
if cs, ok := pusher.(content.Ingester); ok {
|
||||
cw, err = content.OpenWriter(ctx, cs, content.WithRef(MakeRefKey(ctx, desc)), content.WithDescriptor(desc))
|
||||
} else {
|
||||
cw, err = pusher.Push(ctx, desc)
|
||||
}
|
||||
if err != nil {
|
||||
if !errdefs.IsAlreadyExists(err) {
|
||||
return err
|
||||
|
@ -175,7 +197,8 @@ func push(ctx context.Context, provider content.Provider, pusher Pusher, desc oc
|
|||
//
|
||||
// Base handlers can be provided which will be called before any push specific
|
||||
// handlers.
|
||||
func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, store content.Store, platform platforms.MatchComparer, wrapper func(h images.Handler) images.Handler) error {
|
||||
func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, store content.Store, limiter *semaphore.Weighted, platform platforms.MatchComparer, wrapper func(h images.Handler) images.Handler) error {
|
||||
|
||||
var m sync.Mutex
|
||||
manifestStack := []ocispec.Descriptor{}
|
||||
|
||||
|
@ -207,7 +230,7 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, st
|
|||
handler = wrapper(handler)
|
||||
}
|
||||
|
||||
if err := images.Dispatch(ctx, handler, nil, desc); err != nil {
|
||||
if err := images.Dispatch(ctx, handler, limiter, desc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
2
vendor/github.com/containerd/containerd/remotes/resolver.go
generated
vendored
2
vendor/github.com/containerd/containerd/remotes/resolver.go
generated
vendored
|
@ -45,6 +45,8 @@ type Resolver interface {
|
|||
Fetcher(ctx context.Context, ref string) (Fetcher, error)
|
||||
|
||||
// Pusher returns a new pusher for the provided reference
|
||||
// The returned Pusher should satisfy content.Ingester and concurrent attempts
|
||||
// to push the same blob using the Ingester API should result in ErrUnavailable.
|
||||
Pusher(ctx context.Context, ref string) (Pusher, error)
|
||||
}
|
||||
|
||||
|
|
4
vendor/github.com/containerd/containerd/rootfs/init.go
generated
vendored
4
vendor/github.com/containerd/containerd/rootfs/init.go
generated
vendored
|
@ -67,7 +67,7 @@ func InitRootFS(ctx context.Context, name string, parent digest.Digest, readonly
|
|||
return snapshotter.Prepare(ctx, name, parentS)
|
||||
}
|
||||
|
||||
func createInitLayer(ctx context.Context, parent, initName string, initFn func(string) error, snapshotter snapshots.Snapshotter, mounter Mounter) (string, error) {
|
||||
func createInitLayer(ctx context.Context, parent, initName string, initFn func(string) error, snapshotter snapshots.Snapshotter, mounter Mounter) (_ string, retErr error) {
|
||||
initS := fmt.Sprintf("%s %s", parent, initName)
|
||||
if _, err := snapshotter.Stat(ctx, initS); err == nil {
|
||||
return initS, nil
|
||||
|
@ -87,7 +87,7 @@ func createInitLayer(ctx context.Context, parent, initName string, initFn func(s
|
|||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if retErr != nil {
|
||||
if rerr := snapshotter.Remove(ctx, td); rerr != nil {
|
||||
log.G(ctx).Errorf("Failed to remove snapshot %s: %v", td, rerr)
|
||||
}
|
||||
|
|
10
vendor/github.com/containerd/containerd/runtime/runtime.go
generated
vendored
10
vendor/github.com/containerd/containerd/runtime/runtime.go
generated
vendored
|
@ -63,14 +63,14 @@ type PlatformRuntime interface {
|
|||
// ID of the runtime
|
||||
ID() string
|
||||
// Create creates a task with the provided id and options.
|
||||
Create(ctx context.Context, id string, opts CreateOpts) (Task, error)
|
||||
Create(ctx context.Context, taskID string, opts CreateOpts) (Task, error)
|
||||
// Get returns a task.
|
||||
Get(context.Context, string) (Task, error)
|
||||
Get(ctx context.Context, taskID string) (Task, error)
|
||||
// Tasks returns all the current tasks for the runtime.
|
||||
// Any container runs at most one task at a time.
|
||||
Tasks(context.Context, bool) ([]Task, error)
|
||||
Tasks(ctx context.Context, all bool) ([]Task, error)
|
||||
// Add adds a task into runtime.
|
||||
Add(context.Context, Task) error
|
||||
Add(ctx context.Context, task Task) error
|
||||
// Delete remove a task.
|
||||
Delete(context.Context, string)
|
||||
Delete(ctx context.Context, taskID string)
|
||||
}
|
||||
|
|
34
vendor/github.com/containerd/containerd/runtime/task.go
generated
vendored
34
vendor/github.com/containerd/containerd/runtime/task.go
generated
vendored
|
@ -36,19 +36,19 @@ type Process interface {
|
|||
// ID of the process
|
||||
ID() string
|
||||
// State returns the process state
|
||||
State(context.Context) (State, error)
|
||||
State(ctx context.Context) (State, error)
|
||||
// Kill signals a container
|
||||
Kill(context.Context, uint32, bool) error
|
||||
// Pty resizes the processes pty/console
|
||||
ResizePty(context.Context, ConsoleSize) error
|
||||
// CloseStdin closes the processes stdin
|
||||
CloseIO(context.Context) error
|
||||
Kill(ctx context.Context, signal uint32, all bool) error
|
||||
// ResizePty resizes the processes pty/console
|
||||
ResizePty(ctx context.Context, size ConsoleSize) error
|
||||
// CloseIO closes the processes IO
|
||||
CloseIO(ctx context.Context) error
|
||||
// Start the container's user defined process
|
||||
Start(context.Context) error
|
||||
Start(ctx context.Context) error
|
||||
// Wait for the process to exit
|
||||
Wait(context.Context) (*Exit, error)
|
||||
Wait(ctx context.Context) (*Exit, error)
|
||||
// Delete deletes the process
|
||||
Delete(context.Context) (*Exit, error)
|
||||
Delete(ctx context.Context) (*Exit, error)
|
||||
}
|
||||
|
||||
// Task is the runtime object for an executing container
|
||||
|
@ -60,21 +60,21 @@ type Task interface {
|
|||
// Namespace that the task exists in
|
||||
Namespace() string
|
||||
// Pause pauses the container process
|
||||
Pause(context.Context) error
|
||||
Pause(ctx context.Context) error
|
||||
// Resume unpauses the container process
|
||||
Resume(context.Context) error
|
||||
Resume(ctx context.Context) error
|
||||
// Exec adds a process into the container
|
||||
Exec(context.Context, string, ExecOpts) (Process, error)
|
||||
Exec(ctx context.Context, id string, opts ExecOpts) (Process, error)
|
||||
// Pids returns all pids
|
||||
Pids(context.Context) ([]ProcessInfo, error)
|
||||
Pids(ctx context.Context) ([]ProcessInfo, error)
|
||||
// Checkpoint checkpoints a container to an image with live system data
|
||||
Checkpoint(context.Context, string, *types.Any) error
|
||||
Checkpoint(ctx context.Context, path string, opts *types.Any) error
|
||||
// Update sets the provided resources to a running task
|
||||
Update(context.Context, *types.Any, map[string]string) error
|
||||
Update(ctx context.Context, resources *types.Any, annotations map[string]string) error
|
||||
// Process returns a process within the task for the provided id
|
||||
Process(context.Context, string) (Process, error)
|
||||
Process(ctx context.Context, id string) (Process, error)
|
||||
// Stats returns runtime specific metrics for a task
|
||||
Stats(context.Context) (*types.Any, error)
|
||||
Stats(ctx context.Context) (*types.Any, error)
|
||||
}
|
||||
|
||||
// ExecOpts provides additional options for additional processes running in a task
|
||||
|
|
2
vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go
generated
vendored
2
vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go
generated
vendored
|
@ -219,7 +219,7 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts
|
|||
namespaces.WithNamespace(context.TODO(), namespace), cleanupTimeout)
|
||||
defer deferCancel()
|
||||
if kerr := s.KillShim(deferCtx); kerr != nil {
|
||||
log.G(ctx).WithError(err).Error("failed to kill shim")
|
||||
log.G(ctx).WithError(kerr).Error("failed to kill shim")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
|
5
vendor/github.com/containerd/containerd/runtime/v1/shim/client/client.go
generated
vendored
5
vendor/github.com/containerd/containerd/runtime/v1/shim/client/client.go
generated
vendored
|
@ -182,10 +182,7 @@ func setupOOMScore(shimPid int) error {
|
|||
return errors.Wrap(err, "get daemon OOM score")
|
||||
}
|
||||
shimScore := score + 1
|
||||
if shimScore > sys.OOMScoreAdjMax {
|
||||
shimScore = sys.OOMScoreAdjMax
|
||||
}
|
||||
if err := sys.SetOOMScore(shimPid, shimScore); err != nil {
|
||||
if err := sys.AdjustOOMScore(shimPid, shimScore); err != nil {
|
||||
return errors.Wrap(err, "set shim OOM score")
|
||||
}
|
||||
return nil
|
||||
|
|
3
vendor/github.com/containerd/containerd/runtime/v1/shim/service.go
generated
vendored
3
vendor/github.com/containerd/containerd/runtime/v1/shim/service.go
generated
vendored
|
@ -397,6 +397,9 @@ func (s *Service) ListPids(ctx context.Context, r *shimapi.ListPidsRequest) (*sh
|
|||
return nil, errdefs.ToGRPC(err)
|
||||
}
|
||||
var processes []*task.ProcessInfo
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for _, pid := range pids {
|
||||
pInfo := task.ProcessInfo{
|
||||
Pid: pid,
|
||||
|
|
6
vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go
generated
vendored
6
vendor/github.com/containerd/containerd/runtime/v1/shim/service_linux.go
generated
vendored
|
@ -26,7 +26,7 @@ import (
|
|||
|
||||
"github.com/containerd/console"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/containerd/containerd/runtime"
|
||||
"github.com/containerd/containerd/pkg/process"
|
||||
"github.com/containerd/fifo"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -75,14 +75,14 @@ func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console
|
|||
return nil, err
|
||||
}
|
||||
|
||||
cmd := runtime.NewBinaryCmd(uri, id, ns)
|
||||
cmd := process.NewBinaryCmd(uri, id, ns)
|
||||
|
||||
// In case of unexpected errors during logging binary start, close open pipes
|
||||
var filesToClose []*os.File
|
||||
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
runtime.CloseFiles(filesToClose...)
|
||||
process.CloseFiles(filesToClose...)
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
7
vendor/github.com/containerd/containerd/runtime/v1/shim/service_unix.go
generated
vendored
7
vendor/github.com/containerd/containerd/runtime/v1/shim/service_unix.go
generated
vendored
|
@ -28,7 +28,7 @@ import (
|
|||
|
||||
"github.com/containerd/console"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/containerd/containerd/runtime"
|
||||
"github.com/containerd/containerd/pkg/process"
|
||||
"github.com/containerd/fifo"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -63,15 +63,14 @@ func (p *unixPlatform) CopyConsole(ctx context.Context, console console.Console,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd := runtime.NewBinaryCmd(uri, id, ns)
|
||||
cmd := process.NewBinaryCmd(uri, id, ns)
|
||||
|
||||
// In case of unexpected errors during logging binary start, close open pipes
|
||||
var filesToClose []*os.File
|
||||
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
runtime.CloseFiles(filesToClose...)
|
||||
process.CloseFiles(filesToClose...)
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
2
vendor/github.com/containerd/containerd/services/introspection/introspection.go
generated
vendored
2
vendor/github.com/containerd/containerd/services/introspection/introspection.go
generated
vendored
|
@ -25,6 +25,7 @@ import (
|
|||
ptypes "github.com/gogo/protobuf/types"
|
||||
)
|
||||
|
||||
// Service defines the instrospection service interface
|
||||
type Service interface {
|
||||
Plugins(context.Context, []string) (*api.PluginsResponse, error)
|
||||
Server(context.Context, *ptypes.Empty) (*api.ServerResponse, error)
|
||||
|
@ -36,6 +37,7 @@ type introspectionRemote struct {
|
|||
|
||||
var _ = (Service)(&introspectionRemote{})
|
||||
|
||||
// NewIntrospectionServiceFromClient creates a new introspection service from an API client
|
||||
func NewIntrospectionServiceFromClient(c api.IntrospectionClient) Service {
|
||||
return &introspectionRemote{client: c}
|
||||
}
|
||||
|
|
4
vendor/github.com/containerd/containerd/services/introspection/local.go
generated
vendored
4
vendor/github.com/containerd/containerd/services/introspection/local.go
generated
vendored
|
@ -54,6 +54,7 @@ func init() {
|
|||
})
|
||||
}
|
||||
|
||||
// Local is a local implementation of the introspection service
|
||||
type Local struct {
|
||||
mu sync.Mutex
|
||||
plugins []api.Plugin
|
||||
|
@ -62,6 +63,7 @@ type Local struct {
|
|||
|
||||
var _ = (api.IntrospectionClient)(&Local{})
|
||||
|
||||
// UpdateLocal updates the local introspection service
|
||||
func (l *Local) UpdateLocal(root string, plugins []api.Plugin) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
|
@ -69,6 +71,7 @@ func (l *Local) UpdateLocal(root string, plugins []api.Plugin) {
|
|||
l.plugins = plugins
|
||||
}
|
||||
|
||||
// Plugins returns the locally defined plugins
|
||||
func (l *Local) Plugins(ctx context.Context, req *api.PluginsRequest, _ ...grpc.CallOption) (*api.PluginsResponse, error) {
|
||||
filter, err := filters.ParseAll(req.Filters...)
|
||||
if err != nil {
|
||||
|
@ -96,6 +99,7 @@ func (l *Local) getPlugins() []api.Plugin {
|
|||
return l.plugins
|
||||
}
|
||||
|
||||
// Server returns the local server information
|
||||
func (l *Local) Server(ctx context.Context, _ *ptypes.Empty, _ ...grpc.CallOption) (*api.ServerResponse, error) {
|
||||
u, err := l.getUUID()
|
||||
if err != nil {
|
||||
|
|
27
vendor/github.com/containerd/containerd/services/server/config/config.go
generated
vendored
27
vendor/github.com/containerd/containerd/services/server/config/config.go
generated
vendored
|
@ -20,9 +20,10 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/imdario/mergo"
|
||||
"github.com/pelletier/go-toml"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/plugin"
|
||||
|
@ -55,7 +56,7 @@ type Config struct {
|
|||
// required plugin doesn't exist or fails to be initialized or started.
|
||||
RequiredPlugins []string `toml:"required_plugins"`
|
||||
// Plugins provides plugin specific configuration for the initialization of a plugin
|
||||
Plugins map[string]toml.Primitive `toml:"plugins"`
|
||||
Plugins map[string]toml.Tree `toml:"plugins"`
|
||||
// OOMScore adjust the containerd's oom score
|
||||
OOMScore int `toml:"oom_score"`
|
||||
// Cgroup specifies cgroup information for the containerd daemon process
|
||||
|
@ -94,7 +95,9 @@ func (c *Config) GetVersion() int {
|
|||
|
||||
// ValidateV2 validates the config for a v2 file
|
||||
func (c *Config) ValidateV2() error {
|
||||
if c.GetVersion() != 2 {
|
||||
version := c.GetVersion()
|
||||
if version < 2 {
|
||||
logrus.Warnf("deprecated version : `%d`, please switch to version `2`", version)
|
||||
return nil
|
||||
}
|
||||
for _, p := range c.DisabledPlugins {
|
||||
|
@ -209,7 +212,7 @@ func (c *Config) Decode(p *plugin.Registration) (interface{}, error) {
|
|||
if !ok {
|
||||
return p.Config, nil
|
||||
}
|
||||
if err := toml.PrimitiveDecode(data, p.Config); err != nil {
|
||||
if err := data.Unmarshal(p.Config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.Config, nil
|
||||
|
@ -258,16 +261,26 @@ func LoadConfig(path string, out *Config) error {
|
|||
out.Imports = append(out.Imports, path)
|
||||
}
|
||||
|
||||
return out.ValidateV2()
|
||||
err := out.ValidateV2()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to load TOML from %s", path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadConfigFile decodes a TOML file at the given path
|
||||
func loadConfigFile(path string) (*Config, error) {
|
||||
config := &Config{}
|
||||
_, err := toml.DecodeFile(path, &config)
|
||||
|
||||
file, err := toml.LoadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrapf(err, "failed to load TOML: %s", path)
|
||||
}
|
||||
|
||||
if err := file.Unmarshal(config); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal TOML")
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
|
|
3
vendor/github.com/containerd/containerd/snapshots/snapshotter.go
generated
vendored
3
vendor/github.com/containerd/containerd/snapshots/snapshotter.go
generated
vendored
|
@ -28,7 +28,8 @@ import (
|
|||
const (
|
||||
// UnpackKeyPrefix is the beginning of the key format used for snapshots that will have
|
||||
// image content unpacked into them.
|
||||
UnpackKeyPrefix = "extract"
|
||||
UnpackKeyPrefix = "extract"
|
||||
// UnpackKeyFormat is the format for the snapshotter keys used for extraction
|
||||
UnpackKeyFormat = UnpackKeyPrefix + "-%s %s"
|
||||
inheritedLabelsPrefix = "containerd.io/snapshot/"
|
||||
labelSnapshotRef = "containerd.io/snapshot.ref"
|
||||
|
|
35
vendor/github.com/containerd/containerd/sys/filesys.go
generated
vendored
35
vendor/github.com/containerd/containerd/sys/filesys.go
generated
vendored
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sys
|
||||
|
||||
import "os"
|
||||
|
||||
// IsFifo checks if a file is a (named pipe) fifo
|
||||
// if the file does not exist then it returns false
|
||||
func IsFifo(path string) (bool, error) {
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
if stat.Mode()&os.ModeNamedPipe == os.ModeNamedPipe {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
72
vendor/github.com/containerd/containerd/sys/filesys_windows.go
generated
vendored
72
vendor/github.com/containerd/containerd/sys/filesys_windows.go
generated
vendored
|
@ -22,11 +22,14 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
|
@ -257,12 +260,71 @@ func windowsOpenSequential(path string, mode int, _ uint32) (fd windows.Handle,
|
|||
return h, e
|
||||
}
|
||||
|
||||
// ForceRemoveAll is the same as os.RemoveAll, but uses hcsshim.DestroyLayer in order
|
||||
// to delete container layers.
|
||||
// ForceRemoveAll is the same as os.RemoveAll, but is aware of io.containerd.snapshotter.v1.windows
|
||||
// and uses hcsshim to unmount and delete container layers contained therein, in the correct order,
|
||||
// when passed a containerd root data directory (i.e. the `--root` directory for containerd).
|
||||
func ForceRemoveAll(path string) error {
|
||||
info := hcsshim.DriverInfo{
|
||||
HomeDir: filepath.Dir(path),
|
||||
// snapshots/windows/windows.go init()
|
||||
const snapshotPlugin = "io.containerd.snapshotter.v1" + "." + "windows"
|
||||
// snapshots/windows/windows.go NewSnapshotter()
|
||||
snapshotDir := filepath.Join(path, snapshotPlugin, "snapshots")
|
||||
if stat, err := os.Stat(snapshotDir); err == nil && stat.IsDir() {
|
||||
if err := cleanupWCOWLayers(snapshotDir); err != nil {
|
||||
return errors.Wrapf(err, "failed to cleanup WCOW layers in %s", snapshotDir)
|
||||
}
|
||||
}
|
||||
|
||||
return hcsshim.DestroyLayer(info, filepath.Base(path))
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
|
||||
func cleanupWCOWLayers(root string) error {
|
||||
// See snapshots/windows/windows.go getSnapshotDir()
|
||||
var layerNums []int
|
||||
if err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
if path != root && info.IsDir() {
|
||||
if layerNum, err := strconv.Atoi(filepath.Base(path)); err == nil {
|
||||
layerNums = append(layerNums, layerNum)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sort.Sort(sort.Reverse(sort.IntSlice(layerNums)))
|
||||
|
||||
for _, layerNum := range layerNums {
|
||||
if err := cleanupWCOWLayer(filepath.Join(root, strconv.Itoa(layerNum))); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func cleanupWCOWLayer(layerPath string) error {
|
||||
info := hcsshim.DriverInfo{
|
||||
HomeDir: filepath.Dir(layerPath),
|
||||
}
|
||||
|
||||
// ERROR_DEV_NOT_EXIST is returned if the layer is not currently prepared.
|
||||
if err := hcsshim.UnprepareLayer(info, filepath.Base(layerPath)); err != nil {
|
||||
if hcserror, ok := err.(*hcsshim.HcsError); !ok || hcserror.Err != windows.ERROR_DEV_NOT_EXIST {
|
||||
return errors.Wrapf(err, "failed to unprepare %s", layerPath)
|
||||
}
|
||||
}
|
||||
|
||||
if err := hcsshim.DeactivateLayer(info, filepath.Base(layerPath)); err != nil {
|
||||
return errors.Wrapf(err, "failed to deactivate %s", layerPath)
|
||||
}
|
||||
|
||||
if err := hcsshim.DestroyLayer(info, filepath.Base(layerPath)); err != nil {
|
||||
return errors.Wrapf(err, "failed to destroy %s", layerPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
|
@ -24,17 +22,34 @@ import (
|
|||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/pkg/userns"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
// OOMScoreMaxKillable is the maximum score keeping the process killable by the oom killer
|
||||
OOMScoreMaxKillable = -999
|
||||
// OOMScoreAdjMax is from OOM_SCORE_ADJ_MAX https://github.com/torvalds/linux/blob/master/include/uapi/linux/oom.h
|
||||
// OOMScoreAdjMin is from OOM_SCORE_ADJ_MIN https://github.com/torvalds/linux/blob/v5.10/include/uapi/linux/oom.h#L9
|
||||
OOMScoreAdjMin = -1000
|
||||
// OOMScoreAdjMax is from OOM_SCORE_ADJ_MAX https://github.com/torvalds/linux/blob/v5.10/include/uapi/linux/oom.h#L10
|
||||
OOMScoreAdjMax = 1000
|
||||
)
|
||||
|
||||
// AdjustOOMScore sets the oom score for the provided pid. If the provided score
|
||||
// is out of range (-1000 - 1000), it is clipped to the min/max value.
|
||||
func AdjustOOMScore(pid, score int) error {
|
||||
if score > OOMScoreAdjMax {
|
||||
score = OOMScoreAdjMax
|
||||
} else if score < OOMScoreAdjMin {
|
||||
score = OOMScoreAdjMin
|
||||
}
|
||||
return SetOOMScore(pid, score)
|
||||
}
|
||||
|
||||
// SetOOMScore sets the oom score for the provided pid
|
||||
func SetOOMScore(pid, score int) error {
|
||||
if score > OOMScoreAdjMax || score < OOMScoreAdjMin {
|
||||
return fmt.Errorf("value out of range (%d): OOM score must be between %d and %d", score, OOMScoreAdjMin, OOMScoreAdjMax)
|
||||
}
|
||||
path := fmt.Sprintf("/proc/%d/oom_score_adj", pid)
|
||||
f, err := os.OpenFile(path, os.O_WRONLY, 0)
|
||||
if err != nil {
|
||||
|
@ -42,7 +57,7 @@ func SetOOMScore(pid, score int) error {
|
|||
}
|
||||
defer f.Close()
|
||||
if _, err = f.WriteString(strconv.Itoa(score)); err != nil {
|
||||
if os.IsPermission(err) && (RunningInUserNS() || RunningUnprivileged()) {
|
||||
if os.IsPermission(err) && (!runningPrivileged() || userns.RunningInUserNS()) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
|
@ -50,7 +65,8 @@ func SetOOMScore(pid, score int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetOOMScoreAdj gets the oom score for a process
|
||||
// GetOOMScoreAdj gets the oom score for a process. It returns 0 (zero) if either
|
||||
// no oom score is set, or a sore is set to 0.
|
||||
func GetOOMScoreAdj(pid int) (int, error) {
|
||||
path := fmt.Sprintf("/proc/%d/oom_score_adj", pid)
|
||||
data, err := ioutil.ReadFile(path)
|
||||
|
@ -59,3 +75,9 @@ func GetOOMScoreAdj(pid int) (int, error) {
|
|||
}
|
||||
return strconv.Atoi(strings.TrimSpace(string(data)))
|
||||
}
|
||||
|
||||
// runningPrivileged returns true if the effective user ID of the
|
||||
// calling process is 0
|
||||
func runningPrivileged() bool {
|
||||
return unix.Geteuid() == 0
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
// +build !linux
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
|
@ -17,10 +19,20 @@
|
|||
package sys
|
||||
|
||||
const (
|
||||
// OOMScoreAdjMax is not implemented on Windows
|
||||
// OOMScoreMaxKillable is not implemented on non Linux
|
||||
OOMScoreMaxKillable = 0
|
||||
// OOMScoreAdjMax is not implemented on non Linux
|
||||
OOMScoreAdjMax = 0
|
||||
)
|
||||
|
||||
// AdjustOOMScore sets the oom score for the provided pid. If the provided score
|
||||
// is out of range (-1000 - 1000), it is clipped to the min/max value.
|
||||
//
|
||||
// Not implemented on Windows
|
||||
func AdjustOOMScore(pid, score int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetOOMScore sets the oom score for the process
|
||||
//
|
||||
// Not implemented on Windows
|
|
@ -1,5 +1,3 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
|
@ -18,16 +16,8 @@
|
|||
|
||||
package sys
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
import "github.com/containerd/containerd/pkg/userns"
|
||||
|
||||
// RunningPrivileged returns true if the effective user ID of the
|
||||
// calling process is 0
|
||||
func RunningPrivileged() bool {
|
||||
return unix.Geteuid() == 0
|
||||
}
|
||||
|
||||
// RunningUnprivileged returns true if the effective user ID of the
|
||||
// calling process is not 0
|
||||
func RunningUnprivileged() bool {
|
||||
return !RunningPrivileged()
|
||||
}
|
||||
// RunningInUserNS detects whether we are currently running in a user namespace.
|
||||
// Deprecated: use github.com/containerd/containerd/pkg/userns.RunningInUserNS instead.
|
||||
var RunningInUserNS = userns.RunningInUserNS
|
15
vendor/github.com/containerd/containerd/task.go
generated
vendored
15
vendor/github.com/containerd/containerd/task.go
generated
vendored
|
@ -451,11 +451,20 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag
|
|||
}
|
||||
request.Options = any
|
||||
}
|
||||
// make sure we pause it and resume after all other filesystem operations are completed
|
||||
if err := t.Pause(ctx); err != nil {
|
||||
|
||||
status, err := t.Status(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer t.Resume(ctx)
|
||||
|
||||
if status.Status != Paused {
|
||||
// make sure we pause it and resume after all other filesystem operations are completed
|
||||
if err := t.Pause(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer t.Resume(ctx)
|
||||
}
|
||||
|
||||
index := v1.Index{
|
||||
Versioned: is.Versioned{
|
||||
SchemaVersion: 2,
|
||||
|
|
2
vendor/github.com/containerd/containerd/version/version.go
generated
vendored
2
vendor/github.com/containerd/containerd/version/version.go
generated
vendored
|
@ -23,7 +23,7 @@ var (
|
|||
Package = "github.com/containerd/containerd"
|
||||
|
||||
// Version holds the complete version number. Filled in at linking time.
|
||||
Version = "1.5.0-beta.0+unknown"
|
||||
Version = "1.5.2+unknown"
|
||||
|
||||
// Revision is filled with the VCS (e.g. git) revision being used to build
|
||||
// the program at linking time.
|
||||
|
|
Loading…
Reference in a new issue