Merge pull request #1704 from jessvalarezo/ctr-move-tasks

ctr: move commands (tasks, run, pprof, shim)
This commit is contained in:
Phil Estes 2017-11-01 12:57:07 -04:00 committed by GitHub
commit aa3516487c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 312 additions and 355 deletions

View File

@ -20,10 +20,10 @@ var Command = cli.Command{
Usage: "manage containers",
Aliases: []string{"c"},
Subcommands: []cli.Command{
listCommand,
deleteCommand,
setLabelsCommand,
infoCommand,
listCommand,
setLabelsCommand,
},
}

View File

@ -27,16 +27,16 @@ var (
Name: "content",
Usage: "manage content",
Subcommands: cli.Commands{
listCommand,
ingestCommand,
activeIngestCommand,
getCommand,
editCommand,
deleteCommand,
setLabelsCommand,
editCommand,
fetchCommand,
fetchObjectCommand,
getCommand,
ingestCommand,
listCommand,
pushObjectCommand,
setLabelsCommand,
},
}

View File

@ -20,9 +20,9 @@ var Command = cli.Command{
Usage: "manage namespaces",
Subcommands: cli.Commands{
createCommand,
setLabelsCommand,
listCommand,
removeCommand,
setLabelsCommand,
},
}

View File

@ -1,4 +1,4 @@
package main
package pprof
import (
"fmt"
@ -17,7 +17,8 @@ type pprofDialer struct {
addr string
}
var pprofCommand = cli.Command{
// Command is the cli command for providing golang pprof outputs for containerd
var Command = cli.Command{
Name: "pprof",
Usage: "provide golang pprof outputs for containerd",
Flags: []cli.Flag{
@ -28,12 +29,12 @@ var pprofCommand = cli.Command{
},
},
Subcommands: []cli.Command{
pprofBlockCommand,
pprofGoroutinesCommand,
pprofHeapCommand,
pprofProfileCommand,
pprofTraceCommand,
pprofBlockCommand,
pprofThreadcreateCommand,
pprofTraceCommand,
},
}
@ -91,7 +92,7 @@ var pprofTraceCommand = cli.Command{
Flags: []cli.Flag{
cli.DurationFlag{
Name: "seconds,s",
Usage: "Trace time (seconds)",
Usage: "trace time (seconds)",
Value: time.Duration(5 * time.Second),
},
},

View File

@ -1,6 +1,6 @@
// +build !windows
package main
package pprof
import "net"

View File

@ -1,4 +1,4 @@
package main
package pprof
import (
"net"

View File

@ -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 {

View File

@ -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))
}

View File

@ -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)
}

View File

@ -1,6 +1,6 @@
// +build !windows
package main
package shim
import (
gocontext "context"

View File

@ -1,4 +1,4 @@
package main
package shim
import (
"io"

View File

@ -1,6 +1,6 @@
// +build !windows
package main
package shim
import (
"fmt"
@ -45,7 +45,8 @@ var fifoFlags = []cli.Flag{
},
}
var shimCommand = cli.Command{
// Command is the cli command for interacting with a shim
var Command = cli.Command{
Name: "shim",
Usage: "interact with a shim directly",
Flags: []cli.Flag{
@ -55,89 +56,14 @@ var shimCommand = cli.Command{
},
},
Subcommands: []cli.Command{
shimCreateCommand,
shimStartCommand,
shimDeleteCommand,
shimStateCommand,
shimExecCommand,
deleteCommand,
execCommand,
startCommand,
stateCommand,
},
}
var shimCreateCommand = cli.Command{
Name: "create",
Usage: "create a container with a shim",
Flags: append(fifoFlags,
cli.StringFlag{
Name: "bundle",
Usage: "bundle path for the container",
},
cli.StringFlag{
Name: "runtime",
Value: "runc",
Usage: "runtime to use for the container",
},
cli.BoolFlag{
Name: "attach,a",
Usage: "stay attached to the container and open the fifos",
},
),
Action: func(context *cli.Context) error {
var (
id = context.Args().First()
ctx = gocontext.Background()
)
if id == "" {
return errors.New("container id must be provided")
}
service, err := getShimService(context)
if err != nil {
return err
}
tty := context.Bool("tty")
wg, err := prepareStdio(context.String("stdin"), context.String("stdout"), context.String("stderr"), tty)
if err != nil {
return err
}
r, err := service.Create(ctx, &shim.CreateTaskRequest{
ID: id,
Bundle: context.String("bundle"),
Runtime: context.String("runtime"),
Stdin: context.String("stdin"),
Stdout: context.String("stdout"),
Stderr: context.String("stderr"),
Terminal: tty,
})
if err != nil {
return err
}
fmt.Printf("container created with id %s and pid %d\n", id, r.Pid)
if context.Bool("attach") {
if tty {
current := console.Current()
defer current.Reset()
if err := current.SetRaw(); err != nil {
return err
}
size, err := current.Size()
if err != nil {
return err
}
if _, err := service.ResizePty(ctx, &shim.ResizePtyRequest{
ID: id,
Width: uint32(size.Width),
Height: uint32(size.Height),
}); err != nil {
return err
}
}
wg.Wait()
}
return nil
},
}
var shimStartCommand = cli.Command{
var startCommand = cli.Command{
Name: "start",
Usage: "start a container with a shim",
Action: func(context *cli.Context) error {
@ -152,7 +78,7 @@ var shimStartCommand = cli.Command{
},
}
var shimDeleteCommand = cli.Command{
var deleteCommand = cli.Command{
Name: "delete",
Usage: "delete a container with a shim",
Action: func(context *cli.Context) error {
@ -169,7 +95,7 @@ var shimDeleteCommand = cli.Command{
},
}
var shimStateCommand = cli.Command{
var stateCommand = cli.Command{
Name: "state",
Usage: "get the state of all the processes of the shim",
Action: func(context *cli.Context) error {
@ -188,7 +114,7 @@ var shimStateCommand = cli.Command{
},
}
var shimExecCommand = cli.Command{
var execCommand = cli.Command{
Name: "exec",
Usage: "exec a new process in the shim's container",
Flags: append(fifoFlags,

View File

@ -23,17 +23,17 @@ var Command = cli.Command{
Usage: "manage snapshots",
Flags: commands.SnapshotterFlags,
Subcommands: cli.Commands{
listCommand,
usageCommand,
removeCommand,
prepareCommand,
viewCommand,
treeCommand,
mountCommand,
commitCommand,
infoCommand,
listCommand,
mountCommand,
prepareCommand,
removeCommand,
setLabelCommand,
treeCommand,
unpackCommand,
usageCommand,
viewCommand,
},
}

View File

@ -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 {

View File

@ -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",

View File

@ -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",

View File

@ -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 {

View File

@ -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",

View File

@ -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{
Name: "list",
Usage: "list tasks",
Aliases: []string{"ls"},
var listCommand = cli.Command{
Name: "list",
Usage: "list tasks",
Aliases: []string{"ls"},
ArgsUsage: "[flags]",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "quiet, q",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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 {

View 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,
},
}

View 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))
}

View 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)
}

View File

@ -12,7 +12,10 @@ 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/pprof"
"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"
@ -79,10 +82,10 @@ containerd CLI
events.Command,
images.Command,
namespacesCmd.Command,
pprofCommand,
runCommand,
pprof.Command,
run.Command,
snapshot.Command,
tasksCommand,
tasks.Command,
}, extraCmds...)
app.Before = func(context *cli.Context) error {
if context.GlobalBool("debug") {

View File

@ -2,6 +2,8 @@
package main
import "github.com/containerd/containerd/cmd/ctr/commands/shim"
func init() {
extraCmds = append(extraCmds, shimCommand)
extraCmds = append(extraCmds, shim.Command)
}

View File

@ -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
}