...

Source file src/github.com/Microsoft/hcsshim/internal/cmd/io.go

Documentation: github.com/Microsoft/hcsshim/internal/cmd

     1  //go:build windows
     2  
     3  package cmd
     4  
     5  import (
     6  	"context"
     7  	"io"
     8  	"net/url"
     9  	"time"
    10  
    11  	"github.com/pkg/errors"
    12  	"github.com/sirupsen/logrus"
    13  )
    14  
    15  // UpstreamIO is an interface describing the IO to connect to above the shim.
    16  // Depending on the callers settings there may be no opened IO.
    17  type UpstreamIO interface {
    18  	// Close closes all open io.
    19  	//
    20  	// This call is idempotent and safe to call multiple times.
    21  	Close(ctx context.Context)
    22  	// CloseStdin closes just `Stdin()` if open.
    23  	//
    24  	// This call is idempotent and safe to call multiple times.
    25  	CloseStdin(ctx context.Context)
    26  	// Stdin returns the open `stdin` reader. If `stdin` was never opened this
    27  	// will return `nil`.
    28  	Stdin() io.Reader
    29  	// StdinPath returns the original path used to open the `Stdin()` reader.
    30  	StdinPath() string
    31  	// Stdout returns the open `stdout` writer. If `stdout` was never opened
    32  	// this will return `nil`.
    33  	Stdout() io.Writer
    34  	// StdoutPath returns the original path used to open the `Stdout()` writer.
    35  	StdoutPath() string
    36  	// Stderr returns the open `stderr` writer. If `stderr` was never opened
    37  	// this will return `nil`.
    38  	Stderr() io.Writer
    39  	// StderrPath returns the original path used to open the `Stderr()` writer.
    40  	StderrPath() string
    41  	// Terminal returns `true` if the connection is emulating a terminal. If
    42  	// `true` `Stderr()` will always return `nil` and `StderrPath()` will always
    43  	// return `""`.
    44  	Terminal() bool
    45  }
    46  
    47  // NewUpstreamIO returns an UpstreamIO instance. Currently we only support named pipes and binary
    48  // logging driver for container IO. When using binary logger `stdout` and `stderr` are assumed to be
    49  // the same and the value of `stderr` is completely ignored.
    50  func NewUpstreamIO(ctx context.Context, id, stdout, stderr, stdin string, terminal bool, ioRetryTimeout time.Duration) (UpstreamIO, error) {
    51  	u, err := url.Parse(stdout)
    52  
    53  	// Create IO with named pipes.
    54  	if err != nil || u.Scheme == "" {
    55  		return NewNpipeIO(ctx, stdin, stdout, stderr, terminal, ioRetryTimeout)
    56  	}
    57  
    58  	// Create IO for binary logging driver.
    59  	if u.Scheme != "binary" {
    60  		return nil, errors.Errorf("scheme must be 'binary', got: '%s'", u.Scheme)
    61  	}
    62  
    63  	return NewBinaryIO(ctx, id, u)
    64  }
    65  
    66  // relayIO is a glorified io.Copy that also logs when the copy has completed.
    67  func relayIO(w io.Writer, r io.Reader, log *logrus.Entry, name string) (int64, error) {
    68  	n, err := io.Copy(w, r)
    69  	if log != nil {
    70  		lvl := logrus.DebugLevel
    71  		log = log.WithFields(logrus.Fields{
    72  			"file":  name,
    73  			"bytes": n,
    74  		})
    75  		if err != nil {
    76  			lvl = logrus.ErrorLevel
    77  			log = log.WithError(err)
    78  		}
    79  		log.Log(lvl, "Cmd IO relay complete")
    80  	}
    81  	return n, err
    82  }
    83  

View as plain text