diff --git a/cli/cobra.go b/cli/cobra.go index 7f35abe50c..cb1cf8527a 100644 --- a/cli/cobra.go +++ b/cli/cobra.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path/filepath" + "sort" "strings" pluginmanager "github.com/docker/cli/cli-plugins/manager" @@ -12,6 +13,7 @@ import ( cliflags "github.com/docker/cli/cli/flags" "github.com/docker/docker/pkg/homedir" "github.com/docker/docker/registry" + "github.com/fvbommel/sortorder" "github.com/moby/term" "github.com/morikuni/aec" "github.com/pkg/errors" @@ -30,10 +32,14 @@ func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *p cobra.AddTemplateFunc("add", func(a, b int) int { return a + b }) cobra.AddTemplateFunc("hasSubCommands", hasSubCommands) + cobra.AddTemplateFunc("hasTopCommands", hasTopCommands) cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands) + cobra.AddTemplateFunc("hasSwarmSubCommands", hasSwarmSubCommands) cobra.AddTemplateFunc("hasInvalidPlugins", hasInvalidPlugins) + cobra.AddTemplateFunc("topCommands", topCommands) cobra.AddTemplateFunc("operationSubCommands", operationSubCommands) cobra.AddTemplateFunc("managementSubCommands", managementSubCommands) + cobra.AddTemplateFunc("orchestratorSubCommands", orchestratorSubCommands) cobra.AddTemplateFunc("invalidPlugins", invalidPlugins) cobra.AddTemplateFunc("wrappedFlagUsages", wrappedFlagUsages) cobra.AddTemplateFunc("vendorAndVersion", vendorAndVersion) @@ -240,16 +246,51 @@ func hasManagementSubCommands(cmd *cobra.Command) bool { return len(managementSubCommands(cmd)) > 0 } +func hasSwarmSubCommands(cmd *cobra.Command) bool { + return len(orchestratorSubCommands(cmd)) > 0 +} + func hasInvalidPlugins(cmd *cobra.Command) bool { return len(invalidPlugins(cmd)) > 0 } +func hasTopCommands(cmd *cobra.Command) bool { + return len(topCommands(cmd)) > 0 +} + +func topCommands(cmd *cobra.Command) []*cobra.Command { + cmds := []*cobra.Command{} + if cmd.Parent() != nil { + // for now, only use top-commands for the root-command, and skip + // for sub-commands + return cmds + } + for _, sub := range cmd.Commands() { + if isPlugin(sub) || !sub.IsAvailableCommand() { + continue + } + if _, ok := sub.Annotations["category-top"]; ok { + cmds = append(cmds, sub) + } + } + sort.SliceStable(cmds, func(i, j int) bool { + return sortorder.NaturalLess(cmds[i].Annotations["category-top"], cmds[j].Annotations["category-top"]) + }) + return cmds +} + func operationSubCommands(cmd *cobra.Command) []*cobra.Command { cmds := []*cobra.Command{} for _, sub := range cmd.Commands() { if isPlugin(sub) { continue } + if _, ok := sub.Annotations["category-top"]; ok { + if cmd.Parent() == nil { + // for now, only use top-commands for the root-command + continue + } + } if sub.IsAvailableCommand() && !sub.HasSubCommands() { cmds = append(cmds, sub) } @@ -285,6 +326,27 @@ func vendorAndVersion(cmd *cobra.Command) string { } func managementSubCommands(cmd *cobra.Command) []*cobra.Command { + cmds := []*cobra.Command{} + for _, sub := range allManagementSubCommands(cmd) { + if _, ok := sub.Annotations["swarm"]; ok { + continue + } + cmds = append(cmds, sub) + } + return cmds +} + +func orchestratorSubCommands(cmd *cobra.Command) []*cobra.Command { + cmds := []*cobra.Command{} + for _, sub := range allManagementSubCommands(cmd) { + if _, ok := sub.Annotations["swarm"]; ok { + cmds = append(cmds, sub) + } + } + return cmds +} + +func allManagementSubCommands(cmd *cobra.Command) []*cobra.Command { cmds := []*cobra.Command{} for _, sub := range cmd.Commands() { if isPlugin(sub) { @@ -345,11 +407,20 @@ Examples: {{ .Example }} {{- end}} +{{- if .HasParent}} {{- if .HasAvailableFlags}} Options: {{ wrappedFlagUsages . | trimRightSpace}} +{{- end}} +{{- end}} +{{- if hasTopCommands .}} + +Common Commands: +{{- range topCommands .}} + {{rpad (decoratedName .) (add .NamePadding 1)}}{{.Short}} +{{- end}} {{- end}} {{- if hasManagementSubCommands . }} @@ -359,6 +430,15 @@ Management Commands: {{rpad (decoratedName .) (add .NamePadding 1)}}{{.Short}}{{ if isPlugin .}} {{vendorAndVersion .}}{{ end}} {{- end}} +{{- end}} +{{- if hasSwarmSubCommands . }} + +Swarm Commands: + +{{- range orchestratorSubCommands . }} + {{rpad (decoratedName .) (add .NamePadding 1)}}{{.Short}}{{ if isPlugin .}} {{vendorAndVersion .}}{{ end}} +{{- end}} + {{- end}} {{- if hasSubCommands .}} @@ -377,6 +457,14 @@ Invalid Plugins: {{rpad .Name .NamePadding }} {{invalidPluginReason .}} {{- end}} +{{- end}} +{{- if not .HasParent}} +{{- if .HasAvailableFlags}} + +Global Options: +{{ wrappedFlagUsages . | trimRightSpace}} + +{{- end}} {{- end}} {{- if .HasSubCommands }} diff --git a/cli/command/commands/commands.go b/cli/command/commands/commands.go index 7c1ab20f7a..23a43568b5 100644 --- a/cli/command/commands/commands.go +++ b/cli/command/commands/commands.go @@ -28,81 +28,52 @@ import ( // AddCommands adds all the commands from cli/command to the root command func AddCommands(cmd *cobra.Command, dockerCli command.Cli) { cmd.AddCommand( - // checkpoint - checkpoint.NewCheckpointCommand(dockerCli), - - // config - config.NewConfigCommand(dockerCli), - - // container - container.NewContainerCommand(dockerCli), + // commonly used shorthands container.NewRunCommand(dockerCli), - - // image - image.NewImageCommand(dockerCli), + container.NewExecCommand(dockerCli), + container.NewPsCommand(dockerCli), image.NewBuildCommand(dockerCli), - - // builder - builder.NewBuilderCommand(dockerCli), - - // manifest - manifest.NewManifestCommand(dockerCli), - - // network - network.NewNetworkCommand(dockerCli), - - // node - node.NewNodeCommand(dockerCli), - - // plugin - plugin.NewPluginCommand(dockerCli), - - // registry + image.NewPullCommand(dockerCli), + image.NewPushCommand(dockerCli), + image.NewImagesCommand(dockerCli), registry.NewLoginCommand(dockerCli), registry.NewLogoutCommand(dockerCli), registry.NewSearchCommand(dockerCli), - - // secret - secret.NewSecretCommand(dockerCli), - - // service - service.NewServiceCommand(dockerCli), - - // system - system.NewSystemCommand(dockerCli), system.NewVersionCommand(dockerCli), + system.NewInfoCommand(dockerCli), - // stack - stack.NewStackCommand(dockerCli), - - // swarm - swarm.NewSwarmCommand(dockerCli), - - // trust + // management commands + builder.NewBuilderCommand(dockerCli), + checkpoint.NewCheckpointCommand(dockerCli), + container.NewContainerCommand(dockerCli), + context.NewContextCommand(dockerCli), + image.NewImageCommand(dockerCli), + manifest.NewManifestCommand(dockerCli), + network.NewNetworkCommand(dockerCli), + plugin.NewPluginCommand(dockerCli), + system.NewSystemCommand(dockerCli), trust.NewTrustCommand(dockerCli), - - // volume volume.NewVolumeCommand(dockerCli), - // context - context.NewContextCommand(dockerCli), + // orchestration (swarm) commands + config.NewConfigCommand(dockerCli), + node.NewNodeCommand(dockerCli), + secret.NewSecretCommand(dockerCli), + service.NewServiceCommand(dockerCli), + stack.NewStackCommand(dockerCli), + swarm.NewSwarmCommand(dockerCli), // legacy commands may be hidden - hide(system.NewEventsCommand(dockerCli)), - hide(system.NewInfoCommand(dockerCli)), - hide(system.NewInspectCommand(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)), @@ -114,14 +85,13 @@ func AddCommands(cmd *cobra.Command, dockerCli command.Cli) { 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.NewEventsCommand(dockerCli)), + hide(system.NewInspectCommand(dockerCli)), ) } diff --git a/cli/command/config/cmd.go b/cli/command/config/cmd.go index 7defe2a61e..b241229798 100644 --- a/cli/command/config/cmd.go +++ b/cli/command/config/cmd.go @@ -11,7 +11,7 @@ import ( func NewConfigCommand(dockerCli command.Cli) *cobra.Command { cmd := &cobra.Command{ Use: "config", - Short: "Manage Docker configs", + Short: "Manage Swarm configs", Args: cli.NoArgs, RunE: command.ShowHelp(dockerCli.Err()), Annotations: map[string]string{ diff --git a/cli/command/container/exec.go b/cli/command/container/exec.go index 9259e53d84..9dc00724f2 100644 --- a/cli/command/container/exec.go +++ b/cli/command/container/exec.go @@ -52,6 +52,9 @@ func NewExecCommand(dockerCli command.Cli) *cobra.Command { options.Command = args[1:] return RunExec(dockerCli, options) }, + Annotations: map[string]string{ + "category-top": "2", + }, } flags := cmd.Flags() diff --git a/cli/command/container/list.go b/cli/command/container/list.go index 99b5c7ef27..b24ce8b09c 100644 --- a/cli/command/container/list.go +++ b/cli/command/container/list.go @@ -37,6 +37,9 @@ func NewPsCommand(dockerCli command.Cli) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { return runPs(dockerCli, &options) }, + Annotations: map[string]string{ + "category-top": "3", + }, } flags := cmd.Flags() diff --git a/cli/command/container/run.go b/cli/command/container/run.go index 38785129b8..480743611b 100644 --- a/cli/command/container/run.go +++ b/cli/command/container/run.go @@ -44,6 +44,9 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command { } return runRun(dockerCli, cmd.Flags(), &opts, copts) }, + Annotations: map[string]string{ + "category-top": "1", + }, } flags := cmd.Flags() diff --git a/cli/command/image/build.go b/cli/command/image/build.go index 6f5ea8828a..99307e256b 100644 --- a/cli/command/image/build.go +++ b/cli/command/image/build.go @@ -105,6 +105,9 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command { options.context = args[0] return runBuild(dockerCli, options) }, + Annotations: map[string]string{ + "category-top": "4", + }, } flags := cmd.Flags() diff --git a/cli/command/image/list.go b/cli/command/image/list.go index 7f1a8df3a7..4771032cb0 100644 --- a/cli/command/image/list.go +++ b/cli/command/image/list.go @@ -37,6 +37,9 @@ func NewImagesCommand(dockerCli command.Cli) *cobra.Command { } return runImages(dockerCli, options) }, + Annotations: map[string]string{ + "category-top": "7", + }, } flags := cmd.Flags() diff --git a/cli/command/image/pull.go b/cli/command/image/pull.go index 242ad4a19c..391d397684 100644 --- a/cli/command/image/pull.go +++ b/cli/command/image/pull.go @@ -34,6 +34,9 @@ func NewPullCommand(dockerCli command.Cli) *cobra.Command { opts.remote = args[0] return RunPull(dockerCli, opts) }, + Annotations: map[string]string{ + "category-top": "5", + }, } flags := cmd.Flags() diff --git a/cli/command/image/push.go b/cli/command/image/push.go index 771a99592e..c422088ea2 100644 --- a/cli/command/image/push.go +++ b/cli/command/image/push.go @@ -35,6 +35,9 @@ func NewPushCommand(dockerCli command.Cli) *cobra.Command { opts.remote = args[0] return RunPush(dockerCli, opts) }, + Annotations: map[string]string{ + "category-top": "6", + }, } flags := cmd.Flags() diff --git a/cli/command/registry/login.go b/cli/command/registry/login.go index e949c00407..9df30db107 100644 --- a/cli/command/registry/login.go +++ b/cli/command/registry/login.go @@ -44,6 +44,9 @@ func NewLoginCommand(dockerCli command.Cli) *cobra.Command { } return runLogin(dockerCli, opts) }, + Annotations: map[string]string{ + "category-top": "8", + }, } flags := cmd.Flags() diff --git a/cli/command/registry/logout.go b/cli/command/registry/logout.go index 6bd6ae087c..844428d779 100644 --- a/cli/command/registry/logout.go +++ b/cli/command/registry/logout.go @@ -23,6 +23,9 @@ func NewLogoutCommand(dockerCli command.Cli) *cobra.Command { } return runLogout(dockerCli, serverAddress) }, + Annotations: map[string]string{ + "category-top": "9", + }, } return cmd diff --git a/cli/command/registry/search.go b/cli/command/registry/search.go index cabaad28ae..9efc1f3d5a 100644 --- a/cli/command/registry/search.go +++ b/cli/command/registry/search.go @@ -32,6 +32,9 @@ func NewSearchCommand(dockerCli command.Cli) *cobra.Command { options.term = args[0] return runSearch(dockerCli, options) }, + Annotations: map[string]string{ + "category-top": "10", + }, } flags := cmd.Flags() diff --git a/cli/command/secret/cmd.go b/cli/command/secret/cmd.go index a29d2def37..937fcdb150 100644 --- a/cli/command/secret/cmd.go +++ b/cli/command/secret/cmd.go @@ -11,7 +11,7 @@ import ( func NewSecretCommand(dockerCli command.Cli) *cobra.Command { cmd := &cobra.Command{ Use: "secret", - Short: "Manage Docker secrets", + Short: "Manage Swarm secrets", Args: cli.NoArgs, RunE: command.ShowHelp(dockerCli.Err()), Annotations: map[string]string{ diff --git a/cli/command/service/cmd.go b/cli/command/service/cmd.go index 98af9852ab..23132d9928 100644 --- a/cli/command/service/cmd.go +++ b/cli/command/service/cmd.go @@ -11,7 +11,7 @@ import ( func NewServiceCommand(dockerCli command.Cli) *cobra.Command { cmd := &cobra.Command{ Use: "service", - Short: "Manage services", + Short: "Manage Swarm services", Args: cli.NoArgs, RunE: command.ShowHelp(dockerCli.Err()), Annotations: map[string]string{ diff --git a/cli/command/stack/cmd.go b/cli/command/stack/cmd.go index 4f59b99f4a..9e87482171 100644 --- a/cli/command/stack/cmd.go +++ b/cli/command/stack/cmd.go @@ -12,11 +12,12 @@ import ( func NewStackCommand(dockerCli command.Cli) *cobra.Command { cmd := &cobra.Command{ Use: "stack [OPTIONS]", - Short: "Manage Docker stacks", + Short: "Manage Swarm stacks", Args: cli.NoArgs, RunE: command.ShowHelp(dockerCli.Err()), Annotations: map[string]string{ "version": "1.25", + "swarm": "", }, } defaultHelpFunc := cmd.HelpFunc() diff --git a/cli/command/system/info.go b/cli/command/system/info.go index 1d57f3f5ca..ff2f794221 100644 --- a/cli/command/system/info.go +++ b/cli/command/system/info.go @@ -54,6 +54,9 @@ func NewInfoCommand(dockerCli command.Cli) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { return runInfo(cmd, dockerCli, &opts) }, + Annotations: map[string]string{ + "category-top": "12", + }, } flags := cmd.Flags() diff --git a/cli/command/system/version.go b/cli/command/system/version.go index 06b62ae763..bd56bb0998 100644 --- a/cli/command/system/version.go +++ b/cli/command/system/version.go @@ -96,6 +96,9 @@ func NewVersionCommand(dockerCli command.Cli) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { return runVersion(dockerCli, &opts) }, + Annotations: map[string]string{ + "category-top": "10", + }, } flags := cmd.Flags() diff --git a/docs/reference/commandline/config.md b/docs/reference/commandline/config.md index 67329bd940..80ea03dfac 100644 --- a/docs/reference/commandline/config.md +++ b/docs/reference/commandline/config.md @@ -9,7 +9,7 @@ keywords: "config" ```markdown Usage: docker config COMMAND -Manage Docker configs +Manage Swarm configs Options: --help Print usage diff --git a/docs/reference/commandline/secret.md b/docs/reference/commandline/secret.md index 83c74ee638..206c9b58bd 100644 --- a/docs/reference/commandline/secret.md +++ b/docs/reference/commandline/secret.md @@ -9,7 +9,7 @@ keywords: "secret" ```markdown Usage: docker secret COMMAND -Manage Docker secrets +Manage Swarm secrets Options: --help Print usage diff --git a/docs/reference/commandline/service.md b/docs/reference/commandline/service.md index b1cff8ae44..8d834dcd90 100644 --- a/docs/reference/commandline/service.md +++ b/docs/reference/commandline/service.md @@ -9,7 +9,7 @@ keywords: "service" ```markdown Usage: docker service COMMAND -Manage services +Manage Swarm services Options: --help Print usage @@ -29,7 +29,7 @@ Run 'docker service COMMAND --help' for more information on a command. ## Description -Manage services. +Manage Swarm services. > **Note** > diff --git a/docs/reference/commandline/stack.md b/docs/reference/commandline/stack.md index c6431d247e..5003440429 100644 --- a/docs/reference/commandline/stack.md +++ b/docs/reference/commandline/stack.md @@ -9,7 +9,7 @@ keywords: "stack" ```markdown Usage: docker stack [OPTIONS] COMMAND -Manage Docker stacks +Manage Swarm stacks Options: --help Print usage