Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve istioctl options command description #38236

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion istioctl/cmd/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func TestConfigList(t *testing.T) {
cases := []testCase{
{ // case 0
args: strings.Split("experimental config get istioNamespace", " "),
expectedRegexp: regexp.MustCompile("Usage:\n istioctl experimental config"),
expectedRegexp: regexp.MustCompile("Examples:\n # list configuration parameters\n istioctl config list"),
wantException: false,
},
{ // case 1
Expand Down
11 changes: 8 additions & 3 deletions istioctl/cmd/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,31 @@ import (
)

var helpFlags = map[string]bool{
"context": true,
"istioNamespace": true,
"kubeconfig": true,
"log_as_json": true,
"log_stacktrace_level": true,
"log_target": true,
"log_caller": true,
"log_output_level": true,
"namespace": true,
"vklog": true,
// istioctl also inherits support for log_rotate, log_rotate_max_age, log_rotate_max_backups,
// log_rotate_max_size, but these are rarely appropriate for a user-facing CLI so we ignore them
}

func optionsCommand(rootCmd *cobra.Command) *cobra.Command {
func optionsCommand() *cobra.Command {
retval := &cobra.Command{
Use: "options",
Short: "Displays istioctl global options",
Args: cobra.ExactArgs(0),
}

retval.SetHelpFunc(func(c *cobra.Command, args []string) {
c.Printf("The following options can be passed to any command:\n")
c.Printf("The following options can be passed to any command:\n\n")
// (Currently the only global options we show are help options)
rootCmd.PersistentFlags().VisitAll(func(flag *pflag.Flag) {
retval.Root().PersistentFlags().VisitAll(func(flag *pflag.Flag) {
if _, ok := helpFlags[flag.Name]; ok {
// Currently every flag.Shorthand is "", so there is no point in showing shorthands
shorthand := " "
Expand Down
5 changes: 5 additions & 0 deletions istioctl/cmd/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@ import (

// nolint: lll
var expectedOutput = `The following options can be passed to any command:

--context: The name of the kubeconfig context to use
-i, --istioNamespace: Istio system namespace
-c, --kubeconfig: Kubernetes configuration file
--log_as_json: Whether to format output as JSON or in plain console-friendly format
--log_caller: Comma-separated list of scopes for which to include caller information, scopes can be any of \[.*\]
--log_output_level: Comma-separated minimum per-scope logging level of messages to output, in the form of <scope>:<level>,<scope>:<level>,... where scope can be one of \[.*\] and level can be one of \[.*\]
--log_stacktrace_level: Comma-separated minimum per-scope logging level at which stack traces are captured, in the form of <scope>:<level>,<scope:level>,... where scope can be one of \[.*\] and level can be one of \[.*\]
--log_target: The set of paths where to output the log. This can be any path as well as the special values stdout and stderr
-n, --namespace: Config namespace
`

func TestLogHelp(t *testing.T) {
Expand Down
68 changes: 38 additions & 30 deletions istioctl/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ import (
"errors"
"fmt"
"path/filepath"
"sort"
"strings"

"github.com/spf13/cobra"
"github.com/spf13/cobra/doc"
"github.com/spf13/viper"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kubectl/pkg/util/templates"

"istio.io/istio/istioctl/pkg/install"
"istio.io/istio/istioctl/pkg/multicluster"
Expand Down Expand Up @@ -144,6 +146,9 @@ func GetRootCmd(args []string) *cobra.Command {
Long: `Istio configuration command line utility for service operators to
debug and diagnose their Istio mesh.
`,
Run: func(cmd *cobra.Command, args []string) {
_ = cmd.Help()
hanxiaop marked this conversation as resolved.
Show resolved Hide resolved
},
PersistentPreRunE: configureLogging,
}

Expand All @@ -170,6 +175,11 @@ debug and diagnose their Istio mesh.
"log_as_json", "log_rotate", "log_rotate_max_age", "log_rotate_max_backups",
"log_rotate_max_size", "log_stacktrace_level", "log_target", "log_caller", "log_output_level",
}

group := templates.CommandGroup{
Message: "Available Commands:",
Commands: []*cobra.Command{},
}
for _, opt := range hiddenFlags {
_ = rootCmd.PersistentFlags().MarkHidden(opt)
}
Expand All @@ -178,7 +188,7 @@ debug and diagnose their Istio mesh.

kubeInjectCmd := injectCommand()
hideInheritedFlags(kubeInjectCmd, FlagNamespace)
rootCmd.AddCommand(kubeInjectCmd)
group.Commands = append(group.Commands, kubeInjectCmd)

experimentalCmd := &cobra.Command{
Use: "experimental",
Expand All @@ -194,35 +204,26 @@ debug and diagnose their Istio mesh.
newVersionCommand(),
statusCommand(),
}
var debugCmdAttachmentPoint *cobra.Command
if viper.GetBool("PREFER-EXPERIMENTAL") {
legacyCmd := &cobra.Command{
Use: "legacy",
Short: "Legacy command variants",
}
rootCmd.AddCommand(legacyCmd)
for _, c := range xdsBasedTroubleshooting {
rootCmd.AddCommand(c)
}
debugCmdAttachmentPoint = legacyCmd
group.Commands = append(group.Commands, legacyCmd)
group.Commands = append(group.Commands, xdsBasedTroubleshooting...)
} else {
debugCmdAttachmentPoint = rootCmd
group.Commands = append(group.Commands, debugBasedTroubleshooting...)
}
for _, c := range xdsBasedTroubleshooting {
experimentalCmd.AddCommand(c)
}
for _, c := range debugBasedTroubleshooting {
debugCmdAttachmentPoint.AddCommand(c)
}

rootCmd.AddCommand(experimentalCmd)
rootCmd.AddCommand(proxyConfig())
rootCmd.AddCommand(adminCmd())
group.Commands = append(group.Commands, experimentalCmd, proxyConfig(), adminCmd())
experimentalCmd.AddCommand(injectorCommand())

rootCmd.AddCommand(install.NewVerifyCommand())
group.Commands = append(group.Commands, install.NewVerifyCommand())
experimentalCmd.AddCommand(AuthZ())
rootCmd.AddCommand(seeExperimentalCmd("authz"))
group.Commands = append(group.Commands, seeExperimentalCmd("authz"))
experimentalCmd.AddCommand(uninjectCommand())
experimentalCmd.AddCommand(metricsCmd())
experimentalCmd.AddCommand(describe())
Expand All @@ -239,59 +240,66 @@ debug and diagnose their Istio mesh.

analyzeCmd := Analyze()
hideInheritedFlags(analyzeCmd, FlagIstioNamespace)
rootCmd.AddCommand(analyzeCmd)
group.Commands = append(group.Commands, analyzeCmd)

dashboardCmd := dashboard()
hideInheritedFlags(dashboardCmd, FlagNamespace, FlagIstioNamespace)
rootCmd.AddCommand(dashboardCmd)
group.Commands = append(group.Commands, dashboardCmd)

manifestCmd := mesh.ManifestCmd(loggingOptions)
hideInheritedFlags(manifestCmd, FlagNamespace, FlagIstioNamespace, FlagCharts)
rootCmd.AddCommand(manifestCmd)
group.Commands = append(group.Commands, manifestCmd)

operatorCmd := mesh.OperatorCmd()
hideInheritedFlags(operatorCmd, FlagNamespace, FlagIstioNamespace, FlagCharts)
rootCmd.AddCommand(operatorCmd)
group.Commands = append(group.Commands, operatorCmd)

installCmd := mesh.InstallCmd(loggingOptions)
hideInheritedFlags(installCmd, FlagNamespace, FlagIstioNamespace, FlagCharts)
rootCmd.AddCommand(installCmd)
group.Commands = append(group.Commands, installCmd)

profileCmd := mesh.ProfileCmd(loggingOptions)
hideInheritedFlags(profileCmd, FlagNamespace, FlagIstioNamespace, FlagCharts)
rootCmd.AddCommand(profileCmd)
group.Commands = append(group.Commands, profileCmd)

upgradeCmd := mesh.UpgradeCmd(loggingOptions)
hideInheritedFlags(upgradeCmd, FlagNamespace, FlagIstioNamespace, FlagCharts)
rootCmd.AddCommand(upgradeCmd)
group.Commands = append(group.Commands, upgradeCmd)

bugReportCmd := bugreport.Cmd(loggingOptions)
hideInheritedFlags(bugReportCmd, FlagNamespace, FlagIstioNamespace)
rootCmd.AddCommand(bugReportCmd)
group.Commands = append(group.Commands, bugReportCmd)

tagCmd := tagCommand()
hideInheritedFlags(tagCommand(), FlagNamespace, FlagIstioNamespace, FlagCharts)
rootCmd.AddCommand(tagCmd)
group.Commands = append(group.Commands, tagCmd)

remoteSecretCmd := multicluster.NewCreateRemoteSecretCommand()
remoteClustersCmd := clustersCommand()
// leave the multicluster commands in x for backwards compat
rootCmd.AddCommand(remoteSecretCmd)
rootCmd.AddCommand(remoteClustersCmd)
group.Commands = append(group.Commands, remoteSecretCmd, remoteClustersCmd)
experimentalCmd.AddCommand(remoteSecretCmd)
experimentalCmd.AddCommand(remoteClustersCmd)

rootCmd.AddCommand(collateral.CobraCommand(rootCmd, &doc.GenManHeader{
group.Commands = append(group.Commands, collateral.CobraCommand(rootCmd, &doc.GenManHeader{
Title: "Istio Control",
Section: "istioctl CLI",
Manual: "Istio Control",
}))

validateCmd := validate.NewValidateCommand(&istioNamespace, &namespace)
hideInheritedFlags(validateCmd, "kubeconfig")
rootCmd.AddCommand(validateCmd)
group.Commands = append(group.Commands, validateCmd, optionsCommand())

sort.SliceStable(group.Commands, func(i, j int) bool {
return group.Commands[i].Use < group.Commands[j].Use
})

groups := templates.CommandGroups{group}
groups.Add(rootCmd)

rootCmd.AddCommand(optionsCommand(rootCmd))
filters := []string{"options"}
templates.ActsAsRootCommand(rootCmd, filters, groups...)

// BFS apply the flag error function to all subcommands
seenCommands := make(map[*cobra.Command]bool)
Expand Down
6 changes: 6 additions & 0 deletions releasenotes/notes/38236.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: release-notes/v2
kind: feature
area: istioctl
releaseNotes:
- |
**Improved** `options` command to be similar like `kubectl` , and put all global flags into the `options` command.