mirror of https://github.com/docker/cli.git
Convert docker root command to use pflag and cobra
Fix the daemon proxy for cobra commands. Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
parent
23dd85befd
commit
08784d7e0e
18
daemon.go
18
daemon.go
|
@ -1,18 +0,0 @@
|
|||
package main
|
||||
|
||||
const daemonBinary = "dockerd"
|
||||
|
||||
// DaemonProxy acts as a cli.Handler to proxy calls to the daemon binary
|
||||
type DaemonProxy struct{}
|
||||
|
||||
// NewDaemonProxy returns a new handler
|
||||
func NewDaemonProxy() DaemonProxy {
|
||||
return DaemonProxy{}
|
||||
}
|
||||
|
||||
// Command returns a cli command handler if one exists
|
||||
func (p DaemonProxy) Command(name string) func(...string) error {
|
||||
return map[string]func(...string) error{
|
||||
"daemon": p.CmdDaemon,
|
||||
}[name]
|
||||
}
|
|
@ -4,12 +4,22 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// CmdDaemon reports on an error on windows, because there is no exec
|
||||
func (p DaemonProxy) CmdDaemon(args ...string) error {
|
||||
func newDaemonCommand() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "daemon",
|
||||
Hidden: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runDaemon()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func runDaemon() error {
|
||||
return fmt.Errorf(
|
||||
"`docker daemon` is not supported on %s. Please run `dockerd` directly",
|
||||
strings.Title(runtime.GOOS))
|
||||
|
|
|
@ -3,23 +3,37 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// CmdDaemon execs dockerd with the same flags
|
||||
func (p DaemonProxy) CmdDaemon(args ...string) error {
|
||||
// Special case for handling `docker help daemon`. When pkg/mflag is removed
|
||||
// we can support this on the daemon side, but that is not possible with
|
||||
// pkg/mflag because it uses os.Exit(1) instead of returning an error on
|
||||
// unexpected args.
|
||||
if len(args) == 0 || args[0] != "--help" {
|
||||
// Use os.Args[1:] so that "global" args are passed to dockerd
|
||||
args = stripDaemonArg(os.Args[1:])
|
||||
const daemonBinary = "dockerd"
|
||||
|
||||
func newDaemonCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "daemon",
|
||||
Hidden: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runDaemon()
|
||||
},
|
||||
}
|
||||
cmd.SetHelpFunc(helpFunc)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// CmdDaemon execs dockerd with the same flags
|
||||
func runDaemon() error {
|
||||
// Use os.Args[1:] so that "global" args are passed to dockerd
|
||||
return execDaemon(stripDaemonArg(os.Args[1:]))
|
||||
}
|
||||
|
||||
func execDaemon(args []string) error {
|
||||
binaryPath, err := findDaemonBinary()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -31,6 +45,12 @@ func (p DaemonProxy) CmdDaemon(args ...string) error {
|
|||
os.Environ())
|
||||
}
|
||||
|
||||
func helpFunc(cmd *cobra.Command, args []string) {
|
||||
if err := execDaemon([]string{"--help"}); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// findDaemonBinary looks for the path to the dockerd binary starting with
|
||||
// the directory of the current executable (if one exists) and followed by $PATH
|
||||
func findDaemonBinary() (string, error) {
|
||||
|
|
108
docker.go
108
docker.go
|
@ -12,64 +12,52 @@ import (
|
|||
cliflags "github.com/docker/docker/cli/flags"
|
||||
"github.com/docker/docker/cliconfig"
|
||||
"github.com/docker/docker/dockerversion"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/docker/docker/utils"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var (
|
||||
commonFlags = cliflags.InitCommonFlags()
|
||||
clientFlags = initClientFlags(commonFlags)
|
||||
flHelp = flag.Bool([]string{"h", "-help"}, false, "Print usage")
|
||||
flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
|
||||
)
|
||||
func newDockerCommand(dockerCli *client.DockerCli, opts *cliflags.ClientOptions) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "docker [OPTIONS] COMMAND [arg...]",
|
||||
Short: "A self-sufficient runtime for containers.",
|
||||
SilenceUsage: true,
|
||||
SilenceErrors: true,
|
||||
Args: cli.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if opts.Version {
|
||||
showVersion()
|
||||
return nil
|
||||
}
|
||||
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
|
||||
return nil
|
||||
},
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
dockerPreRun(cmd.Flags(), opts)
|
||||
return dockerCli.Initialize(opts)
|
||||
},
|
||||
}
|
||||
cobraadaptor.SetupRootCommand(cmd, dockerCli)
|
||||
|
||||
flags := cmd.Flags()
|
||||
flags.BoolVarP(&opts.Version, "version", "v", false, "Print version information and quit")
|
||||
flags.StringVar(&opts.ConfigDir, "config", cliconfig.ConfigDir(), "Location of client config files")
|
||||
opts.Common.InstallFlags(flags)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Set terminal emulation based on platform as required.
|
||||
stdin, stdout, stderr := term.StdStreams()
|
||||
|
||||
logrus.SetOutput(stderr)
|
||||
|
||||
flag.Merge(flag.CommandLine, clientFlags.FlagSet, commonFlags.FlagSet)
|
||||
opts := cliflags.NewClientOptions()
|
||||
dockerCli := client.NewDockerCli(stdin, stdout, stderr, opts)
|
||||
cmd := newDockerCommand(dockerCli, opts)
|
||||
|
||||
cobraAdaptor := cobraadaptor.NewCobraAdaptor(clientFlags)
|
||||
|
||||
flag.Usage = func() {
|
||||
fmt.Fprint(stdout, "Usage: docker [OPTIONS] COMMAND [arg...]\n docker [ --help | -v | --version ]\n\n")
|
||||
fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n")
|
||||
|
||||
flag.CommandLine.SetOutput(stdout)
|
||||
flag.PrintDefaults()
|
||||
|
||||
help := "\nCommands:\n"
|
||||
|
||||
dockerCommands := append(cli.DockerCommandUsage, cobraAdaptor.Usage()...)
|
||||
for _, cmd := range sortCommands(dockerCommands) {
|
||||
help += fmt.Sprintf(" %-10.10s%s\n", cmd.Name, cmd.Description)
|
||||
}
|
||||
|
||||
help += "\nRun 'docker COMMAND --help' for more information on a command."
|
||||
fmt.Fprintf(stdout, "%s\n", help)
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if *flVersion {
|
||||
showVersion()
|
||||
return
|
||||
}
|
||||
|
||||
if *flHelp {
|
||||
// if global flag --help is present, regardless of what other options and commands there are,
|
||||
// just print the usage.
|
||||
flag.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
clientCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags)
|
||||
|
||||
c := cli.New(clientCli, NewDaemonProxy(), cobraAdaptor)
|
||||
if err := c.Run(flag.Args()...); err != nil {
|
||||
if err := cmd.Execute(); err != nil {
|
||||
if sterr, ok := err.(cli.StatusError); ok {
|
||||
if sterr.Status != "" {
|
||||
fmt.Fprintln(stderr, sterr.Status)
|
||||
|
@ -94,26 +82,22 @@ func showVersion() {
|
|||
}
|
||||
}
|
||||
|
||||
func initClientFlags(commonFlags *cliflags.CommonFlags) *cliflags.ClientFlags {
|
||||
clientFlags := &cliflags.ClientFlags{FlagSet: new(flag.FlagSet), Common: commonFlags}
|
||||
client := clientFlags.FlagSet
|
||||
client.StringVar(&clientFlags.ConfigDir, []string{"-config"}, cliconfig.ConfigDir(), "Location of client config files")
|
||||
func dockerPreRun(flags *pflag.FlagSet, opts *cliflags.ClientOptions) {
|
||||
opts.Common.SetDefaultOptions(flags)
|
||||
cliflags.SetDaemonLogLevel(opts.Common.LogLevel)
|
||||
|
||||
clientFlags.PostParse = func() {
|
||||
clientFlags.Common.PostParse()
|
||||
cliflags.SetDaemonLogLevel(commonOpts.LogLevel)
|
||||
|
||||
if clientFlags.ConfigDir != "" {
|
||||
cliconfig.SetConfigDir(clientFlags.ConfigDir)
|
||||
// TODO: remove this, set a default in New, and pass it in opts
|
||||
if opts.ConfigDir != "" {
|
||||
cliconfig.SetConfigDir(opts.ConfigDir)
|
||||
}
|
||||
|
||||
if clientFlags.Common.TrustKey == "" {
|
||||
clientFlags.Common.TrustKey = filepath.Join(cliconfig.ConfigDir(), cliflags.DefaultTrustKeyFile)
|
||||
if opts.Common.TrustKey == "" {
|
||||
opts.Common.TrustKey = filepath.Join(
|
||||
cliconfig.ConfigDir(),
|
||||
cliflags.DefaultTrustKeyFile)
|
||||
}
|
||||
|
||||
if clientFlags.Common.Debug {
|
||||
if opts.Common.Debug {
|
||||
utils.EnableDebug()
|
||||
}
|
||||
}
|
||||
return clientFlags
|
||||
}
|
||||
|
|
|
@ -6,13 +6,21 @@ import (
|
|||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/utils"
|
||||
|
||||
"github.com/docker/docker/api/client"
|
||||
cliflags "github.com/docker/docker/cli/flags"
|
||||
)
|
||||
|
||||
func TestClientDebugEnabled(t *testing.T) {
|
||||
defer utils.DisableDebug()
|
||||
|
||||
clientFlags.Common.FlagSet.Parse([]string{"-D"})
|
||||
clientFlags.PostParse()
|
||||
opts := cliflags.NewClientOptions()
|
||||
cmd := newDockerCommand(&client.DockerCli{}, opts)
|
||||
|
||||
opts.Common.Debug = true
|
||||
if err := cmd.PersistentPreRunE(cmd, []string{}); err != nil {
|
||||
t.Fatalf("Unexpected error: %s", err.Error())
|
||||
}
|
||||
|
||||
if os.Getenv("DEBUG") != "1" {
|
||||
t.Fatal("expected debug enabled, got false")
|
||||
|
|
Loading…
Reference in New Issue