Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 31 additions & 13 deletions cmd/ctr/app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import (
"fmt"
"io"

"github.com/containerd/log"
"github.com/urfave/cli/v2"
"google.golang.org/grpc/grpclog"

"github.com/containerd/containerd/v2/cmd/ctr/commands/content"
"github.com/containerd/containerd/v2/cmd/ctr/commands/events"
"github.com/containerd/containerd/v2/cmd/ctr/commands/install"
Expand All @@ -37,9 +41,6 @@ import (
"github.com/containerd/imgcrypt/cmd/ctr/commands/containers"
"github.com/containerd/imgcrypt/cmd/ctr/commands/images"
"github.com/containerd/imgcrypt/cmd/ctr/commands/run"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
"google.golang.org/grpc/grpclog"
)

var extraCmds = []*cli.Command{}
Expand All @@ -48,8 +49,25 @@ func init() {
// Discard grpc logs so that they don't mess with our stdio
grpclog.SetLoggerV2(grpclog.NewLoggerV2(io.Discard, io.Discard, io.Discard))

cli.VersionPrinter = func(c *cli.Context) {
fmt.Println(c.App.Name, version.Package, c.App.Version)
cli.VersionPrinter = func(cliContext *cli.Context) {
fmt.Println(cliContext.App.Name, version.Package, cliContext.App.Version)
}

// Override the default flag descriptions for '--version' and '--help'
// to align with other flags and start with uppercase.
cli.VersionFlag = &cli.BoolFlag{
Name: "version",
Aliases: []string{"v"},
Usage: "Print the version",

DisableDefaultText: true,
}
cli.HelpFlag = &cli.BoolFlag{
Name: "help",
Aliases: []string{"h"},
Usage: "Show help",

DisableDefaultText: true,
}
}

Expand Down Expand Up @@ -77,27 +95,27 @@ containerd CLI
app.Flags = []cli.Flag{
&cli.BoolFlag{
Name: "debug",
Usage: "enable debug output in logs",
Usage: "Enable debug output in logs",
},
&cli.StringFlag{
Name: "address",
Aliases: []string{"a"},
Usage: "address for containerd's GRPC server",
Usage: "Address for containerd's GRPC server",
Value: defaults.DefaultAddress,
EnvVars: []string{"CONTAINERD_ADDRESS"},
},
&cli.DurationFlag{
Name: "timeout",
Usage: "total timeout for ctr commands",
Usage: "Total timeout for ctr commands",
},
&cli.DurationFlag{
Name: "connect-timeout",
Usage: "timeout for connecting to containerd",
Usage: "Timeout for connecting to containerd",
},
&cli.StringFlag{
Name: "namespace",
Aliases: []string{"n"},
Usage: "namespace to use with commands",
Usage: "Namespace to use with commands",
Value: namespaces.Default,
EnvVars: []string{namespaces.NamespaceEnvVar},
},
Expand All @@ -118,9 +136,9 @@ containerd CLI
install.Command,
ociCmd.Command,
}, extraCmds...)
app.Before = func(context *cli.Context) error {
if context.Bool("debug") {
logrus.SetLevel(logrus.DebugLevel)
app.Before = func(cliContext *cli.Context) error {
if cliContext.Bool("debug") {
return log.SetLevel("debug")
}
return nil
}
Expand Down
1 change: 0 additions & 1 deletion cmd/ctr/app/main_unix.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build !windows
// +build !windows

/*
Copyright The containerd Authors.
Expand Down
226 changes: 213 additions & 13 deletions cmd/ctr/commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,219 @@ import (
"path/filepath"
"strings"

"github.com/containerd/containerd/v2/defaults"
"github.com/containerd/containerd/v2/pkg/atomicfile"

"github.com/urfave/cli/v2"
)

var (
// SnapshotterFlags are cli flags specifying snapshotter names
SnapshotterFlags = []cli.Flag{
&cli.StringFlag{
Name: "snapshotter",
Usage: "Snapshotter name. Empty value stands for the default value.",
EnvVars: []string{"CONTAINERD_SNAPSHOTTER"},
},
}

// SnapshotterLabels are cli flags specifying labels which will be added to the new snapshot for container.
SnapshotterLabels = &cli.StringSliceFlag{
Name: "snapshotter-label",
Usage: "Labels added to the new snapshot for this container.",
}

// LabelFlag is a cli flag specifying labels
LabelFlag = &cli.StringSliceFlag{
Name: "label",
Usage: "Labels to attach to the image",
}

// RegistryFlags are cli flags specifying registry options
RegistryFlags = []cli.Flag{
&cli.BoolFlag{
Name: "skip-verify",
Aliases: []string{"k"},
Usage: "Skip SSL certificate validation",
},
&cli.BoolFlag{
Name: "plain-http",
Usage: "Allow connections using plain HTTP",
},
&cli.StringFlag{
Name: "user",
Aliases: []string{"u"},
Usage: "User[:password] Registry user and password",
},
&cli.StringFlag{
Name: "refresh",
Usage: "Refresh token for authorization server",
},
&cli.StringFlag{
Name: "hosts-dir",
// compatible with "/etc/docker/certs.d"
Usage: "Custom hosts configuration directory",
},
&cli.StringFlag{
Name: "tlscacert",
Usage: "Path to TLS root CA",
},
&cli.StringFlag{
Name: "tlscert",
Usage: "Path to TLS client certificate",
},
&cli.StringFlag{
Name: "tlskey",
Usage: "Path to TLS client key",
},
&cli.BoolFlag{
Name: "http-dump",
Usage: "Dump all HTTP request/responses when interacting with container registry",
},
&cli.BoolFlag{
Name: "http-trace",
Usage: "Enable HTTP tracing for registry interactions",
},
}

// RuntimeFlags are cli flags specifying runtime
RuntimeFlags = []cli.Flag{
&cli.StringFlag{
Name: "runtime",
Usage: "Runtime name or absolute path to runtime binary",
Value: defaults.DefaultRuntime,
},
&cli.StringFlag{
Name: "runtime-config-path",
Usage: "Optional runtime config path",
},
}

// ContainerFlags are cli flags specifying container options
ContainerFlags = []cli.Flag{
&cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Usage: "Path to the runtime-specific spec config file",
},
&cli.StringFlag{
Name: "cwd",
Usage: "Specify the working directory of the process",
},
&cli.StringSliceFlag{
Name: "env",
Usage: "Specify additional container environment variables (e.g. FOO=bar)",
},
&cli.StringFlag{
Name: "env-file",
Usage: "Specify additional container environment variables in a file(e.g. FOO=bar, one per line)",
},
&cli.StringSliceFlag{
Name: "label",
Usage: "Specify additional labels (e.g. foo=bar)",
},
&cli.StringSliceFlag{
Name: "annotation",
Usage: "Specify additional OCI annotations (e.g. foo=bar)",
},
&cli.StringSliceFlag{
Name: "mount",
Usage: "Specify additional container mount (e.g. type=bind,src=/tmp,dst=/host,options=rbind:ro)",
},
&cli.BoolFlag{
Name: "net-host",
Usage: "Enable host networking for the container",
},
&cli.BoolFlag{
Name: "privileged",
Usage: "Run privileged container",
},
&cli.BoolFlag{
Name: "read-only",
Usage: "Set the containers filesystem as readonly",
},
&cli.StringFlag{
Name: "sandbox",
Usage: "Create the container in the given sandbox",
},
&cli.BoolFlag{
Name: "tty",
Aliases: []string{"t"},
Usage: "Allocate a TTY for the container",
},
&cli.StringSliceFlag{
Name: "with-ns",
Usage: "Specify existing Linux namespaces to join at container runtime (format '<nstype>:<path>')",
},
&cli.StringFlag{
Name: "pid-file",
Usage: "File path to write the task's pid",
},
&cli.IntSliceFlag{
Name: "gpus",
Usage: "Add gpus to the container",
},
&cli.BoolFlag{
Name: "allow-new-privs",
Usage: "Turn off OCI spec's NoNewPrivileges feature flag",
},
&cli.Uint64Flag{
Name: "memory-limit",
Usage: "Memory limit (in bytes) for the container",
},
&cli.StringSliceFlag{
Name: "cap-add",
Usage: "Add Linux capabilities (Set capabilities with 'CAP_' prefix)",
},
&cli.StringSliceFlag{
Name: "cap-drop",
Usage: "Drop Linux capabilities (Set capabilities with 'CAP_' prefix)",
},
&cli.BoolFlag{
Name: "seccomp",
Usage: "Enable the default seccomp profile",
},
&cli.StringFlag{
Name: "seccomp-profile",
Usage: "File path to custom seccomp profile. seccomp must be set to true, before using seccomp-profile",
},
&cli.StringFlag{
Name: "apparmor-default-profile",
Usage: "Enable AppArmor with the default profile with the specified name, e.g. \"cri-containerd.apparmor.d\"",
},
&cli.StringFlag{
Name: "apparmor-profile",
Usage: "Enable AppArmor with an existing custom profile",
},
&cli.StringFlag{
Name: "blockio-config-file",
Usage: "File path to blockio class definitions. By default class definitions are not loaded.",
},
&cli.StringFlag{
Name: "blockio-class",
Usage: "Name of the blockio class to associate the container with",
},
&cli.StringFlag{
Name: "rdt-class",
Usage: "Name of the RDT class to associate the container with. Specifies a Class of Service (CLOS) for cache and memory bandwidth management.",
},
&cli.StringFlag{
Name: "hostname",
Usage: "Set the container's host name",
},
&cli.StringFlag{
Name: "user",
Aliases: []string{"u"},
Usage: "Username or user id, group optional (format: <name|uid>[:<group|gid>])",
},
}
)

// ObjectWithLabelArgs returns the first arg and a LabelArgs object
func ObjectWithLabelArgs(clicontext *cli.Context) (string, map[string]string) {
func ObjectWithLabelArgs(cliContext *cli.Context) (string, map[string]string) {
var (
first = clicontext.Args().First()
labelStrings = clicontext.Args().Tail()
first = cliContext.Args().First()
labelStrings = cliContext.Args().Tail()
)

return first, LabelArgs(labelStrings)
Expand All @@ -42,13 +245,10 @@ func ObjectWithLabelArgs(clicontext *cli.Context) (string, map[string]string) {
func LabelArgs(labelStrings []string) map[string]string {
labels := make(map[string]string, len(labelStrings))
for _, label := range labelStrings {
parts := strings.SplitN(label, "=", 2)
key := parts[0]
value := "true"
if len(parts) > 1 {
value = parts[1]
key, value, ok := strings.Cut(label, "=")
if !ok {
value = "true"
}

labels[key] = value
}

Expand All @@ -59,17 +259,17 @@ func LabelArgs(labelStrings []string) map[string]string {
func AnnotationArgs(annoStrings []string) (map[string]string, error) {
annotations := make(map[string]string, len(annoStrings))
for _, anno := range annoStrings {
parts := strings.SplitN(anno, "=", 2)
if len(parts) != 2 {
key, value, ok := strings.Cut(anno, "=")
if !ok {
return nil, fmt.Errorf("invalid key=value format annotation: %v", anno)
}
annotations[parts[0]] = parts[1]
annotations[key] = value
}
return annotations, nil
}

// PrintAsJSON prints input in JSON format
func PrintAsJSON(x interface{}) {
func PrintAsJSON(x any) {
b, err := json.MarshalIndent(x, "", " ")
if err != nil {
fmt.Fprintf(os.Stderr, "can't marshal %+v as a JSON string: %v\n", x, err)
Expand Down
Loading
Loading