Merge pull request #26025 from dnephin/cli-new-command-structure

Restructure CLI Commands
This commit is contained in:
Sebastiaan van Stijn 2016-09-19 22:23:37 +02:00 committed by GitHub
commit ad9ceff3b3
18 changed files with 326 additions and 52 deletions

View file

@ -9,6 +9,11 @@ import (
// SetupRootCommand sets default usage, help, and error handling for the
// root command.
func SetupRootCommand(rootCmd *cobra.Command) {
cobra.AddTemplateFunc("hasSubCommands", hasSubCommands)
cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands)
cobra.AddTemplateFunc("operationSubCommands", operationSubCommands)
cobra.AddTemplateFunc("managementSubCommands", managementSubCommands)
rootCmd.SetUsageTemplate(usageTemplate)
rootCmd.SetHelpTemplate(helpTemplate)
rootCmd.SetFlagErrorFunc(FlagErrorFunc)
@ -34,23 +39,81 @@ func FlagErrorFunc(cmd *cobra.Command, err error) error {
}
}
var usageTemplate = `Usage: {{if not .HasSubCommands}}{{.UseLine}}{{end}}{{if .HasSubCommands}}{{ .CommandPath}} COMMAND{{end}}
func hasSubCommands(cmd *cobra.Command) bool {
return len(operationSubCommands(cmd)) > 0
}
{{ .Short | trim }}{{if gt .Aliases 0}}
func hasManagementSubCommands(cmd *cobra.Command) bool {
return len(managementSubCommands(cmd)) > 0
}
func operationSubCommands(cmd *cobra.Command) []*cobra.Command {
cmds := []*cobra.Command{}
for _, sub := range cmd.Commands() {
if sub.IsAvailableCommand() && !sub.HasSubCommands() {
cmds = append(cmds, sub)
}
}
return cmds
}
func managementSubCommands(cmd *cobra.Command) []*cobra.Command {
cmds := []*cobra.Command{}
for _, sub := range cmd.Commands() {
if sub.IsAvailableCommand() && sub.HasSubCommands() {
cmds = append(cmds, sub)
}
}
return cmds
}
var usageTemplate = `Usage:
{{- if not .HasSubCommands}} {{.UseLine}}{{end}}
{{- if .HasSubCommands}} {{ .CommandPath}} COMMAND{{end}}
{{ .Short | trim }}
{{- if gt .Aliases 0}}
Aliases:
{{.NameAndAliases}}{{end}}{{if .HasExample}}
{{.NameAndAliases}}
{{- end}}
{{- if .HasExample}}
Examples:
{{ .Example }}{{end}}{{if .HasFlags}}
{{ .Example }}
{{- end}}
{{- if .HasFlags}}
Options:
{{.Flags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableSubCommands}}
{{.Flags.FlagUsages | trimRightSpace}}
Commands:{{range .Commands}}{{if .IsAvailableCommand}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasSubCommands }}
{{- end}}
{{- if hasManagementSubCommands . }}
Run '{{.CommandPath}} COMMAND --help' for more information on a command.{{end}}
Management Commands:
{{- range managementSubCommands . }}
{{rpad .Name .NamePadding }} {{.Short}}
{{- end}}
{{- end}}
{{- if hasSubCommands .}}
Commands:
{{- range operationSubCommands . }}
{{rpad .Name .NamePadding }} {{.Short}}
{{- end}}
{{- end}}
{{- if .HasSubCommands }}
Run '{{.CommandPath}} COMMAND --help' for more information on a command.
{{- end}}
`
var helpTemplate = `

View file

@ -15,7 +15,7 @@ import (
func NewCheckpointCommand(rootCmd *cobra.Command, dockerCli *command.DockerCli) {
cmd := &cobra.Command{
Use: "checkpoint",
Short: "Manage Container Checkpoints",
Short: "Manage checkpoints",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())

View file

@ -1,6 +1,8 @@
package commands
import (
"os"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/cli/command/checkpoint"
"github.com/docker/docker/cli/command/container"
@ -25,49 +27,61 @@ func AddCommands(cmd *cobra.Command, dockerCli *command.DockerCli) {
stack.NewStackCommand(dockerCli),
stack.NewTopLevelDeployCommand(dockerCli),
swarm.NewSwarmCommand(dockerCli),
container.NewAttachCommand(dockerCli),
container.NewCommitCommand(dockerCli),
container.NewCopyCommand(dockerCli),
container.NewCreateCommand(dockerCli),
container.NewDiffCommand(dockerCli),
container.NewExecCommand(dockerCli),
container.NewExportCommand(dockerCli),
container.NewKillCommand(dockerCli),
container.NewLogsCommand(dockerCli),
container.NewPauseCommand(dockerCli),
container.NewPortCommand(dockerCli),
container.NewPsCommand(dockerCli),
container.NewRenameCommand(dockerCli),
container.NewRestartCommand(dockerCli),
container.NewRmCommand(dockerCli),
container.NewContainerCommand(dockerCli),
image.NewImageCommand(dockerCli),
container.NewRunCommand(dockerCli),
container.NewStartCommand(dockerCli),
container.NewStatsCommand(dockerCli),
container.NewStopCommand(dockerCli),
container.NewTopCommand(dockerCli),
container.NewUnpauseCommand(dockerCli),
container.NewUpdateCommand(dockerCli),
container.NewWaitCommand(dockerCli),
image.NewBuildCommand(dockerCli),
image.NewHistoryCommand(dockerCli),
image.NewImagesCommand(dockerCli),
image.NewLoadCommand(dockerCli),
image.NewRemoveCommand(dockerCli),
image.NewSaveCommand(dockerCli),
image.NewPullCommand(dockerCli),
image.NewPushCommand(dockerCli),
image.NewSearchCommand(dockerCli),
image.NewImportCommand(dockerCli),
image.NewTagCommand(dockerCli),
network.NewNetworkCommand(dockerCli),
system.NewEventsCommand(dockerCli),
system.NewInspectCommand(dockerCli),
registry.NewLoginCommand(dockerCli),
registry.NewLogoutCommand(dockerCli),
registry.NewSearchCommand(dockerCli),
system.NewVersionCommand(dockerCli),
volume.NewVolumeCommand(dockerCli),
system.NewInfoCommand(dockerCli),
hide(container.NewAttachCommand(dockerCli)),
hide(container.NewCommitCommand(dockerCli)),
hide(container.NewCopyCommand(dockerCli)),
hide(container.NewCreateCommand(dockerCli)),
hide(container.NewDiffCommand(dockerCli)),
hide(container.NewExecCommand(dockerCli)),
hide(container.NewExportCommand(dockerCli)),
hide(container.NewKillCommand(dockerCli)),
hide(container.NewLogsCommand(dockerCli)),
hide(container.NewPauseCommand(dockerCli)),
hide(container.NewPortCommand(dockerCli)),
hide(container.NewPsCommand(dockerCli)),
hide(container.NewRenameCommand(dockerCli)),
hide(container.NewRestartCommand(dockerCli)),
hide(container.NewRmCommand(dockerCli)),
hide(container.NewStartCommand(dockerCli)),
hide(container.NewStatsCommand(dockerCli)),
hide(container.NewStopCommand(dockerCli)),
hide(container.NewTopCommand(dockerCli)),
hide(container.NewUnpauseCommand(dockerCli)),
hide(container.NewUpdateCommand(dockerCli)),
hide(container.NewWaitCommand(dockerCli)),
hide(image.NewHistoryCommand(dockerCli)),
hide(image.NewImagesCommand(dockerCli)),
hide(image.NewImportCommand(dockerCli)),
hide(image.NewLoadCommand(dockerCli)),
hide(image.NewPullCommand(dockerCli)),
hide(image.NewPushCommand(dockerCli)),
hide(image.NewRemoveCommand(dockerCli)),
hide(image.NewSaveCommand(dockerCli)),
hide(image.NewTagCommand(dockerCli)),
hide(system.NewInspectCommand(dockerCli)),
)
checkpoint.NewCheckpointCommand(cmd, dockerCli)
plugin.NewPluginCommand(cmd, dockerCli)
}
func hide(cmd *cobra.Command) *cobra.Command {
if os.Getenv("DOCKER_HIDE_LEGACY_COMMANDS") == "" {
return cmd
}
cmdCopy := *cmd
cmdCopy.Hidden = true
cmdCopy.Aliases = []string{}
return &cmdCopy
}

View file

@ -0,0 +1,49 @@
package container
import (
"fmt"
"github.com/spf13/cobra"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
)
// NewContainerCommand returns a cobra command for `container` subcommands
func NewContainerCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "container",
Short: "Manage containers",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
},
}
cmd.AddCommand(
NewAttachCommand(dockerCli),
NewCommitCommand(dockerCli),
NewCopyCommand(dockerCli),
NewCreateCommand(dockerCli),
NewDiffCommand(dockerCli),
NewExecCommand(dockerCli),
NewExportCommand(dockerCli),
NewKillCommand(dockerCli),
NewLogsCommand(dockerCli),
NewPauseCommand(dockerCli),
NewPortCommand(dockerCli),
NewRenameCommand(dockerCli),
NewRestartCommand(dockerCli),
NewRmCommand(dockerCli),
NewRunCommand(dockerCli),
NewStartCommand(dockerCli),
NewStatsCommand(dockerCli),
NewStopCommand(dockerCli),
NewTopCommand(dockerCli),
NewUnpauseCommand(dockerCli),
NewUpdateCommand(dockerCli),
NewWaitCommand(dockerCli),
newListCommand(dockerCli),
newInspectCommand(dockerCli),
)
return cmd
}

View file

@ -0,0 +1,47 @@
package container
import (
"golang.org/x/net/context"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/cli/command/inspect"
"github.com/spf13/cobra"
)
type inspectOptions struct {
format string
size bool
refs []string
}
// newInspectCommand creates a new cobra.Command for `docker container inspect`
func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
var opts inspectOptions
cmd := &cobra.Command{
Use: "inspect [OPTIONS] CONTAINER [CONTAINER...]",
Short: "Display detailed information on one or more containers",
Args: cli.RequiresMinArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.refs = args
return runInspect(dockerCli, opts)
},
}
flags := cmd.Flags()
flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given go template")
flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes")
return cmd
}
func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
client := dockerCli.Client()
ctx := context.Background()
getRefFunc := func(ref string) (interface{}, []byte, error) {
return client.ContainerInspectWithRaw(ctx, ref, opts.size)
}
return inspect.Inspect(dockerCli.Out(), opts.refs, opts.format, getRefFunc)
}

View file

@ -52,6 +52,13 @@ func NewPsCommand(dockerCli *command.DockerCli) *cobra.Command {
return cmd
}
func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := *NewPsCommand(dockerCli)
cmd.Aliases = []string{"ps", "list"}
cmd.Use = "ls [OPTIONS]"
return &cmd
}
type preProcessor struct {
types.Container
opts *types.ContainerListOptions

36
cli/command/image/cmd.go Normal file
View file

@ -0,0 +1,36 @@
package image
import (
"fmt"
"github.com/spf13/cobra"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
)
// NewImageCommand returns a cobra command for `image` subcommands
func NewImageCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "image",
Short: "Manage images",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
},
}
cmd.AddCommand(
NewBuildCommand(dockerCli),
NewHistoryCommand(dockerCli),
NewImportCommand(dockerCli),
NewLoadCommand(dockerCli),
NewPullCommand(dockerCli),
NewPushCommand(dockerCli),
NewSaveCommand(dockerCli),
NewTagCommand(dockerCli),
newListCommand(dockerCli),
newRemoveCommand(dockerCli),
newInspectCommand(dockerCli),
)
return cmd
}

View file

@ -0,0 +1,44 @@
package image
import (
"golang.org/x/net/context"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/cli/command/inspect"
"github.com/spf13/cobra"
)
type inspectOptions struct {
format string
refs []string
}
// newInspectCommand creates a new cobra.Command for `docker image inspect`
func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
var opts inspectOptions
cmd := &cobra.Command{
Use: "inspect [OPTIONS] IMAGE [IMAGE...]",
Short: "Display detailed information on one or more images",
Args: cli.RequiresMinArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.refs = args
return runInspect(dockerCli, opts)
},
}
flags := cmd.Flags()
flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given go template")
return cmd
}
func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
client := dockerCli.Client()
ctx := context.Background()
getRefFunc := func(ref string) (interface{}, []byte, error) {
return client.ImageInspectWithRaw(ctx, ref)
}
return inspect.Inspect(dockerCli.Out(), opts.refs, opts.format, getRefFunc)
}

View file

@ -50,6 +50,13 @@ func NewImagesCommand(dockerCli *command.DockerCli) *cobra.Command {
return cmd
}
func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := *NewImagesCommand(dockerCli)
cmd.Aliases = []string{"images", "list"}
cmd.Use = "ls [OPTIONS] [REPOSITORY[:TAG]]"
return &cmd
}
func runImages(dockerCli *command.DockerCli, opts imagesOptions) error {
ctx := context.Background()

View file

@ -38,6 +38,13 @@ func NewRemoveCommand(dockerCli *command.DockerCli) *cobra.Command {
return cmd
}
func newRemoveCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := *NewRemoveCommand(dockerCli)
cmd.Aliases = []string{"rmi", "remove"}
cmd.Use = "rm [OPTIONS] IMAGE [IMAGE...]"
return &cmd
}
func runRemove(dockerCli *command.DockerCli, opts removeOptions, images []string) error {
client := dockerCli.Client()
ctx := context.Background()

View file

@ -13,7 +13,7 @@ import (
func NewNetworkCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "network",
Short: "Manage Docker networks",
Short: "Manage networks",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())

View file

@ -14,7 +14,7 @@ import (
func NewNodeCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "node",
Short: "Manage Docker Swarm nodes",
Short: "Manage Swarm nodes",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())

View file

@ -14,7 +14,7 @@ import (
func NewPluginCommand(rootCmd *cobra.Command, dockerCli *command.DockerCli) {
cmd := &cobra.Command{
Use: "plugin",
Short: "Manage Docker plugins",
Short: "Manage plugins",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())

View file

@ -1,4 +1,4 @@
package image
package registry
import (
"fmt"

View file

@ -13,7 +13,7 @@ import (
func NewServiceCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "service",
Short: "Manage Docker services",
Short: "Manage services",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())

View file

@ -14,7 +14,7 @@ import (
func NewStackCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "stack",
Short: "Manage Docker stacks",
Short: "Manage stacks",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
@ -32,8 +32,8 @@ func NewStackCommand(dockerCli *command.DockerCli) *cobra.Command {
// NewTopLevelDeployCommand returns a command for `docker deploy`
func NewTopLevelDeployCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := newDeployCommand(dockerCli)
cmd := *newDeployCommand(dockerCli)
// Remove the aliases at the top level
cmd.Aliases = []string{}
return cmd
return &cmd
}

View file

@ -13,7 +13,7 @@ import (
func NewSwarmCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "swarm",
Short: "Manage Docker Swarm",
Short: "Manage Swarm",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())

View file

@ -13,7 +13,7 @@ import (
func NewVolumeCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "volume COMMAND",
Short: "Manage Docker volumes",
Short: "Manage volumes",
Long: volumeDescription,
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {