From 15678e4a67e1b725368ca1bd3a97b670c5d97776 Mon Sep 17 00:00:00 2001 From: LronDC Date: Wed, 10 May 2023 18:10:28 +0800 Subject: [PATCH] Optimize usage message of commands which have subcommands. Signed-off-by: LronDC --- .../kubectl/pkg/cmd/create/create_secret.go | 24 +++++++++++++------ .../kubectl/pkg/util/templates/templater.go | 10 ++++++++ .../kubectl/pkg/util/templates/templates.go | 5 ++-- test/cmd/help.sh | 18 ++++++++++++++ 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/create/create_secret.go b/staging/src/k8s.io/kubectl/pkg/cmd/create/create_secret.go index cfd9320241e..b9bb191f9f5 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/create/create_secret.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/create/create_secret.go @@ -44,10 +44,11 @@ import ( // This is the entry point of create_secret.go which will be called by create.go func NewCmdCreateSecret(f cmdutil.Factory, ioStreams genericiooptions.IOStreams) *cobra.Command { cmd := &cobra.Command{ - Use: "secret", - Short: i18n.T("Create a secret using specified subcommand"), - Long: i18n.T("Create a secret using specified subcommand."), - Run: cmdutil.DefaultSubCommandRun(ioStreams.ErrOut), + Use: "secret (docker-registry | generic | tls)", + DisableFlagsInUseLine: true, + Short: i18n.T("Create a secret using a specified subcommand"), + Long: secretLong, + Run: cmdutil.DefaultSubCommandRun(ioStreams.ErrOut), } cmd.AddCommand(NewCmdCreateSecretDockerRegistry(f, ioStreams)) cmd.AddCommand(NewCmdCreateSecretTLS(f, ioStreams)) @@ -58,6 +59,15 @@ func NewCmdCreateSecret(f cmdutil.Factory, ioStreams genericiooptions.IOStreams) var ( secretLong = templates.LongDesc(i18n.T(` + Create a secret with specified type. + + A docker-registry type secret is for accessing a container registry. + + A generic type secret indicate an Opaque secret type. + + A tls type secret holds TLS certificate and its associated key.`)) + + secretForGenericLong = templates.LongDesc(i18n.T(` Create a secret based on a file, directory, or specified literal value. A single secret may package one or more key/value pairs. @@ -70,7 +80,7 @@ var ( packaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories, symlinks, devices, pipes, etc).`)) - secretExample = templates.Examples(i18n.T(` + secretForGenericExample = templates.Examples(i18n.T(` # Create a new secret named my-secret with keys for each file in folder bar kubectl create secret generic my-secret --from-file=path/to/bar @@ -134,8 +144,8 @@ func NewCmdCreateSecretGeneric(f cmdutil.Factory, ioStreams genericiooptions.IOS Use: "generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run=server|client|none]", DisableFlagsInUseLine: true, Short: i18n.T("Create a secret from a local file, directory, or literal value"), - Long: secretLong, - Example: secretExample, + Long: secretForGenericLong, + Example: secretForGenericExample, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) cmdutil.CheckErr(o.Validate()) diff --git a/staging/src/k8s.io/kubectl/pkg/util/templates/templater.go b/staging/src/k8s.io/kubectl/pkg/util/templates/templater.go index 2e9f942a573..8fe181a0508 100644 --- a/staging/src/k8s.io/kubectl/pkg/util/templates/templater.go +++ b/staging/src/k8s.io/kubectl/pkg/util/templates/templater.go @@ -126,6 +126,7 @@ func (templater *templater) templateFuncs(exposedFlags ...string) template.FuncM "isRootCmd": templater.isRootCmd, "optionsCmdFor": templater.optionsCmdFor, "usageLine": templater.usageLine, + "reverseParentsNames": templater.reverseParentsNames, "exposed": func(c *cobra.Command) *flag.FlagSet { exposed := flag.NewFlagSet("exposed", flag.ContinueOnError) if len(exposedFlags) > 0 { @@ -172,6 +173,15 @@ func (t *templater) rootCmdName(c *cobra.Command) string { return t.rootCmd(c).CommandPath() } +func (t *templater) reverseParentsNames(c *cobra.Command) []string { + reverseParentsNames := []string{} + parents := t.parents(c) + for i := len(parents) - 1; i >= 0; i-- { + reverseParentsNames = append(reverseParentsNames, parents[i].Name()) + } + return reverseParentsNames +} + func (t *templater) isRootCmd(c *cobra.Command) bool { return t.rootCmd(c) == c } diff --git a/staging/src/k8s.io/kubectl/pkg/util/templates/templates.go b/staging/src/k8s.io/kubectl/pkg/util/templates/templates.go index 9f3b75b57ee..454695c0b24 100644 --- a/staging/src/k8s.io/kubectl/pkg/util/templates/templates.go +++ b/staging/src/k8s.io/kubectl/pkg/util/templates/templates.go @@ -28,7 +28,8 @@ const ( `{{$visibleFlags := visibleFlags (flagsNotIntersected .LocalFlags .PersistentFlags)}}` + `{{$explicitlyExposedFlags := exposed .}}` + `{{$optionsCmdFor := optionsCmdFor .}}` + - `{{$usageLine := usageLine .}}` + `{{$usageLine := usageLine .}}` + + `{{$reverseParentsNames := reverseParentsNames .}}` // SectionAliases is the help template section that displays command aliases. SectionAliases = `{{if gt .Aliases 0}}Aliases: @@ -61,7 +62,7 @@ const ( {{end}}` // SectionTipsHelp is the help template section that displays the '--help' hint. - SectionTipsHelp = `{{if .HasSubCommands}}Use "{{$rootCmd}} --help" for more information about a given command. + SectionTipsHelp = `{{if .HasSubCommands}}Use "{{range $reverseParentsNames}}{{.}} {{end}} --help" for more information about a given command. {{end}}` // SectionTipsGlobalOptions is the help template section that displays the 'options' hint for displaying global flags. diff --git a/test/cmd/help.sh b/test/cmd/help.sh index 72cca6c949f..3781399a5cc 100644 --- a/test/cmd/help.sh +++ b/test/cmd/help.sh @@ -47,6 +47,24 @@ run_kubectl_help_tests() { kube::test::if_has_string "$(LANG=zh_CN.UTF-8 kubectl uncordon --help)" "标记节点为可调度。" kube::test::if_has_string "$(LANG=zh_TW.UTF-8 kubectl uncordon --help)" "Mark node as schedulable." + # This part of test is to check those commands that have subcommands output the correct usage prompts. + # If a new command with subcommands is added, it is best to be added here. + # If some refactoring causes the command to become without subcommands, it needs to be removed here to ensure that the test passes. + + kube::test::if_has_string "$(kubectl --help)" "Use \"kubectl --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl apply --help)" "Use \"kubectl apply --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl auth --help)" "Use \"kubectl auth --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl certificate --help)" "Use \"kubectl certificate --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl cluster-info --help)" "Use \"kubectl cluster-info --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl config --help)" "Use \"kubectl config --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl create --help)" "Use \"kubectl create --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl create secret --help)" "Use \"kubectl create secret --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl create service --help)" "Use \"kubectl create service --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl plugin --help)" "Use \"kubectl plugin --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl rollout --help)" "Use \"kubectl rollout --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl set --help)" "Use \"kubectl set --help\" for more information about a given command." + kube::test::if_has_string "$(kubectl top --help)" "Use \"kubectl top --help\" for more information about a given command." + set +o nounset set +o errexit }