mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
83f9f18776
Originally, some of the commands' usage display didn't achieved to show newline, while some of them does, which are more user-friendly, and won't confuse the message if there're more which should be in the nextline. Fix this issue by returning usage string with a newline. Signed-off-by: I Hsin Cheng <richard120310@gmail.com>
138 lines
3.4 KiB
Go
138 lines
3.4 KiB
Go
// Copyright 2018 The gVisor Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"text/tabwriter"
|
|
"time"
|
|
|
|
"github.com/google/subcommands"
|
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
|
"gvisor.dev/gvisor/pkg/log"
|
|
"gvisor.dev/gvisor/runsc/cmd/util"
|
|
"gvisor.dev/gvisor/runsc/config"
|
|
"gvisor.dev/gvisor/runsc/container"
|
|
"gvisor.dev/gvisor/runsc/flag"
|
|
)
|
|
|
|
// List implements subcommands.Command for the "list" command.
|
|
type List struct {
|
|
quiet bool
|
|
format string
|
|
sandbox bool
|
|
}
|
|
|
|
// Name implements subcommands.command.name.
|
|
func (*List) Name() string {
|
|
return "list"
|
|
}
|
|
|
|
// Synopsis implements subcommands.Command.Synopsis.
|
|
func (*List) Synopsis() string {
|
|
return "list containers started by runsc with the given root"
|
|
}
|
|
|
|
// Usage implements subcommands.Command.Usage.
|
|
func (*List) Usage() string {
|
|
return "list [flags]\n"
|
|
}
|
|
|
|
// SetFlags implements subcommands.Command.SetFlags.
|
|
func (l *List) SetFlags(f *flag.FlagSet) {
|
|
f.BoolVar(&l.quiet, "quiet", false, "only list container ids")
|
|
f.StringVar(&l.format, "format", "text", "output format: 'text' (default) or 'json'")
|
|
f.BoolVar(&l.sandbox, "sandbox", false, "limit output to sandboxes only")
|
|
}
|
|
|
|
// Execute implements subcommands.Command.Execute.
|
|
func (l *List) Execute(_ context.Context, f *flag.FlagSet, args ...any) subcommands.ExitStatus {
|
|
if f.NArg() != 0 {
|
|
f.Usage()
|
|
return subcommands.ExitUsageError
|
|
}
|
|
|
|
conf := args[0].(*config.Config)
|
|
|
|
if err := l.execute(conf.RootDir, os.Stdout); err != nil {
|
|
util.Fatalf("%v", err)
|
|
}
|
|
return subcommands.ExitSuccess
|
|
}
|
|
|
|
func (l *List) execute(rootDir string, out io.Writer) error {
|
|
var ids []container.FullID
|
|
var err error
|
|
if l.sandbox {
|
|
ids, err = container.ListSandboxes(rootDir)
|
|
} else {
|
|
ids, err = container.List(rootDir)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if l.quiet {
|
|
for _, id := range ids {
|
|
fmt.Fprintln(out, id.ContainerID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Collect the containers.
|
|
var containers []*container.Container
|
|
for _, id := range ids {
|
|
c, err := container.Load(rootDir, id, container.LoadOpts{Exact: true})
|
|
if err != nil {
|
|
log.Warningf("Skipping container %q: %v", id, err)
|
|
continue
|
|
}
|
|
containers = append(containers, c)
|
|
}
|
|
|
|
switch l.format {
|
|
case "text":
|
|
// Print a nice table.
|
|
w := tabwriter.NewWriter(out, 12, 1, 3, ' ', 0)
|
|
fmt.Fprint(w, "ID\tPID\tSTATUS\tBUNDLE\tCREATED\tOWNER\n")
|
|
for _, c := range containers {
|
|
fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\t%s\n",
|
|
c.ID,
|
|
c.SandboxPid(),
|
|
c.Status,
|
|
c.BundleDir,
|
|
c.CreatedAt.Format(time.RFC3339Nano),
|
|
c.Owner)
|
|
}
|
|
_ = w.Flush()
|
|
case "json":
|
|
// Print just the states.
|
|
var states []specs.State
|
|
for _, c := range containers {
|
|
states = append(states, c.State())
|
|
}
|
|
if err := json.NewEncoder(out).Encode(states); err != nil {
|
|
return fmt.Errorf("marshaling container state: %w", err)
|
|
}
|
|
default:
|
|
return fmt.Errorf("unknown list format %q", l.format)
|
|
}
|
|
return nil
|
|
}
|