ctr: move tasks, run to commands package
Signed-off-by: Jess Valarezo <valarezo.jessica@gmail.com>
This commit is contained in:
parent
fe3d9a70fa
commit
c3b70f1d0b
@ -1,13 +1,16 @@
|
||||
package main
|
||||
package run
|
||||
|
||||
import (
|
||||
gocontext "context"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
"github.com/containerd/containerd/cmd/ctr/commands/tasks"
|
||||
"github.com/containerd/containerd/containers"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
@ -15,10 +18,6 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
type resizer interface {
|
||||
Resize(ctx gocontext.Context, w, h uint32) error
|
||||
}
|
||||
|
||||
func withEnv(context *cli.Context) containerd.SpecOpts {
|
||||
return func(_ gocontext.Context, _ *containerd.Client, _ *containers.Container, s *specs.Spec) error {
|
||||
env := context.StringSlice("env")
|
||||
@ -42,10 +41,84 @@ func withMounts(context *cli.Context) containerd.SpecOpts {
|
||||
}
|
||||
}
|
||||
|
||||
var runCommand = cli.Command{
|
||||
// parseMountFlag parses a mount string in the form "type=foo,source=/path,destination=/target,options=rbind:rw"
|
||||
func parseMountFlag(m string) (specs.Mount, error) {
|
||||
mount := specs.Mount{}
|
||||
r := csv.NewReader(strings.NewReader(m))
|
||||
|
||||
fields, err := r.Read()
|
||||
if err != nil {
|
||||
return mount, err
|
||||
}
|
||||
|
||||
for _, field := range fields {
|
||||
v := strings.Split(field, "=")
|
||||
if len(v) != 2 {
|
||||
return mount, fmt.Errorf("invalid mount specification: expected key=val")
|
||||
}
|
||||
|
||||
key := v[0]
|
||||
val := v[1]
|
||||
switch key {
|
||||
case "type":
|
||||
mount.Type = val
|
||||
case "source", "src":
|
||||
mount.Source = val
|
||||
case "destination", "dst":
|
||||
mount.Destination = val
|
||||
case "options":
|
||||
mount.Options = strings.Split(val, ":")
|
||||
default:
|
||||
return mount, fmt.Errorf("mount option %q not supported", key)
|
||||
}
|
||||
}
|
||||
|
||||
return mount, nil
|
||||
}
|
||||
|
||||
// replaceOrAppendEnvValues returns the defaults with the overrides either
|
||||
// replaced by env key or appended to the list
|
||||
func replaceOrAppendEnvValues(defaults, overrides []string) []string {
|
||||
cache := make(map[string]int, len(defaults))
|
||||
for i, e := range defaults {
|
||||
parts := strings.SplitN(e, "=", 2)
|
||||
cache[parts[0]] = i
|
||||
}
|
||||
|
||||
for _, value := range overrides {
|
||||
// Values w/o = means they want this env to be removed/unset.
|
||||
if !strings.Contains(value, "=") {
|
||||
if i, exists := cache[value]; exists {
|
||||
defaults[i] = "" // Used to indicate it should be removed
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Just do a normal set/update
|
||||
parts := strings.SplitN(value, "=", 2)
|
||||
if i, exists := cache[parts[0]]; exists {
|
||||
defaults[i] = value
|
||||
} else {
|
||||
defaults = append(defaults, value)
|
||||
}
|
||||
}
|
||||
|
||||
// Now remove all entries that we want to "unset"
|
||||
for i := 0; i < len(defaults); i++ {
|
||||
if defaults[i] == "" {
|
||||
defaults = append(defaults[:i], defaults[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
|
||||
return defaults
|
||||
}
|
||||
|
||||
// Command runs a container
|
||||
var Command = cli.Command{
|
||||
Name: "run",
|
||||
Usage: "run a container",
|
||||
ArgsUsage: "Image|RootFS ID [COMMAND] [ARG...]",
|
||||
ArgsUsage: "[flags] Image|RootFS ID [COMMAND] [ARG...]",
|
||||
Flags: append([]cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "tty,t",
|
||||
@ -125,7 +198,7 @@ var runCommand = cli.Command{
|
||||
if context.Bool("rm") && !detach {
|
||||
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
|
||||
}
|
||||
task, err := newTask(ctx, client, container, context.String("checkpoint"), tty, context.Bool("null-io"))
|
||||
task, err := tasks.NewTask(ctx, client, container, context.String("checkpoint"), tty, context.Bool("null-io"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -151,7 +224,7 @@ var runCommand = cli.Command{
|
||||
return nil
|
||||
}
|
||||
if tty {
|
||||
if err := handleConsoleResize(ctx, task, con); err != nil {
|
||||
if err := tasks.HandleConsoleResize(ctx, task, con); err != nil {
|
||||
logrus.WithError(err).Error("console resize")
|
||||
}
|
||||
} else {
|
@ -1,56 +1,23 @@
|
||||
// +build !windows
|
||||
|
||||
package main
|
||||
package run
|
||||
|
||||
import (
|
||||
gocontext "context"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
func init() {
|
||||
runCommand.Flags = append(runCommand.Flags, cli.BoolFlag{
|
||||
Command.Flags = append(Command.Flags, cli.BoolFlag{
|
||||
Name: "rootfs",
|
||||
Usage: "use custom rootfs that is not managed by containerd snapshotter.",
|
||||
Usage: "use custom rootfs that is not managed by containerd snapshotter",
|
||||
})
|
||||
}
|
||||
|
||||
func handleConsoleResize(ctx gocontext.Context, task resizer, con console.Console) error {
|
||||
// do an initial resize of the console
|
||||
size, err := con.Size()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil {
|
||||
logrus.WithError(err).Error("resize pty")
|
||||
}
|
||||
s := make(chan os.Signal, 16)
|
||||
signal.Notify(s, unix.SIGWINCH)
|
||||
go func() {
|
||||
for range s {
|
||||
size, err := con.Size()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("get pty size")
|
||||
continue
|
||||
}
|
||||
if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil {
|
||||
logrus.WithError(err).Error("resize pty")
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func withTTY() containerd.SpecOpts {
|
||||
return containerd.WithTTY
|
||||
}
|
||||
@ -115,24 +82,3 @@ func newContainer(ctx gocontext.Context, client *containerd.Client, context *cli
|
||||
cOpts = append([]containerd.NewContainerOpts{containerd.WithNewSpec(opts...)}, cOpts...)
|
||||
return client.NewContainer(ctx, id, cOpts...)
|
||||
}
|
||||
|
||||
func newTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, checkpoint string, tty, nullIO bool) (containerd.Task, error) {
|
||||
if checkpoint == "" {
|
||||
io := containerd.Stdio
|
||||
if tty {
|
||||
io = containerd.StdioTerminal
|
||||
}
|
||||
if nullIO {
|
||||
if tty {
|
||||
return nil, errors.New("tty and null-io cannot be used together")
|
||||
}
|
||||
io = containerd.NullIO
|
||||
}
|
||||
return container.NewTask(ctx, io)
|
||||
}
|
||||
im, err := client.GetImage(ctx, checkpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return container.NewTask(ctx, containerd.Stdio, containerd.WithTaskCheckpoint(im))
|
||||
}
|
@ -1,15 +1,13 @@
|
||||
package main
|
||||
package run
|
||||
|
||||
import (
|
||||
gocontext "context"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/log"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -19,7 +17,7 @@ import (
|
||||
const pipeRoot = `\\.\pipe`
|
||||
|
||||
func init() {
|
||||
runCommand.Flags = append(runCommand.Flags, cli.StringSliceFlag{
|
||||
Command.Flags = append(Command.Flags, cli.StringSliceFlag{
|
||||
Name: "layer",
|
||||
Usage: "HCSSHIM Layers to be used",
|
||||
})
|
||||
@ -36,34 +34,6 @@ func withLayers(context *cli.Context) containerd.SpecOpts {
|
||||
}
|
||||
}
|
||||
|
||||
func handleConsoleResize(ctx gocontext.Context, task resizer, con console.Console) error {
|
||||
// do an initial resize of the console
|
||||
size, err := con.Size()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
prevSize := size
|
||||
for {
|
||||
time.Sleep(time.Millisecond * 250)
|
||||
|
||||
size, err := con.Size()
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Error("get pty size")
|
||||
continue
|
||||
}
|
||||
|
||||
if size.Width != prevSize.Width || size.Height != prevSize.Height {
|
||||
if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil {
|
||||
logrus.WithError(err).Error("resize pty")
|
||||
}
|
||||
prevSize = size
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func withTTY(terminal bool) containerd.SpecOpts {
|
||||
if !terminal {
|
||||
return func(ctx gocontext.Context, client *containerd.Client, c *containers.Container, s *specs.Spec) error {
|
||||
@ -117,17 +87,3 @@ func newContainer(ctx gocontext.Context, client *containerd.Client, context *cli
|
||||
// TODO(mlaventure): containerd.WithImage(image),
|
||||
)
|
||||
}
|
||||
|
||||
func newTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, _ string, tty, nullIO bool) (containerd.Task, error) {
|
||||
io := containerd.Stdio
|
||||
if tty {
|
||||
io = containerd.StdioTerminal
|
||||
}
|
||||
if nullIO {
|
||||
if tty {
|
||||
return nil, errors.New("tty and null-io cannot be used together")
|
||||
}
|
||||
io = containerd.NullIO
|
||||
}
|
||||
return container.NewTask(ctx, io)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"os"
|
||||
@ -10,7 +10,7 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var taskAttachCommand = cli.Command{
|
||||
var attachCommand = cli.Command{
|
||||
Name: "attach",
|
||||
Usage: "attach to the IO of a running container",
|
||||
ArgsUsage: "CONTAINER",
|
||||
@ -51,7 +51,7 @@ var taskAttachCommand = cli.Command{
|
||||
}
|
||||
|
||||
if tty {
|
||||
if err := handleConsoleResize(ctx, task, con); err != nil {
|
||||
if err := HandleConsoleResize(ctx, task, con); err != nil {
|
||||
logrus.WithError(err).Error("console resize")
|
||||
}
|
||||
} else {
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -9,10 +9,10 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var taskCheckpointCommand = cli.Command{
|
||||
var checkpointCommand = cli.Command{
|
||||
Name: "checkpoint",
|
||||
Usage: "checkpoint a container",
|
||||
ArgsUsage: "CONTAINER",
|
||||
ArgsUsage: "[flags] CONTAINER",
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "exit",
|
@ -1,11 +1,11 @@
|
||||
package main
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var taskDeleteCommand = cli.Command{
|
||||
var deleteCommand = cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "delete a task",
|
||||
ArgsUsage: "CONTAINER",
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -11,10 +11,10 @@ import (
|
||||
)
|
||||
|
||||
//TODO:(jessvalarezo) exec-id is optional here, update to required arg
|
||||
var taskExecCommand = cli.Command{
|
||||
var execCommand = cli.Command{
|
||||
Name: "exec",
|
||||
Usage: "execute additional processes in an existing container",
|
||||
ArgsUsage: "CONTAINER CMD [ARG...]",
|
||||
ArgsUsage: "[flags] CONTAINER CMD [ARG...]",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "cwd",
|
||||
@ -84,7 +84,7 @@ var taskExecCommand = cli.Command{
|
||||
}
|
||||
}
|
||||
if tty {
|
||||
if err := handleConsoleResize(ctx, process, con); err != nil {
|
||||
if err := HandleConsoleResize(ctx, process, con); err != nil {
|
||||
logrus.WithError(err).Error("console resize")
|
||||
}
|
||||
} else {
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
@ -8,10 +8,10 @@ import (
|
||||
|
||||
// TODO:(jessvalarezo) the pid flag is not used here
|
||||
// update to be able to signal given pid
|
||||
var taskKillCommand = cli.Command{
|
||||
var killCommand = cli.Command{
|
||||
Name: "kill",
|
||||
Usage: "signal a container (default: SIGTERM)",
|
||||
ArgsUsage: "CONTAINER",
|
||||
ArgsUsage: "[flags] CONTAINER",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "signal, s",
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -10,28 +10,11 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var tasksCommand = cli.Command{
|
||||
Name: "tasks",
|
||||
Usage: "manage tasks",
|
||||
Aliases: []string{"t"},
|
||||
Subcommands: []cli.Command{
|
||||
taskAttachCommand,
|
||||
taskCheckpointCommand,
|
||||
taskExecCommand,
|
||||
taskKillCommand,
|
||||
taskPauseCommand,
|
||||
taskPsCommand,
|
||||
taskResumeCommand,
|
||||
taskStartCommand,
|
||||
taskDeleteCommand,
|
||||
taskListCommand,
|
||||
},
|
||||
}
|
||||
|
||||
var taskListCommand = cli.Command{
|
||||
var listCommand = cli.Command{
|
||||
Name: "list",
|
||||
Usage: "list tasks",
|
||||
Aliases: []string{"ls"},
|
||||
ArgsUsage: "[flags]",
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
@ -1,11 +1,11 @@
|
||||
package main
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var taskPauseCommand = cli.Command{
|
||||
var pauseCommand = cli.Command{
|
||||
Name: "pause",
|
||||
Usage: "pause an existing container",
|
||||
ArgsUsage: "CONTAINER",
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var taskPsCommand = cli.Command{
|
||||
var psCommand = cli.Command{
|
||||
Name: "ps",
|
||||
Usage: "list processes for container",
|
||||
ArgsUsage: "CONTAINER",
|
@ -1,11 +1,11 @@
|
||||
package main
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var taskResumeCommand = cli.Command{
|
||||
var resumeCommand = cli.Command{
|
||||
Name: "resume",
|
||||
Usage: "resume a paused container",
|
||||
ArgsUsage: "CONTAINER",
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"github.com/containerd/console"
|
||||
@ -8,7 +8,7 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var taskStartCommand = cli.Command{
|
||||
var startCommand = cli.Command{
|
||||
Name: "start",
|
||||
Usage: "start a container that have been created",
|
||||
ArgsUsage: "CONTAINER",
|
||||
@ -43,7 +43,7 @@ var taskStartCommand = cli.Command{
|
||||
|
||||
tty := spec.Process.Terminal
|
||||
|
||||
task, err := newTask(ctx, client, container, "", tty, context.Bool("null-io"))
|
||||
task, err := NewTask(ctx, client, container, "", tty, context.Bool("null-io"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -66,7 +66,7 @@ var taskStartCommand = cli.Command{
|
||||
return err
|
||||
}
|
||||
if tty {
|
||||
if err := handleConsoleResize(ctx, task, con); err != nil {
|
||||
if err := HandleConsoleResize(ctx, task, con); err != nil {
|
||||
logrus.WithError(err).Error("console resize")
|
||||
}
|
||||
} else {
|
30
cmd/ctr/commands/tasks/tasks.go
Normal file
30
cmd/ctr/commands/tasks/tasks.go
Normal file
@ -0,0 +1,30 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
gocontext "context"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
type resizer interface {
|
||||
Resize(ctx gocontext.Context, w, h uint32) error
|
||||
}
|
||||
|
||||
// Command is the cli command for managing tasks
|
||||
var Command = cli.Command{
|
||||
Name: "tasks",
|
||||
Usage: "manage tasks",
|
||||
Aliases: []string{"t"},
|
||||
Subcommands: []cli.Command{
|
||||
attachCommand,
|
||||
checkpointCommand,
|
||||
deleteCommand,
|
||||
execCommand,
|
||||
listCommand,
|
||||
killCommand,
|
||||
pauseCommand,
|
||||
psCommand,
|
||||
resumeCommand,
|
||||
startCommand,
|
||||
},
|
||||
}
|
64
cmd/ctr/commands/tasks/tasks_unix.go
Normal file
64
cmd/ctr/commands/tasks/tasks_unix.go
Normal file
@ -0,0 +1,64 @@
|
||||
// +build !windows
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
gocontext "context"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// HandleConsoleResize resizes the console
|
||||
func HandleConsoleResize(ctx gocontext.Context, task resizer, con console.Console) error {
|
||||
// do an initial resize of the console
|
||||
size, err := con.Size()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil {
|
||||
log.G(ctx).WithError(err).Error("resize pty")
|
||||
}
|
||||
s := make(chan os.Signal, 16)
|
||||
signal.Notify(s, unix.SIGWINCH)
|
||||
go func() {
|
||||
for range s {
|
||||
size, err := con.Size()
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Error("get pty size")
|
||||
continue
|
||||
}
|
||||
if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil {
|
||||
log.G(ctx).WithError(err).Error("resize pty")
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewTask creates a new task
|
||||
func NewTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, checkpoint string, tty, nullIO bool) (containerd.Task, error) {
|
||||
if checkpoint == "" {
|
||||
io := containerd.Stdio
|
||||
if tty {
|
||||
io = containerd.StdioTerminal
|
||||
}
|
||||
if nullIO {
|
||||
if tty {
|
||||
return nil, errors.New("tty and null-io cannot be used together")
|
||||
}
|
||||
io = containerd.NullIO
|
||||
}
|
||||
return container.NewTask(ctx, io)
|
||||
}
|
||||
im, err := client.GetImage(ctx, checkpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return container.NewTask(ctx, containerd.Stdio, containerd.WithTaskCheckpoint(im))
|
||||
}
|
55
cmd/ctr/commands/tasks/tasks_windows.go
Normal file
55
cmd/ctr/commands/tasks/tasks_windows.go
Normal file
@ -0,0 +1,55 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
gocontext "context"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// HandleConsoleResize resizes the console
|
||||
func HandleConsoleResize(ctx gocontext.Context, task resizer, con console.Console) error {
|
||||
// do an initial resize of the console
|
||||
size, err := con.Size()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
prevSize := size
|
||||
for {
|
||||
time.Sleep(time.Millisecond * 250)
|
||||
|
||||
size, err := con.Size()
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Error("get pty size")
|
||||
continue
|
||||
}
|
||||
|
||||
if size.Width != prevSize.Width || size.Height != prevSize.Height {
|
||||
if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil {
|
||||
log.G(ctx).WithError(err).Error("resize pty")
|
||||
}
|
||||
prevSize = size
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewTask creates a new task
|
||||
func NewTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, _ string, tty, nullIO bool) (containerd.Task, error) {
|
||||
io := containerd.Stdio
|
||||
if tty {
|
||||
io = containerd.StdioTerminal
|
||||
}
|
||||
if nullIO {
|
||||
if tty {
|
||||
return nil, errors.New("tty and null-io cannot be used together")
|
||||
}
|
||||
io = containerd.NullIO
|
||||
}
|
||||
return container.NewTask(ctx, io)
|
||||
}
|
@ -12,7 +12,9 @@ import (
|
||||
"github.com/containerd/containerd/cmd/ctr/commands/images"
|
||||
namespacesCmd "github.com/containerd/containerd/cmd/ctr/commands/namespaces"
|
||||
"github.com/containerd/containerd/cmd/ctr/commands/plugins"
|
||||
"github.com/containerd/containerd/cmd/ctr/commands/run"
|
||||
"github.com/containerd/containerd/cmd/ctr/commands/snapshot"
|
||||
"github.com/containerd/containerd/cmd/ctr/commands/tasks"
|
||||
versionCmd "github.com/containerd/containerd/cmd/ctr/commands/version"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/containerd/containerd/server"
|
||||
@ -80,9 +82,9 @@ containerd CLI
|
||||
images.Command,
|
||||
namespacesCmd.Command,
|
||||
pprofCommand,
|
||||
runCommand,
|
||||
run.Command,
|
||||
snapshot.Command,
|
||||
tasksCommand,
|
||||
tasks.Command,
|
||||
}, extraCmds...)
|
||||
app.Before = func(context *cli.Context) error {
|
||||
if context.GlobalBool("debug") {
|
||||
|
@ -1,82 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
// parseMountFlag parses a mount string in the form "type=foo,source=/path,destination=/target,options=rbind:rw"
|
||||
func parseMountFlag(m string) (specs.Mount, error) {
|
||||
mount := specs.Mount{}
|
||||
r := csv.NewReader(strings.NewReader(m))
|
||||
|
||||
fields, err := r.Read()
|
||||
if err != nil {
|
||||
return mount, err
|
||||
}
|
||||
|
||||
for _, field := range fields {
|
||||
v := strings.Split(field, "=")
|
||||
if len(v) != 2 {
|
||||
return mount, fmt.Errorf("invalid mount specification: expected key=val")
|
||||
}
|
||||
|
||||
key := v[0]
|
||||
val := v[1]
|
||||
switch key {
|
||||
case "type":
|
||||
mount.Type = val
|
||||
case "source", "src":
|
||||
mount.Source = val
|
||||
case "destination", "dst":
|
||||
mount.Destination = val
|
||||
case "options":
|
||||
mount.Options = strings.Split(val, ":")
|
||||
default:
|
||||
return mount, fmt.Errorf("mount option %q not supported", key)
|
||||
}
|
||||
}
|
||||
|
||||
return mount, nil
|
||||
}
|
||||
|
||||
// replaceOrAppendEnvValues returns the defaults with the overrides either
|
||||
// replaced by env key or appended to the list
|
||||
func replaceOrAppendEnvValues(defaults, overrides []string) []string {
|
||||
cache := make(map[string]int, len(defaults))
|
||||
for i, e := range defaults {
|
||||
parts := strings.SplitN(e, "=", 2)
|
||||
cache[parts[0]] = i
|
||||
}
|
||||
|
||||
for _, value := range overrides {
|
||||
// Values w/o = means they want this env to be removed/unset.
|
||||
if !strings.Contains(value, "=") {
|
||||
if i, exists := cache[value]; exists {
|
||||
defaults[i] = "" // Used to indicate it should be removed
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Just do a normal set/update
|
||||
parts := strings.SplitN(value, "=", 2)
|
||||
if i, exists := cache[parts[0]]; exists {
|
||||
defaults[i] = value
|
||||
} else {
|
||||
defaults = append(defaults, value)
|
||||
}
|
||||
}
|
||||
|
||||
// Now remove all entries that we want to "unset"
|
||||
for i := 0; i < len(defaults); i++ {
|
||||
if defaults[i] == "" {
|
||||
defaults = append(defaults[:i], defaults[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
|
||||
return defaults
|
||||
}
|
Loading…
Reference in New Issue
Block a user