github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/cmd/ctr/commands/tasks/tasks_unix.go (about)

     1  // +build !windows
     2  
     3  /*
     4     Copyright The containerd Authors.
     5  
     6     Licensed under the Apache License, Version 2.0 (the "License");
     7     you may not use this file except in compliance with the License.
     8     You may obtain a copy of the License at
     9  
    10         http://www.apache.org/licenses/LICENSE-2.0
    11  
    12     Unless required by applicable law or agreed to in writing, software
    13     distributed under the License is distributed on an "AS IS" BASIS,
    14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15     See the License for the specific language governing permissions and
    16     limitations under the License.
    17  */
    18  
    19  package tasks
    20  
    21  import (
    22  	gocontext "context"
    23  	"net/url"
    24  	"os"
    25  	"os/signal"
    26  
    27  	"github.com/containerd/console"
    28  	"github.com/containerd/containerd"
    29  	"github.com/containerd/containerd/cio"
    30  	"github.com/containerd/containerd/log"
    31  	"github.com/pkg/errors"
    32  	"github.com/urfave/cli"
    33  	"golang.org/x/sys/unix"
    34  )
    35  
    36  func init() {
    37  	startCommand.Flags = append(startCommand.Flags, cli.BoolFlag{
    38  		Name:  "no-pivot",
    39  		Usage: "disable use of pivot-root (linux only)",
    40  	})
    41  }
    42  
    43  // HandleConsoleResize resizes the console
    44  func HandleConsoleResize(ctx gocontext.Context, task resizer, con console.Console) error {
    45  	// do an initial resize of the console
    46  	size, err := con.Size()
    47  	if err != nil {
    48  		return err
    49  	}
    50  	if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil {
    51  		log.G(ctx).WithError(err).Error("resize pty")
    52  	}
    53  	s := make(chan os.Signal, 16)
    54  	signal.Notify(s, unix.SIGWINCH)
    55  	go func() {
    56  		for range s {
    57  			size, err := con.Size()
    58  			if err != nil {
    59  				log.G(ctx).WithError(err).Error("get pty size")
    60  				continue
    61  			}
    62  			if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil {
    63  				log.G(ctx).WithError(err).Error("resize pty")
    64  			}
    65  		}
    66  	}()
    67  	return nil
    68  }
    69  
    70  // NewTask creates a new task
    71  func NewTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, checkpoint string, con console.Console, nullIO bool, logURI string, ioOpts []cio.Opt, opts ...containerd.NewTaskOpts) (containerd.Task, error) {
    72  	stdinC := &stdinCloser{
    73  		stdin: os.Stdin,
    74  	}
    75  	stdio := cio.NewCreator(append([]cio.Opt{cio.WithStreams(stdinC, os.Stdout, os.Stderr)}, ioOpts...)...)
    76  	if checkpoint != "" {
    77  		im, err := client.GetImage(ctx, checkpoint)
    78  		if err != nil {
    79  			return nil, err
    80  		}
    81  		opts = append(opts, containerd.WithTaskCheckpoint(im))
    82  	}
    83  	ioCreator := stdio
    84  	if con != nil {
    85  		ioCreator = cio.NewCreator(append([]cio.Opt{cio.WithStreams(con, con, nil), cio.WithTerminal}, ioOpts...)...)
    86  	}
    87  	if nullIO {
    88  		if con != nil {
    89  			return nil, errors.New("tty and null-io cannot be used together")
    90  		}
    91  		ioCreator = cio.NullIO
    92  	}
    93  	if logURI != "" {
    94  		u, err := url.Parse(logURI)
    95  		if err != nil {
    96  			return nil, err
    97  		}
    98  		ioCreator = cio.LogURI(u)
    99  	}
   100  	t, err := container.NewTask(ctx, ioCreator, opts...)
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  	stdinC.closer = func() {
   105  		t.CloseIO(ctx, containerd.WithStdinCloser)
   106  	}
   107  	return t, nil
   108  }
   109  
   110  func getNewTaskOpts(context *cli.Context) []containerd.NewTaskOpts {
   111  	if context.Bool("no-pivot") {
   112  		return []containerd.NewTaskOpts{containerd.WithNoPivotRoot}
   113  	}
   114  	return nil
   115  }