// 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" "fmt" "github.com/google/subcommands" "gvisor.dev/gvisor/runsc/flag" ) // NewHelp returns a help command for the given commander. func NewHelp(cdr *subcommands.Commander) *Help { return &Help{ cdr: cdr, } } // Help implements subcommands.Command for the "help" command. The 'help' // command prints help for commands registered to a Commander but also allows for // registering additional help commands that print other documentation. type Help struct { cdr *subcommands.Commander commands []subcommands.Command help bool } // Name implements subcommands.Command.Name. func (*Help) Name() string { return "help" } // Synopsis implements subcommands.Command.Synopsis. func (*Help) Synopsis() string { return "Print help documentation." } // Usage implements subcommands.Command.Usage. func (*Help) Usage() string { return `help [<subcommand>]: With an argument, prints detailed information on the use of the specified topic or subcommand. With no argument, print a list of all commands and a brief description of each. ` } // SetFlags implements subcommands.Command.SetFlags. func (h *Help) SetFlags(f *flag.FlagSet) {} // Execute implements subcommands.Command.Execute. func (h *Help) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { switch f.NArg() { case 0: fmt.Fprintf(h.cdr.Output, "Usage: %s <flags> <subcommand> <subcommand args>\n\n", h.cdr.Name()) fmt.Fprintf(h.cdr.Output, `runsc is a command line client for running applications packaged in the Open Container Initiative (OCI) format. Applications run by runsc are run in an isolated gVisor sandbox that emulates a Linux environment. gVisor is a user-space kernel, written in Go, that implements a substantial portion of the Linux system call interface. It provides an additional layer of isolation between running applications and the host operating system. Functionality is provided by subcommands. For additonal help on individual subcommands use "%s %s <subcommand>". `, h.cdr.Name(), h.Name()) h.cdr.VisitGroups(func(g *subcommands.CommandGroup) { h.cdr.ExplainGroup(h.cdr.Output, g) }) fmt.Fprintf(h.cdr.Output, "Additional help topics (Use \"%s %s <topic>\" to see help on the topic):\n", h.cdr.Name(), h.Name()) for _, cmd := range h.commands { fmt.Fprintf(h.cdr.Output, "\t%-15s %s\n", cmd.Name(), cmd.Synopsis()) } fmt.Fprintf(h.cdr.Output, "\nUse \"%s flags\" for a list of top-level flags\n", h.cdr.Name()) return subcommands.ExitSuccess default: // Look for commands registered to the commander and print help explanation if found. found := false h.cdr.VisitCommands(func(g *subcommands.CommandGroup, cmd subcommands.Command) { if f.Arg(0) == cmd.Name() { h.cdr.ExplainCommand(h.cdr.Output, cmd) found = true } }) if found { return subcommands.ExitSuccess } // Next check commands registered to the help command. for _, cmd := range h.commands { if f.Arg(0) == cmd.Name() { fs := flag.NewFlagSet(f.Arg(0), flag.ContinueOnError) fs.Usage = func() { h.cdr.ExplainCommand(h.cdr.Error, cmd) } cmd.SetFlags(fs) if fs.Parse(f.Args()[1:]) != nil { return subcommands.ExitUsageError } return cmd.Execute(ctx, f, args...) } } fmt.Fprintf(h.cdr.Error, "Subcommand %s not understood\n", f.Arg(0)) } f.Usage() return subcommands.ExitUsageError } // Register registers a new help command. func (h *Help) Register(cmd subcommands.Command) { h.commands = append(h.commands, cmd) }