diff --git a/hack/versions b/hack/versions index 802c507fb..6bd92e350 100644 --- a/hack/versions +++ b/hack/versions @@ -1,6 +1,6 @@ -RUNC_VERSION=74a17296470088de3805e138d3d87c62e613dfc4 +RUNC_VERSION=7f24b40cc5423969b4554ef04ba0b00e2b4ba010 CNI_VERSION=v0.6.0 -CONTAINERD_VERSION=6c7abf7c76c1973d4fb4b0bad51691de84869a51 +CONTAINERD_VERSION=90553efdef0678b2609aed74926a487f8ff58d1a CONTAINERD_REPO= CRITOOL_VERSION=v1.0.0-alpha.0 KUBERNETES_VERSION=v1.9.0 diff --git a/pkg/server/io/container_io.go b/pkg/server/io/container_io.go index 65c500bbe..0c7504b9b 100644 --- a/pkg/server/io/container_io.go +++ b/pkg/server/io/container_io.go @@ -19,7 +19,6 @@ package io import ( "errors" "io" - "os" "strings" "sync" @@ -116,12 +115,7 @@ func NewContainerIO(id string, opts ...ContainerIOOpts) (_ *ContainerIO, err err // Config returns io config. func (c *ContainerIO) Config() cio.Config { - return cio.Config{ - Terminal: c.fifos.Terminal, - Stdin: c.fifos.In, - Stdout: c.fifos.Out, - Stderr: c.fifos.Err, - } + return c.fifos.Config } // Pipe creates container fifos and pipe container output @@ -239,7 +233,7 @@ func (c *ContainerIO) Wait() { func (c *ContainerIO) Close() error { c.closer.Close() if c.fifos != nil { - return os.RemoveAll(c.fifos.Dir) + return c.fifos.Close() } return nil } diff --git a/pkg/server/io/exec_io.go b/pkg/server/io/exec_io.go index fc02636ed..72c36b6bc 100644 --- a/pkg/server/io/exec_io.go +++ b/pkg/server/io/exec_io.go @@ -18,7 +18,6 @@ package io import ( "io" - "os" "sync" "github.com/containerd/containerd/cio" @@ -57,12 +56,7 @@ func NewExecIO(id, root string, tty, stdin bool) (*ExecIO, error) { // Config returns io config. func (e *ExecIO) Config() cio.Config { - return cio.Config{ - Terminal: e.fifos.Terminal, - Stdin: e.fifos.In, - Stdout: e.fifos.Out, - Stderr: e.fifos.Err, - } + return e.fifos.Config } // Attach attaches exec stdio. The logic is similar with container io attach. @@ -146,7 +140,7 @@ func (e *ExecIO) Close() error { e.closer.Close() } if e.fifos != nil { - return os.RemoveAll(e.fifos.Dir) + return e.fifos.Close() } return nil } diff --git a/pkg/server/io/helpers.go b/pkg/server/io/helpers.go index e0ddc2de5..221b96e38 100644 --- a/pkg/server/io/helpers.go +++ b/pkg/server/io/helpers.go @@ -18,7 +18,6 @@ package io import ( "io" - "io/ioutil" "os" "path/filepath" "sync" @@ -80,19 +79,12 @@ func newFifos(root, id string, tty, stdin bool) (*cio.FIFOSet, error) { if err := os.MkdirAll(root, 0700); err != nil { return nil, err } - dir, err := ioutil.TempDir(root, "") + fifos, err := cio.NewFIFOSetInDir(root, id, tty) if err != nil { return nil, err } - fifos := &cio.FIFOSet{ - Dir: dir, - In: filepath.Join(dir, id+"-stdin"), - Out: filepath.Join(dir, id+"-stdout"), - Err: filepath.Join(dir, id+"-stderr"), - Terminal: tty, - } if !stdin { - fifos.In = "" + fifos.Stdin = "" } return fifos, nil } @@ -120,21 +112,21 @@ func newStdioPipes(fifos *cio.FIFOSet) (_ *stdioPipes, _ *wgCloser, err error) { } }() - if fifos.In != "" { - if f, err = fifo.OpenFifo(ctx, fifos.In, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { + if fifos.Stdin != "" { + if f, err = fifo.OpenFifo(ctx, fifos.Stdin, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { return nil, nil, err } p.stdin = f set = append(set, f) } - if f, err = fifo.OpenFifo(ctx, fifos.Out, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { + if f, err = fifo.OpenFifo(ctx, fifos.Stdout, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { return nil, nil, err } p.stdout = f set = append(set, f) - if f, err = fifo.OpenFifo(ctx, fifos.Err, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { + if f, err = fifo.OpenFifo(ctx, fifos.Stderr, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { return nil, nil, err } p.stderr = f diff --git a/vendor.conf b/vendor.conf index 791b3f46f..3fa058419 100644 --- a/vendor.conf +++ b/vendor.conf @@ -1,7 +1,7 @@ github.com/blang/semver v3.1.0 github.com/BurntSushi/toml v0.2.0-21-g9906417 github.com/containerd/cgroups 29da22c6171a4316169f9205ab6c49f59b5b852f -github.com/containerd/containerd 6c7abf7c76c1973d4fb4b0bad51691de84869a51 +github.com/containerd/containerd 90553efdef0678b2609aed74926a487f8ff58d1a github.com/containerd/continuity cf279e6ac893682272b4479d4c67fd3abf878b4e github.com/containerd/fifo fbfb6a11ec671efbe94ad1c12c2e98773f19e1e6 github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788 @@ -35,11 +35,11 @@ github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 github.com/json-iterator/go 13f86432b882000a51c6e610c620974462691a97 github.com/juju/ratelimit 5b9ff866471762aa2ab2dced63c9fb6f53921342 github.com/mailru/easyjson d5b7844b561a7bc640052f1b935f7b800330d7e0 -github.com/Microsoft/go-winio v0.4.4 +github.com/Microsoft/go-winio v0.4.5 github.com/opencontainers/go-digest 21dfd564fd89c944783d00d069f33e3e7123c448 -github.com/opencontainers/image-spec v1.0.0 -github.com/opencontainers/runc 74a17296470088de3805e138d3d87c62e613dfc4 -github.com/opencontainers/runtime-spec v1.0.0 +github.com/opencontainers/image-spec v1.0.1 +github.com/opencontainers/runc 7f24b40cc5423969b4554ef04ba0b00e2b4ba010 +github.com/opencontainers/runtime-spec v1.0.1 github.com/opencontainers/runtime-tools 6073aff4ac61897f75895123f7e24135204a404d github.com/opencontainers/selinux 4a2974bf1ee960774ffd517717f1f45325af0206 github.com/peterbourgon/diskv v2.0.1 @@ -60,7 +60,7 @@ golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c golang.org/x/sys 314a259e304ff91bd6985da2a7149bbf91237993 https://github.com/golang/sys golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 -google.golang.org/grpc v1.7.2 +google.golang.org/grpc v1.7.4 gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 gopkg.in/yaml.v2 53feefa2559fb8dfa8d81baad31be332c97d6c77 k8s.io/api 9382f5a87a364c195477134986b578d103c7c24d diff --git a/vendor/github.com/Microsoft/go-winio/backup.go b/vendor/github.com/Microsoft/go-winio/backup.go index 27d6ace0c..2be34af43 100644 --- a/vendor/github.com/Microsoft/go-winio/backup.go +++ b/vendor/github.com/Microsoft/go-winio/backup.go @@ -68,10 +68,20 @@ func NewBackupStreamReader(r io.Reader) *BackupStreamReader { return &BackupStreamReader{r, 0} } -// Next returns the next backup stream and prepares for calls to Write(). It skips the remainder of the current stream if +// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if // it was not completely read. func (r *BackupStreamReader) Next() (*BackupHeader, error) { if r.bytesLeft > 0 { + if s, ok := r.r.(io.Seeker); ok { + // Make sure Seek on io.SeekCurrent sometimes succeeds + // before trying the actual seek. + if _, err := s.Seek(0, io.SeekCurrent); err == nil { + if _, err = s.Seek(r.bytesLeft, io.SeekCurrent); err != nil { + return nil, err + } + r.bytesLeft = 0 + } + } if _, err := io.Copy(ioutil.Discard, r); err != nil { return nil, err } @@ -220,7 +230,7 @@ type BackupFileWriter struct { ctx uintptr } -// NewBackupFileWrtier returns a new BackupFileWriter from a file handle. If includeSecurity is true, +// NewBackupFileWriter returns a new BackupFileWriter from a file handle. If includeSecurity is true, // Write() will attempt to restore the security descriptor from the stream. func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter { w := &BackupFileWriter{f, includeSecurity, 0} diff --git a/vendor/github.com/Microsoft/go-winio/ea.go b/vendor/github.com/Microsoft/go-winio/ea.go new file mode 100644 index 000000000..b37e930d6 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/ea.go @@ -0,0 +1,137 @@ +package winio + +import ( + "bytes" + "encoding/binary" + "errors" +) + +type fileFullEaInformation struct { + NextEntryOffset uint32 + Flags uint8 + NameLength uint8 + ValueLength uint16 +} + +var ( + fileFullEaInformationSize = binary.Size(&fileFullEaInformation{}) + + errInvalidEaBuffer = errors.New("invalid extended attribute buffer") + errEaNameTooLarge = errors.New("extended attribute name too large") + errEaValueTooLarge = errors.New("extended attribute value too large") +) + +// ExtendedAttribute represents a single Windows EA. +type ExtendedAttribute struct { + Name string + Value []byte + Flags uint8 +} + +func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { + var info fileFullEaInformation + err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info) + if err != nil { + err = errInvalidEaBuffer + return + } + + nameOffset := fileFullEaInformationSize + nameLen := int(info.NameLength) + valueOffset := nameOffset + int(info.NameLength) + 1 + valueLen := int(info.ValueLength) + nextOffset := int(info.NextEntryOffset) + if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) { + err = errInvalidEaBuffer + return + } + + ea.Name = string(b[nameOffset : nameOffset+nameLen]) + ea.Value = b[valueOffset : valueOffset+valueLen] + ea.Flags = info.Flags + if info.NextEntryOffset != 0 { + nb = b[info.NextEntryOffset:] + } + return +} + +// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION +// buffer retrieved from BackupRead, ZwQueryEaFile, etc. +func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) { + for len(b) != 0 { + ea, nb, err := parseEa(b) + if err != nil { + return nil, err + } + + eas = append(eas, ea) + b = nb + } + return +} + +func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error { + if int(uint8(len(ea.Name))) != len(ea.Name) { + return errEaNameTooLarge + } + if int(uint16(len(ea.Value))) != len(ea.Value) { + return errEaValueTooLarge + } + entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value)) + withPadding := (entrySize + 3) &^ 3 + nextOffset := uint32(0) + if !last { + nextOffset = withPadding + } + info := fileFullEaInformation{ + NextEntryOffset: nextOffset, + Flags: ea.Flags, + NameLength: uint8(len(ea.Name)), + ValueLength: uint16(len(ea.Value)), + } + + err := binary.Write(buf, binary.LittleEndian, &info) + if err != nil { + return err + } + + _, err = buf.Write([]byte(ea.Name)) + if err != nil { + return err + } + + err = buf.WriteByte(0) + if err != nil { + return err + } + + _, err = buf.Write(ea.Value) + if err != nil { + return err + } + + _, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize]) + if err != nil { + return err + } + + return nil +} + +// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION +// buffer for use with BackupWrite, ZwSetEaFile, etc. +func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) { + var buf bytes.Buffer + for i := range eas { + last := false + if i == len(eas)-1 { + last = true + } + + err := writeEa(&buf, &eas[i], last) + if err != nil { + return nil, err + } + } + return buf.Bytes(), nil +} diff --git a/vendor/github.com/Microsoft/go-winio/file.go b/vendor/github.com/Microsoft/go-winio/file.go index 2a311d1f2..57ac3696a 100644 --- a/vendor/github.com/Microsoft/go-winio/file.go +++ b/vendor/github.com/Microsoft/go-winio/file.go @@ -78,6 +78,7 @@ func initIo() { type win32File struct { handle syscall.Handle wg sync.WaitGroup + wgLock sync.RWMutex closing atomicBool readDeadline deadlineHandler writeDeadline deadlineHandler @@ -114,14 +115,18 @@ func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) { // closeHandle closes the resources associated with a Win32 handle func (f *win32File) closeHandle() { + f.wgLock.Lock() // Atomically set that we are closing, releasing the resources only once. if !f.closing.swap(true) { + f.wgLock.Unlock() // cancel all IO and wait for it to complete cancelIoEx(f.handle, nil) f.wg.Wait() // at this point, no new IO can start syscall.Close(f.handle) f.handle = 0 + } else { + f.wgLock.Unlock() } } @@ -134,10 +139,13 @@ func (f *win32File) Close() error { // prepareIo prepares for a new IO operation. // The caller must call f.wg.Done() when the IO is finished, prior to Close() returning. func (f *win32File) prepareIo() (*ioOperation, error) { + f.wgLock.RLock() if f.closing.isSet() { + f.wgLock.RUnlock() return nil, ErrFileClosed } f.wg.Add(1) + f.wgLock.RUnlock() c := &ioOperation{} c.ch = make(chan ioResult) return c, nil diff --git a/vendor/github.com/Microsoft/go-winio/pipe.go b/vendor/github.com/Microsoft/go-winio/pipe.go index da706cc8a..44340b816 100644 --- a/vendor/github.com/Microsoft/go-winio/pipe.go +++ b/vendor/github.com/Microsoft/go-winio/pipe.go @@ -265,9 +265,9 @@ func (l *win32PipeListener) listenerRoutine() { if err == nil { // Wait for the client to connect. ch := make(chan error) - go func() { + go func(p *win32File) { ch <- connectPipe(p) - }() + }(p) select { case err = <-ch: if err != nil { diff --git a/vendor/github.com/containerd/containerd/README.md b/vendor/github.com/containerd/containerd/README.md index 84d1eec8a..d76ce1b2c 100644 --- a/vendor/github.com/containerd/containerd/README.md +++ b/vendor/github.com/containerd/containerd/README.md @@ -4,6 +4,7 @@ [![Build Status](https://travis-ci.org/containerd/containerd.svg?branch=master)](https://travis-ci.org/containerd/containerd) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fcontainerd%2Fcontainerd.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fcontainerd%2Fcontainerd?ref=badge_shield) [![Go Report Card](https://goreportcard.com/badge/github.com/containerd/containerd)](https://goreportcard.com/report/github.com/containerd/containerd) +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1271/badge)](https://bestpractices.coreinfrastructure.org/projects/1271) containerd is an industry-standard container runtime with an emphasis on simplicity, robustness and portability. It is available as a daemon for Linux and Windows, which can manage the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments, etc. @@ -13,7 +14,7 @@ containerd is designed to be embedded into a larger system, rather than being us ## Getting Started -See our documentation on [containerd.io](containerd.io): +See our documentation on [containerd.io](https://containerd.io): * [for ops and admins](docs/ops.md) * [namespaces](docs/namespaces.md) * [client options](docs/client-opts.md) diff --git a/vendor/github.com/containerd/containerd/cio/io.go b/vendor/github.com/containerd/containerd/cio/io.go index 25e398147..1b4a4dc25 100644 --- a/vendor/github.com/containerd/containerd/cio/io.go +++ b/vendor/github.com/containerd/containerd/cio/io.go @@ -8,7 +8,7 @@ import ( "sync" ) -// Config holds the io configurations. +// Config holds the IO configurations. type Config struct { // Terminal is true if one has been allocated Terminal bool @@ -24,48 +24,17 @@ type Config struct { type IO interface { // Config returns the IO configuration. Config() Config - // Cancel aborts all current io operations + // Cancel aborts all current io operations. Cancel() - // Wait blocks until all io copy operations have completed + // Wait blocks until all io copy operations have completed. Wait() - // Close cleans up all open io resources + // Close cleans up all open io resources. Cancel() is always called before + // Close() Close() error } -// cio is a basic container IO implementation. -type cio struct { - config Config - - closer *wgCloser -} - -func (c *cio) Config() Config { - return c.config -} - -func (c *cio) Cancel() { - if c.closer == nil { - return - } - c.closer.Cancel() -} - -func (c *cio) Wait() { - if c.closer == nil { - return - } - c.closer.Wait() -} - -func (c *cio) Close() error { - if c.closer == nil { - return nil - } - return c.closer.Close() -} - -// Creation creates new IO sets for a task -type Creation func(id string) (IO, error) +// Creator creates new IO sets for a task +type Creator func(id string) (IO, error) // Attach allows callers to reattach to running tasks // @@ -74,123 +43,138 @@ type Creation func(id string) (IO, error) // will be sent only to the first reads type Attach func(*FIFOSet) (IO, error) -// NewIO returns an Creation that will provide IO sets without a terminal -func NewIO(stdin io.Reader, stdout, stderr io.Writer) Creation { - return NewIOWithTerminal(stdin, stdout, stderr, false) -} - -// NewIOWithTerminal creates a new io set with the provied io.Reader/Writers for use with a terminal -func NewIOWithTerminal(stdin io.Reader, stdout, stderr io.Writer, terminal bool) Creation { - return func(id string) (_ IO, err error) { - paths, err := NewFifos(id) - if err != nil { - return nil, err - } - defer func() { - if err != nil && paths.Dir != "" { - os.RemoveAll(paths.Dir) - } - }() - cfg := Config{ - Terminal: terminal, - Stdout: paths.Out, - Stderr: paths.Err, - Stdin: paths.In, - } - i := &cio{config: cfg} - set := &ioSet{ - in: stdin, - out: stdout, - err: stderr, - } - closer, err := copyIO(paths, set, cfg.Terminal) - if err != nil { - return nil, err - } - i.closer = closer - return i, nil - } -} - -// WithAttach attaches the existing io for a task to the provided io.Reader/Writers -func WithAttach(stdin io.Reader, stdout, stderr io.Writer) Attach { - return func(paths *FIFOSet) (IO, error) { - if paths == nil { - return nil, fmt.Errorf("cannot attach to existing fifos") - } - cfg := Config{ - Terminal: paths.Terminal, - Stdout: paths.Out, - Stderr: paths.Err, - Stdin: paths.In, - } - i := &cio{config: cfg} - set := &ioSet{ - in: stdin, - out: stdout, - err: stderr, - } - closer, err := copyIO(paths, set, cfg.Terminal) - if err != nil { - return nil, err - } - i.closer = closer - return i, nil - } -} - -// Stdio returns an IO set to be used for a task -// that outputs the container's IO as the current processes Stdio -func Stdio(id string) (IO, error) { - return NewIO(os.Stdin, os.Stdout, os.Stderr)(id) -} - -// StdioTerminal will setup the IO for the task to use a terminal -func StdioTerminal(id string) (IO, error) { - return NewIOWithTerminal(os.Stdin, os.Stdout, os.Stderr, true)(id) -} - -// NullIO redirects the container's IO into /dev/null -func NullIO(id string) (IO, error) { - return &cio{}, nil -} - -// FIFOSet is a set of fifos for use with tasks +// FIFOSet is a set of file paths to FIFOs for a task's standard IO streams type FIFOSet struct { - // Dir is the directory holding the task fifos - Dir string - // In, Out, and Err fifo paths - In, Out, Err string - // Terminal returns true if a terminal is being used for the task - Terminal bool + Config + close func() error } -type ioSet struct { - in io.Reader - out, err io.Writer -} - -type wgCloser struct { - wg *sync.WaitGroup - dir string - set []io.Closer - cancel context.CancelFunc -} - -func (g *wgCloser) Wait() { - g.wg.Wait() -} - -func (g *wgCloser) Close() error { - for _, f := range g.set { - f.Close() - } - if g.dir != "" { - return os.RemoveAll(g.dir) +// Close the FIFOSet +func (f *FIFOSet) Close() error { + if f.close != nil { + return f.close() } return nil } -func (g *wgCloser) Cancel() { - g.cancel() +// NewFIFOSet returns a new FIFOSet from a Config and a close function +func NewFIFOSet(config Config, close func() error) *FIFOSet { + return &FIFOSet{Config: config, close: close} } + +// Streams used to configure a Creator or Attach +type Streams struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer + Terminal bool +} + +// Opt customize options for creating a Creator or Attach +type Opt func(*Streams) + +// WithStdio sets stream options to the standard input/output streams +func WithStdio(opt *Streams) { + WithStreams(os.Stdin, os.Stdout, os.Stderr)(opt) +} + +// WithTerminal sets the terminal option +func WithTerminal(opt *Streams) { + opt.Terminal = true +} + +// WithStreams sets the stream options to the specified Reader and Writers +func WithStreams(stdin io.Reader, stdout, stderr io.Writer) Opt { + return func(opt *Streams) { + opt.Stdin = stdin + opt.Stdout = stdout + opt.Stderr = stderr + } +} + +// NewCreator returns an IO creator from the options +func NewCreator(opts ...Opt) Creator { + streams := &Streams{} + for _, opt := range opts { + opt(streams) + } + return func(id string) (IO, error) { + // TODO: accept root as a param + root := "/run/containerd/fifo" + fifos, err := NewFIFOSetInDir(root, id, streams.Terminal) + if err != nil { + return nil, err + } + return copyIO(fifos, streams) + } +} + +// NewAttach attaches the existing io for a task to the provided io.Reader/Writers +func NewAttach(opts ...Opt) Attach { + streams := &Streams{} + for _, opt := range opts { + opt(streams) + } + return func(fifos *FIFOSet) (IO, error) { + if fifos == nil { + return nil, fmt.Errorf("cannot attach, missing fifos") + } + return copyIO(fifos, streams) + } +} + +// NullIO redirects the container's IO into /dev/null +func NullIO(_ string) (IO, error) { + return &cio{}, nil +} + +// cio is a basic container IO implementation. +type cio struct { + config Config + wg *sync.WaitGroup + closers []io.Closer + cancel context.CancelFunc +} + +func (c *cio) Config() Config { + return c.config +} + +func (c *cio) Wait() { + if c.wg != nil { + c.wg.Wait() + } +} + +func (c *cio) Close() error { + var lastErr error + for _, closer := range c.closers { + if closer == nil { + continue + } + if err := closer.Close(); err != nil { + lastErr = err + } + } + return lastErr +} + +func (c *cio) Cancel() { + if c.cancel != nil { + c.cancel() + } +} + +type pipes struct { + Stdin io.WriteCloser + Stdout io.ReadCloser + Stderr io.ReadCloser +} + +// DirectIO allows task IO to be handled externally by the caller +type DirectIO struct { + pipes + cio +} + +var _ IO = &DirectIO{} diff --git a/vendor/github.com/containerd/containerd/cio/io_unix.go b/vendor/github.com/containerd/containerd/cio/io_unix.go index c18f7ecf9..005fb0ce9 100644 --- a/vendor/github.com/containerd/containerd/cio/io_unix.go +++ b/vendor/github.com/containerd/containerd/cio/io_unix.go @@ -12,173 +12,115 @@ import ( "syscall" "github.com/containerd/fifo" + "github.com/pkg/errors" ) -// NewFifos returns a new set of fifos for the task -func NewFifos(id string) (*FIFOSet, error) { - root := "/run/containerd/fifo" - if err := os.MkdirAll(root, 0700); err != nil { - return nil, err +// NewFIFOSetInDir returns a new FIFOSet with paths in a temporary directory under root +func NewFIFOSetInDir(root, id string, terminal bool) (*FIFOSet, error) { + if root != "" { + if err := os.MkdirAll(root, 0700); err != nil { + return nil, err + } } dir, err := ioutil.TempDir(root, "") if err != nil { return nil, err } - return &FIFOSet{ - Dir: dir, - In: filepath.Join(dir, id+"-stdin"), - Out: filepath.Join(dir, id+"-stdout"), - Err: filepath.Join(dir, id+"-stderr"), - }, nil + closer := func() error { + return os.RemoveAll(dir) + } + return NewFIFOSet(Config{ + Stdin: filepath.Join(dir, id+"-stdin"), + Stdout: filepath.Join(dir, id+"-stdout"), + Stderr: filepath.Join(dir, id+"-stderr"), + Terminal: terminal, + }, closer), nil } -func copyIO(fifos *FIFOSet, ioset *ioSet, tty bool) (_ *wgCloser, err error) { - var ( - f io.ReadWriteCloser - set []io.Closer - ctx, cancel = context.WithCancel(context.Background()) - wg = &sync.WaitGroup{} - ) - defer func() { - if err != nil { - for _, f := range set { - f.Close() - } - cancel() - } - }() - - if f, err = fifo.OpenFifo(ctx, fifos.In, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - return nil, err - } - set = append(set, f) - go func(w io.WriteCloser) { - io.Copy(w, ioset.in) - w.Close() - }(f) - - if f, err = fifo.OpenFifo(ctx, fifos.Out, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - return nil, err - } - set = append(set, f) - wg.Add(1) - go func(r io.ReadCloser) { - io.Copy(ioset.out, r) - r.Close() - wg.Done() - }(f) - - if f, err = fifo.OpenFifo(ctx, fifos.Err, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - return nil, err - } - set = append(set, f) - - if !tty { - wg.Add(1) - go func(r io.ReadCloser) { - io.Copy(ioset.err, r) - r.Close() - wg.Done() - }(f) - } - return &wgCloser{ - wg: wg, - dir: fifos.Dir, - set: set, - cancel: cancel, - }, nil -} - -// NewDirectIO returns an IO implementation that exposes the pipes directly -func NewDirectIO(ctx context.Context, terminal bool) (*DirectIO, error) { - set, err := NewFifos("") +func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { + var ctx, cancel = context.WithCancel(context.Background()) + pipes, err := openFifos(ctx, fifos) if err != nil { + cancel() return nil, err } - f := &DirectIO{ - set: set, - terminal: terminal, + + if fifos.Stdin != "" { + go func() { + io.Copy(pipes.Stdin, ioset.Stdin) + pipes.Stdin.Close() + }() } + + var wg = &sync.WaitGroup{} + wg.Add(1) + go func() { + io.Copy(ioset.Stdout, pipes.Stdout) + pipes.Stdout.Close() + wg.Done() + }() + + if !fifos.Terminal { + wg.Add(1) + go func() { + io.Copy(ioset.Stderr, pipes.Stderr) + pipes.Stderr.Close() + wg.Done() + }() + } + return &cio{ + config: fifos.Config, + wg: wg, + closers: append(pipes.closers(), fifos), + cancel: cancel, + }, nil +} + +func openFifos(ctx context.Context, fifos *FIFOSet) (pipes, error) { + var err error defer func() { if err != nil { - f.Delete() + fifos.Close() } }() - if f.Stdin, err = fifo.OpenFifo(ctx, set.In, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - return nil, err + + 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.Stdout, err = fifo.OpenFifo(ctx, set.Out, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - f.Stdin.Close() - return nil, err + if fifos.Stdout != "" { + if f.Stdout, err = fifo.OpenFifo(ctx, fifos.Stdout, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { + f.Stdin.Close() + return f, errors.Wrapf(err, "failed to open stdout fifo") + } } - if f.Stderr, err = fifo.OpenFifo(ctx, set.Err, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - f.Stdin.Close() - f.Stdout.Close() - return nil, err + if fifos.Stderr != "" { + if f.Stderr, err = fifo.OpenFifo(ctx, fifos.Stderr, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { + f.Stdin.Close() + f.Stdout.Close() + return f, errors.Wrapf(err, "failed to open stderr fifo") + } } return f, nil } -// DirectIO allows task IO to be handled externally by the caller -type DirectIO struct { - Stdin io.WriteCloser - Stdout io.ReadCloser - Stderr io.ReadCloser - - set *FIFOSet - terminal bool +// NewDirectIO returns an IO implementation that exposes the IO streams as io.ReadCloser +// and io.WriteCloser. +func NewDirectIO(ctx context.Context, fifos *FIFOSet) (*DirectIO, error) { + ctx, cancel := context.WithCancel(ctx) + pipes, err := openFifos(ctx, fifos) + return &DirectIO{ + pipes: pipes, + cio: cio{ + config: fifos.Config, + closers: append(pipes.closers(), fifos), + cancel: cancel, + }, + }, err } -// IOCreate returns IO avaliable for use with task creation -func (f *DirectIO) IOCreate(id string) (IO, error) { - return f, nil -} - -// IOAttach returns IO avaliable for use with task attachment -func (f *DirectIO) IOAttach(set *FIFOSet) (IO, error) { - return f, nil -} - -// Config returns the Config -func (f *DirectIO) Config() Config { - return Config{ - Terminal: f.terminal, - Stdin: f.set.In, - Stdout: f.set.Out, - Stderr: f.set.Err, - } -} - -// Cancel stops any IO copy operations -// -// Not applicable for DirectIO -func (f *DirectIO) Cancel() { - // nothing to cancel as all operations are handled externally -} - -// Wait on any IO copy operations -// -// Not applicable for DirectIO -func (f *DirectIO) Wait() { - // nothing to wait on as all operations are handled externally -} - -// Close closes all open fds -func (f *DirectIO) Close() error { - err := f.Stdin.Close() - if err2 := f.Stdout.Close(); err == nil { - err = err2 - } - if err2 := f.Stderr.Close(); err == nil { - err = err2 - } - return err -} - -// Delete removes the underlying directory containing fifos -func (f *DirectIO) Delete() error { - if f.set.Dir == "" { - return nil - } - return os.RemoveAll(f.set.Dir) +func (p *pipes) closers() []io.Closer { + return []io.Closer{p.Stdin, p.Stdout, p.Stderr} } diff --git a/vendor/github.com/containerd/containerd/cio/io_windows.go b/vendor/github.com/containerd/containerd/cio/io_windows.go index 1458c3173..017c9a11f 100644 --- a/vendor/github.com/containerd/containerd/cio/io_windows.go +++ b/vendor/github.com/containerd/containerd/cio/io_windows.go @@ -13,25 +13,26 @@ import ( const pipeRoot = `\\.\pipe` -// NewFifos returns a new set of fifos for the task -func NewFifos(id string) (*FIFOSet, error) { - return &FIFOSet{ - In: fmt.Sprintf(`%s\ctr-%s-stdin`, pipeRoot, id), - Out: fmt.Sprintf(`%s\ctr-%s-stdout`, pipeRoot, id), - Err: fmt.Sprintf(`%s\ctr-%s-stderr`, pipeRoot, id), - }, nil +// NewFIFOSetInDir returns a new set of fifos for the task +func NewFIFOSetInDir(_, id string, terminal bool) (*FIFOSet, error) { + return NewFIFOSet(Config{ + Terminal: terminal, + Stdin: fmt.Sprintf(`%s\ctr-%s-stdin`, pipeRoot, id), + Stdout: fmt.Sprintf(`%s\ctr-%s-stdout`, pipeRoot, id), + Stderr: fmt.Sprintf(`%s\ctr-%s-stderr`, pipeRoot, id), + }, nil), nil } -func copyIO(fifos *FIFOSet, ioset *ioSet, tty bool) (_ *wgCloser, err error) { +func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) { var ( wg sync.WaitGroup set []io.Closer ) - if fifos.In != "" { - l, err := winio.ListenPipe(fifos.In, nil) + 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.In) + return nil, errors.Wrapf(err, "failed to create stdin pipe %s", fifos.Stdin) } defer func(l net.Listener) { if err != nil { @@ -43,19 +44,19 @@ func copyIO(fifos *FIFOSet, ioset *ioSet, tty bool) (_ *wgCloser, err error) { go func() { c, err := l.Accept() if err != nil { - log.L.WithError(err).Errorf("failed to accept stdin connection on %s", fifos.In) + log.L.WithError(err).Errorf("failed to accept stdin connection on %s", fifos.Stdin) return } - io.Copy(c, ioset.in) + io.Copy(c, ioset.Stdin) c.Close() l.Close() }() } - if fifos.Out != "" { - l, err := winio.ListenPipe(fifos.Out, nil) + if fifos.Stdout != "" { + l, err := winio.ListenPipe(fifos.Stdout, nil) if err != nil { - return nil, errors.Wrapf(err, "failed to create stdin pipe %s", fifos.Out) + return nil, errors.Wrapf(err, "failed to create stdin pipe %s", fifos.Stdout) } defer func(l net.Listener) { if err != nil { @@ -69,19 +70,19 @@ func copyIO(fifos *FIFOSet, ioset *ioSet, tty bool) (_ *wgCloser, err error) { defer wg.Done() c, err := l.Accept() if err != nil { - log.L.WithError(err).Errorf("failed to accept stdout connection on %s", fifos.Out) + log.L.WithError(err).Errorf("failed to accept stdout connection on %s", fifos.Stdout) return } - io.Copy(ioset.out, c) + io.Copy(ioset.Stdout, c) c.Close() l.Close() }() } - if !tty && fifos.Err != "" { - l, err := winio.ListenPipe(fifos.Err, nil) + if !fifos.Terminal && fifos.Stderr != "" { + l, err := winio.ListenPipe(fifos.Stderr, nil) if err != nil { - return nil, errors.Wrapf(err, "failed to create stderr pipe %s", fifos.Err) + return nil, errors.Wrapf(err, "failed to create stderr pipe %s", fifos.Stderr) } defer func(l net.Listener) { if err != nil { @@ -95,23 +96,29 @@ func copyIO(fifos *FIFOSet, ioset *ioSet, tty bool) (_ *wgCloser, err error) { defer wg.Done() c, err := l.Accept() if err != nil { - log.L.WithError(err).Errorf("failed to accept stderr connection on %s", fifos.Err) + log.L.WithError(err).Errorf("failed to accept stderr connection on %s", fifos.Stderr) return } - io.Copy(ioset.err, c) + io.Copy(ioset.Stderr, c) c.Close() l.Close() }() } - return &wgCloser{ - wg: &wg, - dir: fifos.Dir, - set: set, - cancel: func() { - for _, l := range set { - l.Close() - } - }, - }, nil + return &cio{config: fifos.Config, closers: set}, nil +} + +// NewDirectIO returns an IO implementation that exposes the IO streams as io.ReadCloser +// and io.WriteCloser. +func NewDirectIO(stdin io.WriteCloser, stdout, stderr io.ReadCloser, terminal bool) *DirectIO { + return &DirectIO{ + pipes: pipes{ + Stdin: stdin, + Stdout: stdout, + Stderr: stderr, + }, + cio: cio{ + config: Config{Terminal: terminal}, + }, + } } diff --git a/vendor/github.com/containerd/containerd/container.go b/vendor/github.com/containerd/containerd/container.go index 716e0456c..ad60c69ea 100644 --- a/vendor/github.com/containerd/containerd/container.go +++ b/vendor/github.com/containerd/containerd/container.go @@ -3,6 +3,7 @@ package containerd import ( "context" "encoding/json" + "os" "path/filepath" "strings" @@ -26,7 +27,7 @@ type Container interface { // Delete removes the container Delete(context.Context, ...DeleteOpts) error // NewTask creates a new task based on the container metadata - NewTask(context.Context, cio.Creation, ...NewTaskOpts) (Task, error) + NewTask(context.Context, cio.Creator, ...NewTaskOpts) (Task, error) // Spec returns the OCI runtime specification Spec(context.Context) (*specs.Spec, error) // Task returns the current task for the container @@ -162,7 +163,7 @@ func (c *container) Image(ctx context.Context) (Image, error) { }, nil } -func (c *container) NewTask(ctx context.Context, ioCreate cio.Creation, opts ...NewTaskOpts) (_ Task, err error) { +func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...NewTaskOpts) (_ Task, err error) { i, err := ioCreate(c.id) if err != nil { return nil, err @@ -288,20 +289,23 @@ func (c *container) get(ctx context.Context) (containers.Container, error) { return c.client.ContainerService().Get(ctx, c.id) } +// get the existing fifo paths from the task information stored by the daemon func attachExistingIO(response *tasks.GetResponse, ioAttach cio.Attach) (cio.IO, error) { - // get the existing fifo paths from the task information stored by the daemon - paths := &cio.FIFOSet{ - Dir: getFifoDir([]string{ - response.Process.Stdin, - response.Process.Stdout, - response.Process.Stderr, - }), - In: response.Process.Stdin, - Out: response.Process.Stdout, - Err: response.Process.Stderr, - Terminal: response.Process.Terminal, + path := getFifoDir([]string{ + response.Process.Stdin, + response.Process.Stdout, + response.Process.Stderr, + }) + closer := func() error { + return os.RemoveAll(path) } - return ioAttach(paths) + fifoSet := cio.NewFIFOSet(cio.Config{ + Stdin: response.Process.Stdin, + Stdout: response.Process.Stdout, + Stderr: response.Process.Stderr, + Terminal: response.Process.Terminal, + }, closer) + return ioAttach(fifoSet) } // getFifoDir looks for any non-empty path for a stdio fifo diff --git a/vendor/github.com/containerd/containerd/container_opts_unix.go b/vendor/github.com/containerd/containerd/container_opts_unix.go index b678033b7..deda0f70f 100644 --- a/vendor/github.com/containerd/containerd/container_opts_unix.go +++ b/vendor/github.com/containerd/containerd/container_opts_unix.go @@ -6,7 +6,6 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" "syscall" @@ -16,6 +15,7 @@ import ( "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" + "github.com/containerd/containerd/linux/runctypes" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/platforms" "github.com/gogo/protobuf/proto" @@ -166,7 +166,7 @@ func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool if err != nil { return err } - if err := remapRootFS(mounts, uid, gid); err != nil { + if err := remapRootFS(ctx, mounts, uid, gid); err != nil { snapshotter.Remove(ctx, usernsID) return err } @@ -187,22 +187,10 @@ func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool } } -func remapRootFS(mounts []mount.Mount, uid, gid uint32) error { - root, err := ioutil.TempDir("", "ctd-remap") - if err != nil { - return err - } - defer os.Remove(root) - for _, m := range mounts { - if err := m.Mount(root); err != nil { - return err - } - } - err = filepath.Walk(root, incrementFS(root, uid, gid)) - if uerr := mount.Unmount(root, 0); err == nil { - err = uerr - } - return err +func remapRootFS(ctx context.Context, mounts []mount.Mount, uid, gid uint32) error { + return mount.WithTempMount(ctx, mounts, func(root string) error { + return filepath.Walk(root, incrementFS(root, uid, gid)) + }) } func incrementFS(root string, uidInc, gidInc uint32) filepath.WalkFunc { @@ -218,3 +206,19 @@ func incrementFS(root string, uidInc, gidInc uint32) filepath.WalkFunc { return os.Lchown(path, u, g) } } + +// WithNoPivotRoot instructs the runtime not to you pivot_root +func WithNoPivotRoot(_ context.Context, _ *Client, info *TaskInfo) error { + if info.Options == nil { + info.Options = &runctypes.CreateOptions{ + NoPivotRoot: true, + } + return nil + } + copts, ok := info.Options.(*runctypes.CreateOptions) + if !ok { + return errors.New("invalid options type, expected runctypes.CreateOptions") + } + copts.NoPivotRoot = true + return nil +} diff --git a/vendor/github.com/containerd/containerd/events/events.go b/vendor/github.com/containerd/containerd/events/events.go index 2bfedb1e8..6f4c8b3af 100644 --- a/vendor/github.com/containerd/containerd/events/events.go +++ b/vendor/github.com/containerd/containerd/events/events.go @@ -26,9 +26,9 @@ func (e *Envelope) Field(fieldpath []string) (string, bool) { switch fieldpath[0] { // unhandled: timestamp case "namespace": - return string(e.Namespace), len(e.Namespace) > 0 + return e.Namespace, len(e.Namespace) > 0 case "topic": - return string(e.Topic), len(e.Topic) > 0 + return e.Topic, len(e.Topic) > 0 case "event": decoded, err := typeurl.UnmarshalAny(e.Event) if err != nil { diff --git a/vendor/github.com/containerd/containerd/fs/diff.go b/vendor/github.com/containerd/containerd/fs/diff.go index 3a53f4215..9073d0d92 100644 --- a/vendor/github.com/containerd/containerd/fs/diff.go +++ b/vendor/github.com/containerd/containerd/fs/diff.go @@ -222,10 +222,8 @@ func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b string) (err c1 = make(chan *currentPath) c2 = make(chan *currentPath) - f1, f2 *currentPath - rmdir string - lastEmittedDir = string(filepath.Separator) - parents []os.FileInfo + f1, f2 *currentPath + rmdir string ) g.Go(func() error { defer close(c1) @@ -260,10 +258,7 @@ func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b string) (err continue } - var ( - f os.FileInfo - emit = true - ) + var f os.FileInfo k, p := pathChange(f1, f2) switch k { case ChangeKindAdd: @@ -299,35 +294,13 @@ func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b string) (err f2 = nil if same { if !isLinked(f) { - emit = false + continue } k = ChangeKindUnmodified } } - if emit { - emittedDir, emitParents := commonParents(lastEmittedDir, p, parents) - for _, pf := range emitParents { - p := filepath.Join(emittedDir, pf.Name()) - if err := changeFn(ChangeKindUnmodified, p, pf, nil); err != nil { - return err - } - emittedDir = p - } - - if err := changeFn(k, p, f, nil); err != nil { - return err - } - - if f != nil && f.IsDir() { - lastEmittedDir = p - } else { - lastEmittedDir = emittedDir - } - - parents = parents[:0] - } else if f.IsDir() { - lastEmittedDir, parents = commonParents(lastEmittedDir, p, parents) - parents = append(parents, f) + if err := changeFn(k, p, f, nil); err != nil { + return err } } return nil @@ -335,47 +308,3 @@ func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b string) (err return g.Wait() } - -func commonParents(base, updated string, dirs []os.FileInfo) (string, []os.FileInfo) { - if basePrefix := makePrefix(base); strings.HasPrefix(updated, basePrefix) { - var ( - parents []os.FileInfo - last = base - ) - for _, d := range dirs { - next := filepath.Join(last, d.Name()) - if strings.HasPrefix(updated, makePrefix(last)) { - parents = append(parents, d) - last = next - } else { - break - } - } - return base, parents - } - - baseS := strings.Split(base, string(filepath.Separator)) - updatedS := strings.Split(updated, string(filepath.Separator)) - commonS := []string{string(filepath.Separator)} - - min := len(baseS) - if len(updatedS) < min { - min = len(updatedS) - } - for i := 0; i < min; i++ { - if baseS[i] == updatedS[i] { - commonS = append(commonS, baseS[i]) - } else { - break - } - } - - return filepath.Join(commonS...), []os.FileInfo{} -} - -func makePrefix(d string) string { - if d == "" || d[len(d)-1] != filepath.Separator { - return d + string(filepath.Separator) - } - return d -} diff --git a/vendor/github.com/containerd/containerd/fs/du_unix.go b/vendor/github.com/containerd/containerd/fs/du_unix.go index 6328e80f3..fe3426d27 100644 --- a/vendor/github.com/containerd/containerd/fs/du_unix.go +++ b/vendor/github.com/containerd/containerd/fs/du_unix.go @@ -15,6 +15,15 @@ type inode struct { dev, ino uint64 } +func newInode(stat *syscall.Stat_t) inode { + return inode{ + // Dev is uint32 on darwin/bsd, uint64 on linux/solaris + dev: uint64(stat.Dev), // nolint: unconvert + // Ino is uint32 on bsd, uint64 on darwin/linux/solaris + ino: uint64(stat.Ino), // nolint: unconvert + } +} + func diskUsage(roots ...string) (Usage, error) { var ( @@ -28,9 +37,7 @@ func diskUsage(roots ...string) (Usage, error) { return err } - stat := fi.Sys().(*syscall.Stat_t) - - inoKey := inode{dev: uint64(stat.Dev), ino: uint64(stat.Ino)} + inoKey := newInode(fi.Sys().(*syscall.Stat_t)) if _, ok := inodes[inoKey]; !ok { inodes[inoKey] = struct{}{} size += fi.Size() @@ -60,9 +67,7 @@ func diffUsage(ctx context.Context, a, b string) (Usage, error) { } if kind == ChangeKindAdd || kind == ChangeKindModify { - stat := fi.Sys().(*syscall.Stat_t) - - inoKey := inode{dev: uint64(stat.Dev), ino: uint64(stat.Ino)} + inoKey := newInode(fi.Sys().(*syscall.Stat_t)) if _, ok := inodes[inoKey]; !ok { inodes[inoKey] = struct{}{} size += fi.Size() diff --git a/vendor/github.com/containerd/containerd/fs/hardlink_unix.go b/vendor/github.com/containerd/containerd/fs/hardlink_unix.go index 3b825c940..a6f99778d 100644 --- a/vendor/github.com/containerd/containerd/fs/hardlink_unix.go +++ b/vendor/github.com/containerd/containerd/fs/hardlink_unix.go @@ -13,5 +13,6 @@ func getLinkInfo(fi os.FileInfo) (uint64, bool) { return 0, false } - return uint64(s.Ino), !fi.IsDir() && s.Nlink > 1 + // Ino is uint32 on bsd, uint64 on darwin/linux/solaris + return uint64(s.Ino), !fi.IsDir() && s.Nlink > 1 // nolint: unconvert } diff --git a/vendor/github.com/containerd/containerd/fs/path.go b/vendor/github.com/containerd/containerd/fs/path.go index 412da6711..13fb82638 100644 --- a/vendor/github.com/containerd/containerd/fs/path.go +++ b/vendor/github.com/containerd/containerd/fs/path.go @@ -71,9 +71,9 @@ func sameFile(f1, f2 *currentPath) (bool, error) { return false, nil } - // If the timestamp may have been truncated in one of the + // If the timestamp may have been truncated in both of the // files, check content of file to determine difference - if t1.Nanosecond() == 0 || t2.Nanosecond() == 0 { + if t1.Nanosecond() == 0 && t2.Nanosecond() == 0 { var eq bool if (f1.f.Mode() & os.ModeSymlink) == os.ModeSymlink { eq, err = compareSymlinkTarget(f1.fullPath, f2.fullPath) diff --git a/vendor/github.com/containerd/containerd/images/image.go b/vendor/github.com/containerd/containerd/images/image.go index 7b4215faf..3f58e0620 100644 --- a/vendor/github.com/containerd/containerd/images/image.go +++ b/vendor/github.com/containerd/containerd/images/image.go @@ -357,13 +357,5 @@ func RootFS(ctx context.Context, provider content.Provider, configDesc ocispec.D if err := json.Unmarshal(p, &config); err != nil { return nil, err } - - // TODO(stevvooe): Remove this bit when OCI structure uses correct type for - // rootfs.DiffIDs. - var diffIDs []digest.Digest - for _, diffID := range config.RootFS.DiffIDs { - diffIDs = append(diffIDs, digest.Digest(diffID)) - } - - return diffIDs, nil + return config.RootFS.DiffIDs, nil } diff --git a/vendor/github.com/containerd/containerd/mount/mount.go b/vendor/github.com/containerd/containerd/mount/mount.go index 94c2c9f92..323e6e2fb 100644 --- a/vendor/github.com/containerd/containerd/mount/mount.go +++ b/vendor/github.com/containerd/containerd/mount/mount.go @@ -1,5 +1,14 @@ package mount +import ( + "context" + "io/ioutil" + "os" + + "github.com/containerd/containerd/log" + "github.com/pkg/errors" +) + // Mount is the lingua franca of containerd. A mount represents a // serialized mount syscall. Components either emit or consume mounts. type Mount struct { @@ -22,3 +31,42 @@ func All(mounts []Mount, target string) error { } return nil } + +// WithTempMount mounts the provided mounts to a temp dir, and pass the temp dir to f. +// The mounts are valid during the call to the f. +// Finally we will unmount and remove the temp dir regardless of the result of f. +func WithTempMount(ctx context.Context, mounts []Mount, f func(root string) error) (err error) { + root, uerr := ioutil.TempDir("", "containerd-WithTempMount") + if uerr != nil { + return errors.Wrapf(uerr, "failed to create temp dir") + } + // We use Remove here instead of RemoveAll. + // The RemoveAll will delete the temp dir and all children it contains. + // When the Unmount fails, RemoveAll will incorrectly delete data from + // the mounted dir. However, if we use Remove, even though we won't + // successfully delete the temp dir and it may leak, we won't loss data + // from the mounted dir. + // For details, please refer to #1868 #1785. + defer func() { + if uerr = os.Remove(root); uerr != nil { + log.G(ctx).WithError(uerr).WithField("dir", root).Errorf("failed to remove mount temp dir") + } + }() + + // We should do defer first, if not we will not do Unmount when only a part of Mounts are failed. + defer func() { + if uerr = UnmountAll(root, 0); uerr != nil { + uerr = errors.Wrapf(uerr, "failed to unmount %s", root) + if err == nil { + err = uerr + } else { + err = errors.Wrap(err, uerr.Error()) + } + } + }() + if uerr = All(mounts, root); uerr != nil { + return errors.Wrapf(uerr, "failed to mount %s", root) + } + + return errors.Wrapf(f(root), "mount callback failed on %s", root) +} diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go b/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go index 865aff29a..ebc423d3e 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go +++ b/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go @@ -6,7 +6,6 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" "strconv" @@ -271,49 +270,35 @@ func WithUserID(uid uint32) SpecOpts { if err != nil { return err } - root, err := ioutil.TempDir("", "ctd-username") - if err != nil { - return err - } - defer os.Remove(root) - for _, m := range mounts { - if err := m.Mount(root); err != nil { + + return mount.WithTempMount(ctx, mounts, func(root string) error { + ppath, err := fs.RootPath(root, "/etc/passwd") + if err != nil { return err } - } - defer func() { - if uerr := mount.Unmount(root, 0); uerr != nil { - if err == nil { - err = uerr + f, err := os.Open(ppath) + if err != nil { + if os.IsNotExist(err) { + s.Process.User.UID, s.Process.User.GID = uid, uid + return nil } + return err } - }() - ppath, err := fs.RootPath(root, "/etc/passwd") - if err != nil { - return err - } - f, err := os.Open(ppath) - if err != nil { - if os.IsNotExist(err) { + defer f.Close() + users, err := user.ParsePasswdFilter(f, func(u user.User) bool { + return u.Uid == int(uid) + }) + if err != nil { + return err + } + if len(users) == 0 { s.Process.User.UID, s.Process.User.GID = uid, uid return nil } - return err - } - defer f.Close() - users, err := user.ParsePasswdFilter(f, func(u user.User) bool { - return u.Uid == int(uid) - }) - if err != nil { - return err - } - if len(users) == 0 { - s.Process.User.UID, s.Process.User.GID = uid, uid + u := users[0] + s.Process.User.UID, s.Process.User.GID = uint32(u.Uid), uint32(u.Gid) return nil - } - u := users[0] - s.Process.User.UID, s.Process.User.GID = uint32(u.Uid), uint32(u.Gid) - return nil + }) } } @@ -334,43 +319,28 @@ func WithUsername(username string) SpecOpts { if err != nil { return err } - root, err := ioutil.TempDir("", "ctd-username") - if err != nil { - return err - } - defer os.Remove(root) - for _, m := range mounts { - if err := m.Mount(root); err != nil { + return mount.WithTempMount(ctx, mounts, func(root string) error { + ppath, err := fs.RootPath(root, "/etc/passwd") + if err != nil { return err } - } - defer func() { - if uerr := mount.Unmount(root, 0); uerr != nil { - if err == nil { - err = uerr - } + f, err := os.Open(ppath) + if err != nil { + return err } - }() - ppath, err := fs.RootPath(root, "/etc/passwd") - if err != nil { - return err - } - f, err := os.Open(ppath) - if err != nil { - return err - } - defer f.Close() - users, err := user.ParsePasswdFilter(f, func(u user.User) bool { - return u.Name == username + defer f.Close() + users, err := user.ParsePasswdFilter(f, func(u user.User) bool { + return u.Name == username + }) + if err != nil { + return err + } + if len(users) == 0 { + return errors.Errorf("no users found for %s", username) + } + u := users[0] + s.Process.User.UID, s.Process.User.GID = uint32(u.Uid), uint32(u.Gid) + return nil }) - if err != nil { - return err - } - if len(users) == 0 { - return errors.Errorf("no users found for %s", username) - } - u := users[0] - s.Process.User.UID, s.Process.User.GID = uint32(u.Uid), uint32(u.Gid) - return nil } } diff --git a/vendor/github.com/containerd/containerd/platforms/cpuinfo.go b/vendor/github.com/containerd/containerd/platforms/cpuinfo.go new file mode 100644 index 000000000..b7c23cc19 --- /dev/null +++ b/vendor/github.com/containerd/containerd/platforms/cpuinfo.go @@ -0,0 +1,85 @@ +package platforms + +import ( + "bufio" + "os" + "runtime" + "strings" + + "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" + "github.com/pkg/errors" +) + +// Present the ARM instruction set architecture, eg: v7, v8 +var cpuVariant string + +func init() { + if isArmArch(runtime.GOARCH) { + cpuVariant = getCPUVariant() + } else { + cpuVariant = "" + } +} + +// For Linux, the kernel has already detected the ABI, ISA and Features. +// So we don't need to access the ARM registers to detect platform information +// by ourselves. We can just parse these information from /proc/cpuinfo +func getCPUInfo(pattern string) (info string, err error) { + if !isLinuxOS(runtime.GOOS) { + return "", errors.Wrapf(errdefs.ErrNotImplemented, "getCPUInfo for OS %s", runtime.GOOS) + } + + cpuinfo, err := os.Open("/proc/cpuinfo") + if err != nil { + return "", err + } + defer cpuinfo.Close() + + // Start to Parse the Cpuinfo line by line. For SMP SoC, we parse + // the first core is enough. + scanner := bufio.NewScanner(cpuinfo) + for scanner.Scan() { + newline := scanner.Text() + list := strings.Split(newline, ":") + + if len(list) > 1 && strings.EqualFold(strings.TrimSpace(list[0]), pattern) { + return strings.TrimSpace(list[1]), nil + } + } + + // Check whether the scanner encountered errors + err = scanner.Err() + if err != nil { + return "", err + } + + return "", errors.Wrapf(errdefs.ErrNotFound, "getCPUInfo for pattern: %s", pattern) +} + +func getCPUVariant() string { + variant, err := getCPUInfo("Cpu architecture") + if err != nil { + log.L.WithError(err).Error("failure getting variant") + return "" + } + + switch variant { + case "8": + variant = "v8" + case "7", "7M", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)": + variant = "v7" + case "6", "6TEJ": + variant = "v6" + case "5", "5T", "5TE", "5TEJ": + variant = "v5" + case "4", "4T": + variant = "v4" + case "3": + variant = "v3" + default: + variant = "unknown" + } + + return variant +} diff --git a/vendor/github.com/containerd/containerd/platforms/database.go b/vendor/github.com/containerd/containerd/platforms/database.go index bd66e2517..362b005a6 100644 --- a/vendor/github.com/containerd/containerd/platforms/database.go +++ b/vendor/github.com/containerd/containerd/platforms/database.go @@ -5,6 +5,13 @@ import ( "strings" ) +// isLinuxOS returns true if the operating system is Linux. +// +// The OS value should be normalized before calling this function. +func isLinuxOS(os string) bool { + return os == "linux" +} + // These function are generated from from https://golang.org/src/go/build/syslist.go. // // We use switch statements because they are slightly faster than map lookups @@ -21,6 +28,17 @@ func isKnownOS(os string) bool { return false } +// isArmArch returns true if the architecture is ARM. +// +// The arch value should be normalized before being passed to this function. +func isArmArch(arch string) bool { + switch arch { + case "arm", "arm64": + return true + } + return false +} + // isKnownArch returns true if we know about the architecture. // // The arch value should be normalized before being passed to this function. diff --git a/vendor/github.com/containerd/containerd/platforms/defaults.go b/vendor/github.com/containerd/containerd/platforms/defaults.go index 2b57b4979..ed493ab2c 100644 --- a/vendor/github.com/containerd/containerd/platforms/defaults.go +++ b/vendor/github.com/containerd/containerd/platforms/defaults.go @@ -16,6 +16,7 @@ func DefaultSpec() specs.Platform { return specs.Platform{ OS: runtime.GOOS, Architecture: runtime.GOARCH, - // TODO(stevvooe): Need to resolve GOARM for arm hosts. + // The Variant field will be empty if arch != ARM. + Variant: cpuVariant, } } diff --git a/vendor/github.com/containerd/containerd/process.go b/vendor/github.com/containerd/containerd/process.go index ad1a2a1f4..32049cf07 100644 --- a/vendor/github.com/containerd/containerd/process.go +++ b/vendor/github.com/containerd/containerd/process.go @@ -191,6 +191,7 @@ func (p *process) Delete(ctx context.Context, opts ...ProcessDeleteOpts) (*ExitS return nil, errdefs.FromGRPC(err) } if p.io != nil { + p.io.Cancel() p.io.Wait() p.io.Close() } diff --git a/vendor/github.com/containerd/containerd/remotes/hints.go b/vendor/github.com/containerd/containerd/remotes/hints.go deleted file mode 100644 index 1694477a5..000000000 --- a/vendor/github.com/containerd/containerd/remotes/hints.go +++ /dev/null @@ -1,31 +0,0 @@ -package remotes - -import "strings" - -// HintExists returns true if a hint of the provided kind and values exists in -// the set of provided hints. -func HintExists(kind, value string, hints ...string) bool { - for _, hint := range hints { - if strings.HasPrefix(hint, kind) && strings.HasSuffix(hint, value) { - return true - } - } - - return false -} - -// HintValues returns a slice of the values of the hints that match kind. -func HintValues(kind string, hints ...string) []string { - var values []string - for _, hint := range hints { - if strings.HasPrefix(hint, kind) { - parts := strings.SplitN(hint, ":", 2) - if len(parts) < 2 { - continue - } - values = append(values, parts[1]) - } - } - - return values -} diff --git a/vendor/github.com/containerd/containerd/rootfs/diff.go b/vendor/github.com/containerd/containerd/rootfs/diff.go index bab7a3cca..89ed71d03 100644 --- a/vendor/github.com/containerd/containerd/rootfs/diff.go +++ b/vendor/github.com/containerd/containerd/rootfs/diff.go @@ -39,7 +39,7 @@ func Diff(ctx context.Context, snapshotID string, sn snapshots.Snapshotter, d di if err != nil { return ocispec.Descriptor{}, err } - defer sn.Remove(ctx, lowerKey) + defer sn.Remove(ctx, upperKey) } return d.DiffMounts(ctx, lower, upper, opts...) diff --git a/vendor/github.com/containerd/containerd/sys/stat_bsd.go b/vendor/github.com/containerd/containerd/sys/stat_bsd.go index e043ae52b..84c59ab6f 100644 --- a/vendor/github.com/containerd/containerd/sys/stat_bsd.go +++ b/vendor/github.com/containerd/containerd/sys/stat_bsd.go @@ -4,6 +4,7 @@ package sys import ( "syscall" + "time" ) // StatAtime returns the access time from a stat struct @@ -20,3 +21,8 @@ func StatCtime(st *syscall.Stat_t) syscall.Timespec { func StatMtime(st *syscall.Stat_t) syscall.Timespec { return st.Mtimespec } + +// StatATimeAsTime returns the access time as a time.Time +func StatATimeAsTime(st *syscall.Stat_t) time.Time { + return time.Unix(int64(st.Atimespec.Sec), int64(st.Atimespec.Nsec)) // nolint: unconvert +} diff --git a/vendor/github.com/containerd/containerd/sys/stat_unix.go b/vendor/github.com/containerd/containerd/sys/stat_unix.go index 1f983a98d..799b9b997 100644 --- a/vendor/github.com/containerd/containerd/sys/stat_unix.go +++ b/vendor/github.com/containerd/containerd/sys/stat_unix.go @@ -4,6 +4,7 @@ package sys import ( "syscall" + "time" ) // StatAtime returns the Atim @@ -20,3 +21,8 @@ func StatCtime(st *syscall.Stat_t) syscall.Timespec { func StatMtime(st *syscall.Stat_t) syscall.Timespec { return st.Mtim } + +// StatATimeAsTime returns st.Atim as a time.Time +func StatATimeAsTime(st *syscall.Stat_t) time.Time { + return time.Unix(st.Atim.Sec, st.Atim.Nsec) +} diff --git a/vendor/github.com/containerd/containerd/task.go b/vendor/github.com/containerd/containerd/task.go index 8d256834f..121da9af5 100644 --- a/vendor/github.com/containerd/containerd/task.go +++ b/vendor/github.com/containerd/containerd/task.go @@ -123,7 +123,7 @@ type Task interface { // Resume the execution of the task Resume(context.Context) error // Exec creates a new process inside the task - Exec(context.Context, string, *specs.Process, cio.Creation) (Process, error) + Exec(context.Context, string, *specs.Process, cio.Creator) (Process, error) // Pids returns a list of system specific process ids inside the task Pids(context.Context) ([]ProcessInfo, error) // Checkpoint serializes the runtime and memory information of a task into an @@ -163,6 +163,7 @@ func (t *task) Start(ctx context.Context) error { ContainerID: t.id, }) if err != nil { + t.io.Cancel() t.io.Close() return errdefs.FromGRPC(err) } @@ -277,7 +278,7 @@ func (t *task) Delete(ctx context.Context, opts ...ProcessDeleteOpts) (*ExitStat return &ExitStatus{code: r.ExitStatus, exitedAt: r.ExitedAt}, nil } -func (t *task) Exec(ctx context.Context, id string, spec *specs.Process, ioCreate cio.Creation) (_ Process, err error) { +func (t *task) Exec(ctx context.Context, id string, spec *specs.Process, ioCreate cio.Creator) (_ Process, err error) { if id == "" { return nil, errors.Wrapf(errdefs.ErrInvalidArgument, "exec id must not be empty") } diff --git a/vendor/github.com/containerd/containerd/vendor.conf b/vendor/github.com/containerd/containerd/vendor.conf index fea47e480..a185cd7b7 100644 --- a/vendor/github.com/containerd/containerd/vendor.conf +++ b/vendor/github.com/containerd/containerd/vendor.conf @@ -15,8 +15,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.0 github.com/docker/go-units v0.3.1 github.com/gogo/protobuf v0.5 github.com/golang/protobuf 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 -github.com/opencontainers/runtime-spec v1.0.0 -github.com/opencontainers/runc 74a17296470088de3805e138d3d87c62e613dfc4 +github.com/opencontainers/runtime-spec v1.0.1 +github.com/opencontainers/runc 7f24b40cc5423969b4554ef04ba0b00e2b4ba010 github.com/sirupsen/logrus v1.0.0 github.com/containerd/btrfs cc52c4dea2ce11a44e6639e561bb5c2af9ada9e3 github.com/stretchr/testify v1.1.4 @@ -25,20 +25,19 @@ github.com/pmezard/go-difflib v1.0.0 github.com/containerd/fifo fbfb6a11ec671efbe94ad1c12c2e98773f19e1e6 github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6 -google.golang.org/grpc v1.7.2 +google.golang.org/grpc v1.7.4 github.com/pkg/errors v0.8.0 github.com/opencontainers/go-digest 21dfd564fd89c944783d00d069f33e3e7123c448 golang.org/x/sys 314a259e304ff91bd6985da2a7149bbf91237993 https://github.com/golang/sys -github.com/opencontainers/image-spec v1.0.0 +github.com/opencontainers/image-spec v1.0.1 github.com/containerd/continuity cf279e6ac893682272b4479d4c67fd3abf878b4e golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c github.com/BurntSushi/toml v0.2.0-21-g9906417 github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0 -github.com/Microsoft/go-winio v0.4.4 +github.com/Microsoft/go-winio v0.4.5 github.com/Microsoft/hcsshim v0.6.7 -github.com/Microsoft/opengcs v0.3.2 github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 github.com/dmcgowan/go-tar go1.10 -github.com/stevvooe/ttrpc 76e68349ad9ab4d03d764c713826d31216715e4f +github.com/stevvooe/ttrpc d2710463e497617f16f26d1e715a3308609e7982 diff --git a/vendor/github.com/opencontainers/image-spec/README.md b/vendor/github.com/opencontainers/image-spec/README.md index 5ab5554e4..31e827865 100644 --- a/vendor/github.com/opencontainers/image-spec/README.md +++ b/vendor/github.com/opencontainers/image-spec/README.md @@ -51,7 +51,7 @@ Find more [FAQ on the OCI site](https://www.opencontainers.org/faq). ## Roadmap -The [GitHub milestones](https://github.com/opencontainers/image-spec/milestones) lay out the path to the OCI v1.0.0 release in late 2016. +The [GitHub milestones](https://github.com/opencontainers/image-spec/milestones) lay out the path to the future improvements. # Contributing diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/version.go b/vendor/github.com/opencontainers/image-spec/specs-go/version.go index e3eee29b4..5d493df23 100644 --- a/vendor/github.com/opencontainers/image-spec/specs-go/version.go +++ b/vendor/github.com/opencontainers/image-spec/specs-go/version.go @@ -22,7 +22,7 @@ const ( // VersionMinor is for functionality in a backwards-compatible manner VersionMinor = 0 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 + VersionPatch = 1 // VersionDev indicates development branch. Releases will be empty string. VersionDev = "" diff --git a/vendor/github.com/opencontainers/runc/README.md b/vendor/github.com/opencontainers/runc/README.md index eabfb982b..3ca7a1a22 100644 --- a/vendor/github.com/opencontainers/runc/README.md +++ b/vendor/github.com/opencontainers/runc/README.md @@ -56,7 +56,7 @@ make BUILDTAGS='seccomp apparmor' |-----------|------------------------------------|-------------| | seccomp | Syscall filtering | libseccomp | | selinux | selinux process and mount labeling | | -| apparmor | apparmor profile support | libapparmor | +| apparmor | apparmor profile support | | | ambient | ambient capability support | kernel 4.3 | diff --git a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go index 82ed1a68a..7fff0627f 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go @@ -2,15 +2,10 @@ package apparmor -// #cgo LDFLAGS: -lapparmor -// #include -// #include -import "C" import ( "fmt" "io/ioutil" "os" - "unsafe" ) // IsEnabled returns true if apparmor is enabled for the host. @@ -24,16 +19,36 @@ func IsEnabled() bool { return false } +func setprocattr(attr, value string) error { + // Under AppArmor you can only change your own attr, so use /proc/self/ + // instead of /proc// like libapparmor does + path := fmt.Sprintf("/proc/self/attr/%s", attr) + + f, err := os.OpenFile(path, os.O_WRONLY, 0) + if err != nil { + return err + } + defer f.Close() + + _, err = fmt.Fprintf(f, "%s", value) + return err +} + +// changeOnExec reimplements aa_change_onexec from libapparmor in Go +func changeOnExec(name string) error { + value := "exec " + name + if err := setprocattr("exec", value); err != nil { + return fmt.Errorf("apparmor failed to apply profile: %s", err) + } + return nil +} + // ApplyProfile will apply the profile with the specified name to the process after // the next exec. func ApplyProfile(name string) error { if name == "" { return nil } - cName := C.CString(name) - defer C.free(unsafe.Pointer(cName)) - if _, err := C.aa_change_onexec(cName); err != nil { - return fmt.Errorf("apparmor failed to apply profile: %s", err) - } - return nil + + return changeOnExec(name) } diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go deleted file mode 100644 index 95e2830a4..000000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go +++ /dev/null @@ -1,6 +0,0 @@ -// +build !windows,!linux,!freebsd - -package configs - -type Cgroup struct { -} diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/device_defaults.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/device_defaults.go index 4d348d217..e4f423c52 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/configs/device_defaults.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/device_defaults.go @@ -1,4 +1,4 @@ -// +build linux freebsd +// +build linux package configs diff --git a/vendor/github.com/opencontainers/runc/libcontainer/devices/devices_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/devices/devices.go similarity index 100% rename from vendor/github.com/opencontainers/runc/libcontainer/devices/devices_linux.go rename to vendor/github.com/opencontainers/runc/libcontainer/devices/devices.go diff --git a/vendor/github.com/opencontainers/runc/libcontainer/devices/devices_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/devices/devices_unsupported.go deleted file mode 100644 index 6649b9f2d..000000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/devices/devices_unsupported.go +++ /dev/null @@ -1,3 +0,0 @@ -// +build !linux - -package devices diff --git a/vendor/github.com/opencontainers/runc/libcontainer/system/sysconfig.go b/vendor/github.com/opencontainers/runc/libcontainer/system/sysconfig.go index b3a07cba3..b8434f105 100644 --- a/vendor/github.com/opencontainers/runc/libcontainer/system/sysconfig.go +++ b/vendor/github.com/opencontainers/runc/libcontainer/system/sysconfig.go @@ -1,4 +1,4 @@ -// +build cgo,linux cgo,freebsd +// +build cgo,linux package system diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unsupported.go deleted file mode 100644 index 4a8d00acb..000000000 --- a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unsupported.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris - -package user - -import ( - "io" - "syscall" -) - -func GetPasswdPath() (string, error) { - return "", ErrUnsupported -} - -func GetPasswd() (io.ReadCloser, error) { - return nil, ErrUnsupported -} - -func GetGroupPath() (string, error) { - return "", ErrUnsupported -} - -func GetGroup() (io.ReadCloser, error) { - return nil, ErrUnsupported -} - -// CurrentUser looks up the current user by their user id in /etc/passwd. If the -// user cannot be found (or there is no /etc/passwd file on the filesystem), -// then CurrentUser returns an error. -func CurrentUser() (User, error) { - return LookupUid(syscall.Getuid()) -} - -// CurrentGroup looks up the current user's group by their primary group id's -// entry in /etc/passwd. If the group cannot be found (or there is no -// /etc/group file on the filesystem), then CurrentGroup returns an error. -func CurrentGroup() (Group, error) { - return LookupGid(syscall.Getgid()) -} diff --git a/vendor/github.com/opencontainers/runc/vendor.conf b/vendor/github.com/opencontainers/runc/vendor.conf index 8139d6962..0ab4685fd 100644 --- a/vendor/github.com/opencontainers/runc/vendor.conf +++ b/vendor/github.com/opencontainers/runc/vendor.conf @@ -15,7 +15,7 @@ github.com/coreos/pkg v3 github.com/godbus/dbus v3 github.com/golang/protobuf 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8 # Command-line interface. -github.com/docker/docker 0f5c9d301b9b1cca66b3ea0f9dec3b5317d3686d +github.com/cyphar/filepath-securejoin v0.2.1 github.com/docker/go-units v0.2.0 github.com/urfave/cli d53eb991652b1d438abdd34ce4bfa3ef1539108e golang.org/x/sys 7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce https://github.com/golang/sys diff --git a/vendor/github.com/opencontainers/runtime-spec/README.md b/vendor/github.com/opencontainers/runtime-spec/README.md index 2f7eb6086..f0ad86e67 100644 --- a/vendor/github.com/opencontainers/runtime-spec/README.md +++ b/vendor/github.com/opencontainers/runtime-spec/README.md @@ -52,17 +52,12 @@ It also guarantees that the design is sound before code is written; a GitHub pul Typos and grammatical errors can go straight to a pull-request. When in doubt, start on the [mailing-list](#mailing-list). -### Weekly Call - -The contributors and maintainers of all OCI projects have a weekly meeting on Wednesdays at: - -* 8:00 AM (USA Pacific), during [odd weeks][iso-week]. -* 2:00 PM (USA Pacific), during [even weeks][iso-week]. +### Meetings +The contributors and maintainers of all OCI projects have monthly meetings at 2:00 PM (USA Pacific) on the first Wednesday of every month. There is an [iCalendar][rfc5545] format for the meetings [here](meeting.ics). - Everyone is welcome to participate via [UberConference web][uberconference] or audio-only: +1 415 968 0849 (no PIN needed). -An initial agenda will be posted to the [mailing list](#mailing-list) earlier in the week, and everyone is welcome to propose additional topics or suggest other agenda alterations there. +An initial agenda will be posted to the [mailing list](#mailing-list) in the week before each meeting, and everyone is welcome to propose additional topics or suggest other agenda alterations there. Minutes are posted to the [mailing list](#mailing-list) and minutes from past calls are archived [here][minutes], with minutes from especially old meetings (September 2015 and earlier) archived [here][runtime-wiki]. ### Mailing List diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go index f3f37d42d..71c9fa773 100644 --- a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go +++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go @@ -4,7 +4,7 @@ import "os" // Spec is the base configuration for the container. type Spec struct { - // Version of the Open Container Runtime Specification with which the bundle complies. + // Version of the Open Container Initiative Runtime Specification with which the bundle complies. Version string `json:"ociVersion"` // Process configures the container process. Process *Process `json:"process,omitempty"` diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go index 926ce6650..ff0cb6a80 100644 --- a/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go +++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/version.go @@ -8,7 +8,7 @@ const ( // VersionMinor is for functionality in a backwards-compatible manner VersionMinor = 0 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 + VersionPatch = 1 // VersionDev indicates development branch. Releases will be empty string. VersionDev = "" diff --git a/vendor/google.golang.org/grpc/balancer_conn_wrappers.go b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go index e4a95fd5c..f5dbc4ba2 100644 --- a/vendor/google.golang.org/grpc/balancer_conn_wrappers.go +++ b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go @@ -171,7 +171,9 @@ func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer return nil, err } acbw := &acBalancerWrapper{ac: ac} + ac.mu.Lock() ac.acbw = acbw + ac.mu.Unlock() return acbw, nil } @@ -228,7 +230,9 @@ func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) { return } acbw.ac = ac + ac.mu.Lock() ac.acbw = acbw + ac.mu.Unlock() if acState != connectivity.Idle { ac.connect(false) } diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go index 5462062be..71de2e50d 100644 --- a/vendor/google.golang.org/grpc/clientconn.go +++ b/vendor/google.golang.org/grpc/clientconn.go @@ -929,6 +929,16 @@ func (ac *addrConn) resetTransport() error { newTransport, err := transport.NewClientTransport(ac.cc.ctx, sinfo, copts, timeout) if err != nil { if e, ok := err.(transport.ConnectionError); ok && !e.Temporary() { + ac.mu.Lock() + if ac.state != connectivity.Shutdown { + ac.state = connectivity.TransientFailure + if ac.cc.balancerWrapper != nil { + ac.cc.balancerWrapper.handleSubConnStateChange(ac.acbw, ac.state) + } else { + ac.cc.csMgr.updateState(ac.state) + } + } + ac.mu.Unlock() return err } grpclog.Warningf("grpc: addrConn.resetTransport failed to create client transport: %v; Reconnecting to %v", err, addr) diff --git a/vendor/google.golang.org/grpc/credentials/credentials.go b/vendor/google.golang.org/grpc/credentials/credentials.go index 2475fe832..946aa1f2b 100644 --- a/vendor/google.golang.org/grpc/credentials/credentials.go +++ b/vendor/google.golang.org/grpc/credentials/credentials.go @@ -91,10 +91,14 @@ type TransportCredentials interface { // (io.EOF, context.DeadlineExceeded or err.Temporary() == true). // If the returned error is a wrapper error, implementations should make sure that // the error implements Temporary() to have the correct retry behaviors. + // + // If the returned net.Conn is closed, it MUST close the net.Conn provided. ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error) // ServerHandshake does the authentication handshake for servers. It returns // the authenticated connection and the corresponding auth information about // the connection. + // + // If the returned net.Conn is closed, it MUST close the net.Conn provided. ServerHandshake(net.Conn) (net.Conn, AuthInfo, error) // Info provides the ProtocolInfo of this TransportCredentials. Info() ProtocolInfo diff --git a/vendor/google.golang.org/grpc/rpc_util.go b/vendor/google.golang.org/grpc/rpc_util.go index e71c77bb6..54fc3ecee 100644 --- a/vendor/google.golang.org/grpc/rpc_util.go +++ b/vendor/google.golang.org/grpc/rpc_util.go @@ -567,6 +567,6 @@ const SupportPackageIsVersion3 = true const SupportPackageIsVersion4 = true // Version is the current grpc version. -const Version = "1.7.2" +const Version = "1.7.4" const grpcUA = "grpc-go/" + Version diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go index 7c882dbe6..787665dfe 100644 --- a/vendor/google.golang.org/grpc/server.go +++ b/vendor/google.golang.org/grpc/server.go @@ -118,11 +118,13 @@ type options struct { initialConnWindowSize int32 writeBufferSize int readBufferSize int + connectionTimeout time.Duration } var defaultServerOptions = options{ maxReceiveMessageSize: defaultServerMaxReceiveMessageSize, maxSendMessageSize: defaultServerMaxSendMessageSize, + connectionTimeout: 120 * time.Second, } // A ServerOption sets options such as credentials, codec and keepalive parameters, etc. @@ -291,6 +293,16 @@ func UnknownServiceHandler(streamHandler StreamHandler) ServerOption { } } +// ConnectionTimeout returns a ServerOption that sets the timeout for +// connection establishment (up to and including HTTP/2 handshaking) for all +// new connections. If this is not set, the default is 120 seconds. A zero or +// negative value will result in an immediate timeout. +func ConnectionTimeout(d time.Duration) ServerOption { + return func(o *options) { + o.connectionTimeout = d + } +} + // NewServer creates a gRPC server which has no service registered and has not // started to accept requests yet. func NewServer(opt ...ServerOption) *Server { @@ -499,16 +511,18 @@ func (s *Server) Serve(lis net.Listener) error { // handleRawConn is run in its own goroutine and handles a just-accepted // connection that has not had any I/O performed on it yet. func (s *Server) handleRawConn(rawConn net.Conn) { + rawConn.SetDeadline(time.Now().Add(s.opts.connectionTimeout)) conn, authInfo, err := s.useTransportAuthenticator(rawConn) if err != nil { s.mu.Lock() s.errorf("ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err) s.mu.Unlock() grpclog.Warningf("grpc: Server.Serve failed to complete security handshake from %q: %v", rawConn.RemoteAddr(), err) - // If serverHandShake returns ErrConnDispatched, keep rawConn open. + // If serverHandshake returns ErrConnDispatched, keep rawConn open. if err != credentials.ErrConnDispatched { rawConn.Close() } + rawConn.SetDeadline(time.Time{}) return } @@ -521,18 +535,21 @@ func (s *Server) handleRawConn(rawConn net.Conn) { s.mu.Unlock() if s.opts.useHandlerImpl { + rawConn.SetDeadline(time.Time{}) s.serveUsingHandler(conn) } else { - s.serveHTTP2Transport(conn, authInfo) + st := s.newHTTP2Transport(conn, authInfo) + if st == nil { + return + } + rawConn.SetDeadline(time.Time{}) + s.serveStreams(st) } } -// serveHTTP2Transport sets up a http/2 transport (using the -// gRPC http2 server transport in transport/http2_server.go) and -// serves streams on it. -// This is run in its own goroutine (it does network I/O in -// transport.NewServerTransport). -func (s *Server) serveHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) { +// newHTTP2Transport sets up a http/2 transport (using the +// gRPC http2 server transport in transport/http2_server.go). +func (s *Server) newHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) transport.ServerTransport { config := &transport.ServerConfig{ MaxStreams: s.opts.maxConcurrentStreams, AuthInfo: authInfo, @@ -552,13 +569,13 @@ func (s *Server) serveHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) s.mu.Unlock() c.Close() grpclog.Warningln("grpc: Server.Serve failed to create ServerTransport: ", err) - return + return nil } if !s.addConn(st) { st.Close() - return + return nil } - s.serveStreams(st) + return st } func (s *Server) serveStreams(st transport.ServerTransport) { diff --git a/vendor/google.golang.org/grpc/transport/handler_server.go b/vendor/google.golang.org/grpc/transport/handler_server.go index f1f6caf89..7e0fdb359 100644 --- a/vendor/google.golang.org/grpc/transport/handler_server.go +++ b/vendor/google.golang.org/grpc/transport/handler_server.go @@ -123,10 +123,9 @@ type serverHandlerTransport struct { // when WriteStatus is called. writes chan func() - mu sync.Mutex - // streamDone indicates whether WriteStatus has been called and writes channel - // has been closed. - streamDone bool + // block concurrent WriteStatus calls + // e.g. grpc/(*serverStream).SendMsg/RecvMsg + writeStatusMu sync.Mutex } func (ht *serverHandlerTransport) Close() error { @@ -177,13 +176,9 @@ func (ht *serverHandlerTransport) do(fn func()) error { } func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) error { - ht.mu.Lock() - if ht.streamDone { - ht.mu.Unlock() - return nil - } - ht.streamDone = true - ht.mu.Unlock() + ht.writeStatusMu.Lock() + defer ht.writeStatusMu.Unlock() + err := ht.do(func() { ht.writeCommonHeaders(s) @@ -222,7 +217,11 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro } } }) - close(ht.writes) + + if err == nil { // transport has not been closed + ht.Close() + close(ht.writes) + } return err } diff --git a/vendor/google.golang.org/grpc/transport/http2_server.go b/vendor/google.golang.org/grpc/transport/http2_server.go index bad29b88a..00df8eed0 100644 --- a/vendor/google.golang.org/grpc/transport/http2_server.go +++ b/vendor/google.golang.org/grpc/transport/http2_server.go @@ -152,12 +152,12 @@ func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err Val: uint32(iwz)}) } if err := framer.fr.WriteSettings(isettings...); err != nil { - return nil, connectionErrorf(true, err, "transport: %v", err) + return nil, connectionErrorf(false, err, "transport: %v", err) } // Adjust the connection flow control window if needed. if delta := uint32(icwz - defaultWindowSize); delta > 0 { if err := framer.fr.WriteWindowUpdate(0, delta); err != nil { - return nil, connectionErrorf(true, err, "transport: %v", err) + return nil, connectionErrorf(false, err, "transport: %v", err) } } kp := config.KeepaliveParams @@ -223,6 +223,31 @@ func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err t.stats.HandleConn(t.ctx, connBegin) } t.framer.writer.Flush() + + // Check the validity of client preface. + preface := make([]byte, len(clientPreface)) + if _, err := io.ReadFull(t.conn, preface); err != nil { + return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to receive the preface from client: %v", err) + } + if !bytes.Equal(preface, clientPreface) { + return nil, connectionErrorf(false, nil, "transport: http2Server.HandleStreams received bogus greeting from client: %q", preface) + } + + frame, err := t.framer.fr.ReadFrame() + if err == io.EOF || err == io.ErrUnexpectedEOF { + t.Close() + return + } + if err != nil { + return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to read initial settings frame: %v", err) + } + atomic.StoreUint32(&t.activity, 1) + sf, ok := frame.(*http2.SettingsFrame) + if !ok { + return nil, connectionErrorf(false, nil, "transport: http2Server.HandleStreams saw invalid preface type %T from client", frame) + } + t.handleSettings(sf) + go func() { loopyWriter(t.ctx, t.controlBuf, t.itemHandler) t.Close() @@ -354,41 +379,6 @@ func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func( // typically run in a separate goroutine. // traceCtx attaches trace to ctx and returns the new context. func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context.Context, string) context.Context) { - // Check the validity of client preface. - preface := make([]byte, len(clientPreface)) - if _, err := io.ReadFull(t.conn, preface); err != nil { - // Only log if it isn't a simple tcp accept check (ie: tcp balancer doing open/close socket) - if err != io.EOF { - errorf("transport: http2Server.HandleStreams failed to receive the preface from client: %v", err) - } - t.Close() - return - } - if !bytes.Equal(preface, clientPreface) { - errorf("transport: http2Server.HandleStreams received bogus greeting from client: %q", preface) - t.Close() - return - } - - frame, err := t.framer.fr.ReadFrame() - if err == io.EOF || err == io.ErrUnexpectedEOF { - t.Close() - return - } - if err != nil { - errorf("transport: http2Server.HandleStreams failed to read initial settings frame: %v", err) - t.Close() - return - } - atomic.StoreUint32(&t.activity, 1) - sf, ok := frame.(*http2.SettingsFrame) - if !ok { - errorf("transport: http2Server.HandleStreams saw invalid preface type %T from client", frame) - t.Close() - return - } - t.handleSettings(sf) - for { frame, err := t.framer.fr.ReadFrame() atomic.StoreUint32(&t.activity, 1)