mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-10-29 23:23:54 +08:00
vendor: initial vendor
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
281
vendor/github.com/containerd/containerd/cio/io.go
generated
vendored
Normal file
281
vendor/github.com/containerd/containerd/cio/io.go
generated
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
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 cio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/containerd/defaults"
|
||||
)
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
buffer := make([]byte, 32<<10)
|
||||
return &buffer
|
||||
},
|
||||
}
|
||||
|
||||
// Config holds the IO configurations.
|
||||
type Config struct {
|
||||
// Terminal is true if one has been allocated
|
||||
Terminal bool
|
||||
// Stdin path
|
||||
Stdin string
|
||||
// Stdout path
|
||||
Stdout string
|
||||
// Stderr path
|
||||
Stderr string
|
||||
}
|
||||
|
||||
// IO holds the io information for a task or process
|
||||
type IO interface {
|
||||
// Config returns the IO configuration.
|
||||
Config() Config
|
||||
// Cancel aborts all current io operations.
|
||||
Cancel()
|
||||
// Wait blocks until all io copy operations have completed.
|
||||
Wait()
|
||||
// Close cleans up all open io resources. Cancel() is always called before
|
||||
// Close()
|
||||
Close() error
|
||||
}
|
||||
|
||||
// Creator creates new IO sets for a task
|
||||
type Creator func(id string) (IO, error)
|
||||
|
||||
// Attach allows callers to reattach to running tasks
|
||||
//
|
||||
// There should only be one reader for a task's IO set
|
||||
// because fifo's can only be read from one reader or the output
|
||||
// will be sent only to the first reads
|
||||
type Attach func(*FIFOSet) (IO, error)
|
||||
|
||||
// FIFOSet is a set of file paths to FIFOs for a task's standard IO streams
|
||||
type FIFOSet struct {
|
||||
Config
|
||||
close func() error
|
||||
}
|
||||
|
||||
// Close the FIFOSet
|
||||
func (f *FIFOSet) Close() error {
|
||||
if f.close != nil {
|
||||
return f.close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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
|
||||
FIFODir string
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
// WithFIFODir sets the fifo directory.
|
||||
// e.g. "/run/containerd/fifo", "/run/users/1001/containerd/fifo"
|
||||
func WithFIFODir(dir string) Opt {
|
||||
return func(opt *Streams) {
|
||||
opt.FIFODir = dir
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreator returns an IO creator from the options
|
||||
func NewCreator(opts ...Opt) Creator {
|
||||
streams := &Streams{}
|
||||
for _, opt := range opts {
|
||||
opt(streams)
|
||||
}
|
||||
if streams.FIFODir == "" {
|
||||
streams.FIFODir = defaults.DefaultFIFODir
|
||||
}
|
||||
return func(id string) (IO, error) {
|
||||
fifos, err := NewFIFOSetInDir(streams.FIFODir, id, streams.Terminal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if streams.Stdin == nil {
|
||||
fifos.Stdin = ""
|
||||
}
|
||||
if streams.Stdout == nil {
|
||||
fifos.Stdout = ""
|
||||
}
|
||||
if streams.Stderr == nil {
|
||||
fifos.Stderr = ""
|
||||
}
|
||||
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{}
|
||||
|
||||
// LogFile creates a file on disk that logs the task's STDOUT,STDERR.
|
||||
// If the log file already exists, the logs will be appended to the file.
|
||||
func LogFile(path string) Creator {
|
||||
return func(_ string) (IO, error) {
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.Close()
|
||||
return &logIO{
|
||||
config: Config{
|
||||
Stdout: path,
|
||||
Stderr: path,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
type logIO struct {
|
||||
config Config
|
||||
}
|
||||
|
||||
func (l *logIO) Config() Config {
|
||||
return l.config
|
||||
}
|
||||
|
||||
func (l *logIO) Cancel() {
|
||||
|
||||
}
|
||||
|
||||
func (l *logIO) Wait() {
|
||||
|
||||
}
|
||||
|
||||
func (l *logIO) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load the io for a container but do not attach
|
||||
//
|
||||
// Allows io to be loaded on the task for deletion without
|
||||
// starting copy routines
|
||||
func Load(set *FIFOSet) (IO, error) {
|
||||
return &cio{
|
||||
config: set.Config,
|
||||
closers: []io.Closer{set},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *pipes) closers() []io.Closer {
|
||||
return []io.Closer{p.Stdin, p.Stdout, p.Stderr}
|
||||
}
|
||||
154
vendor/github.com/containerd/containerd/cio/io_unix.go
generated
vendored
Normal file
154
vendor/github.com/containerd/containerd/cio/io_unix.go
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
// +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 cio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/fifo"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
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 *Streams) (*cio, error) {
|
||||
var ctx, cancel = context.WithCancel(context.Background())
|
||||
pipes, err := openFifos(ctx, fifos)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if fifos.Stdin != "" {
|
||||
go func() {
|
||||
p := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(p)
|
||||
|
||||
io.CopyBuffer(pipes.Stdin, ioset.Stdin, *p)
|
||||
pipes.Stdin.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
var wg = &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
p := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(p)
|
||||
|
||||
io.CopyBuffer(ioset.Stdout, pipes.Stdout, *p)
|
||||
pipes.Stdout.Close()
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
if !fifos.Terminal {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
p := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(p)
|
||||
|
||||
io.CopyBuffer(ioset.Stderr, pipes.Stderr, *p)
|
||||
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 {
|
||||
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")
|
||||
}
|
||||
defer func() {
|
||||
if err != 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")
|
||||
}
|
||||
defer func() {
|
||||
if err != nil && f.Stdout != nil {
|
||||
f.Stdout.Close()
|
||||
}
|
||||
}()
|
||||
}
|
||||
if 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")
|
||||
}
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
166
vendor/github.com/containerd/containerd/cio/io_windows.go
generated
vendored
Normal file
166
vendor/github.com/containerd/containerd/cio/io_windows.go
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
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 cio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
winio "github.com/Microsoft/go-winio"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const pipeRoot = `\\.\pipe`
|
||||
|
||||
// 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 *Streams) (*cio, error) {
|
||||
var (
|
||||
set []io.Closer
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
go func() {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
log.L.WithError(err).Errorf("failed to accept stdin connection on %s", fifos.Stdin)
|
||||
return
|
||||
}
|
||||
|
||||
p := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(p)
|
||||
|
||||
io.CopyBuffer(c, ioset.Stdin, *p)
|
||||
c.Close()
|
||||
l.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
if fifos.Stdout != "" {
|
||||
l, err := winio.ListenPipe(fifos.Stdout, nil)
|
||||
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)
|
||||
|
||||
go func() {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
log.L.WithError(err).Errorf("failed to accept stdout connection on %s", fifos.Stdout)
|
||||
return
|
||||
}
|
||||
|
||||
p := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(p)
|
||||
|
||||
io.CopyBuffer(ioset.Stdout, c, *p)
|
||||
c.Close()
|
||||
l.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
if fifos.Stderr != "" {
|
||||
l, err := winio.ListenPipe(fifos.Stderr, nil)
|
||||
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)
|
||||
|
||||
go func() {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
log.L.WithError(err).Errorf("failed to accept stderr connection on %s", fifos.Stderr)
|
||||
return
|
||||
}
|
||||
|
||||
p := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(p)
|
||||
|
||||
io.CopyBuffer(ioset.Stderr, c, *p)
|
||||
c.Close()
|
||||
l.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
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},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewDirectIOFromFIFOSet returns an IO implementation that exposes the IO streams as io.ReadCloser
|
||||
// and io.WriteCloser.
|
||||
func NewDirectIOFromFIFOSet(ctx context.Context, stdin io.WriteCloser, stdout, stderr io.ReadCloser, fifos *FIFOSet) *DirectIO {
|
||||
_, cancel := context.WithCancel(ctx)
|
||||
pipes := pipes{
|
||||
Stdin: stdin,
|
||||
Stdout: stdout,
|
||||
Stderr: stderr,
|
||||
}
|
||||
return &DirectIO{
|
||||
pipes: pipes,
|
||||
cio: cio{
|
||||
config: fifos.Config,
|
||||
closers: append(pipes.closers(), fifos),
|
||||
cancel: cancel,
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user