metropolis/cli/metroctl: don't print usage for runtime errors
Change-Id: I91fdca45e874ea1ec9112df556a9a7392fd45bfd
Fixes: https://github.com/monogon-dev/monogon/issues/352
Reviewed-on: https://review.monogon.dev/c/monogon/+/3440
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/cli/metroctl/cmd_certs.go b/metropolis/cli/metroctl/cmd_certs.go
index d914c83..8475546 100644
--- a/metropolis/cli/metroctl/cmd_certs.go
+++ b/metropolis/cli/metroctl/cmd_certs.go
@@ -48,5 +48,5 @@
}
log.Println("Wrote files to current dir: cert.pem, key.pem")
},
- Args: cobra.NoArgs,
+ Args: PrintUsageOnWrongArgs(cobra.NoArgs),
}
diff --git a/metropolis/cli/metroctl/cmd_install_usb.go b/metropolis/cli/metroctl/cmd_install_usb.go
index a9873b6..fcbcfa2 100644
--- a/metropolis/cli/metroctl/cmd_install_usb.go
+++ b/metropolis/cli/metroctl/cmd_install_usb.go
@@ -13,7 +13,7 @@
Use: "genusb target",
Short: "Generates a Metropolis installer disk or image.",
Example: "metroctl install --bundle=metropolis-v0.1.zip genusb /dev/sdx",
- Args: cobra.ExactArgs(1), // One positional argument: the target
+ Args: PrintUsageOnWrongArgs(cobra.ExactArgs(1)), // One positional argument: the target
Run: doGenUSB,
}
diff --git a/metropolis/cli/metroctl/cmd_k8s_configure.go b/metropolis/cli/metroctl/cmd_k8s_configure.go
index c238cdf..cd90416 100644
--- a/metropolis/cli/metroctl/cmd_k8s_configure.go
+++ b/metropolis/cli/metroctl/cmd_k8s_configure.go
@@ -23,7 +23,7 @@
Long: `Configures a local kubectl instance (or any other Kubernetes application)
to connect to a Metropolis cluster. A cluster endpoint must be provided with the
--endpoints parameter.`,
- Args: cobra.ExactArgs(0),
+ Args: PrintUsageOnWrongArgs(cobra.ExactArgs(0)),
Run: doK8sConfigure,
}
diff --git a/metropolis/cli/metroctl/cmd_k8scredplugin.go b/metropolis/cli/metroctl/cmd_k8scredplugin.go
index 0d1f318..8d84a9e 100644
--- a/metropolis/cli/metroctl/cmd_k8scredplugin.go
+++ b/metropolis/cli/metroctl/cmd_k8scredplugin.go
@@ -21,7 +21,7 @@
Long: `This implements a Kubernetes client-go credential plugin to
authenticate client-go based callers including kubectl against a Metropolis
cluster. This should never be directly called by end users.`,
- Args: cobra.ExactArgs(0),
+ Args: PrintUsageOnWrongArgs(cobra.ExactArgs(0)),
Hidden: true,
Run: doK8sCredPlugin,
}
diff --git a/metropolis/cli/metroctl/cmd_node.go b/metropolis/cli/metroctl/cmd_node.go
index 59b4d9b..d7a23ee 100644
--- a/metropolis/cli/metroctl/cmd_node.go
+++ b/metropolis/cli/metroctl/cmd_node.go
@@ -53,7 +53,7 @@
}
printNodes(nodes, args, columns)
},
- Args: cobra.ArbitraryArgs,
+ Args: PrintUsageOnWrongArgs(cobra.ArbitraryArgs),
}
var nodeListCmd = &cobra.Command{
@@ -72,7 +72,7 @@
printNodes(nodes, args, map[string]bool{"node id": true})
},
- Args: cobra.ArbitraryArgs,
+ Args: PrintUsageOnWrongArgs(cobra.ArbitraryArgs),
}
var nodeUpdateCmd = &cobra.Command{
@@ -225,7 +225,7 @@
return nil
},
- Args: cobra.MinimumNArgs(1),
+ Args: PrintUsageOnWrongArgs(cobra.MinimumNArgs(1)),
}
var nodeDeleteCmd = &cobra.Command{
@@ -283,7 +283,7 @@
_, err = mgmt.DeleteNode(ctx, req)
return err
},
- Args: cobra.ExactArgs(1),
+ Args: PrintUsageOnWrongArgs(cobra.ExactArgs(1)),
}
func dialNode(ctx context.Context, node string) (apb.NodeManagementClient, error) {
@@ -331,7 +331,7 @@
--firmware flag. This flag cannot be combined with any others.
`,
Use: "reboot [node-id]",
- Args: cobra.ExactArgs(1),
+ Args: PrintUsageOnWrongArgs(cobra.ExactArgs(1)),
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
@@ -385,7 +385,7 @@
var nodePoweroffCmd = &cobra.Command{
Short: "Power off a node",
Use: "poweroff [node-id]",
- Args: cobra.ExactArgs(1),
+ Args: PrintUsageOnWrongArgs(cobra.ExactArgs(1)),
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
diff --git a/metropolis/cli/metroctl/cmd_node_approve.go b/metropolis/cli/metroctl/cmd_node_approve.go
index 62ab7bd..294f8c3 100644
--- a/metropolis/cli/metroctl/cmd_node_approve.go
+++ b/metropolis/cli/metroctl/cmd_node_approve.go
@@ -17,7 +17,7 @@
var approveCmd = &cobra.Command{
Short: "Approves a candidate node, if specified; lists nodes pending approval otherwise.",
Use: "approve [node-id]",
- Args: cobra.MaximumNArgs(1), // One positional argument: node ID
+ Args: PrintUsageOnWrongArgs(cobra.MaximumNArgs(1)), // One positional argument: node ID
Run: doApprove,
}
diff --git a/metropolis/cli/metroctl/cmd_node_logs.go b/metropolis/cli/metroctl/cmd_node_logs.go
index 5b8cef9..d21df7b 100644
--- a/metropolis/cli/metroctl/cmd_node_logs.go
+++ b/metropolis/cli/metroctl/cmd_node_logs.go
@@ -54,7 +54,7 @@
unnecessary lines are fetched.
`,
Use: "logs [node-id]",
- Args: cobra.MinimumNArgs(1),
+ Args: PrintUsageOnWrongArgs(cobra.MinimumNArgs(1)),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
diff --git a/metropolis/cli/metroctl/cmd_node_metrics.go b/metropolis/cli/metroctl/cmd_node_metrics.go
index f3bde46..0842c24 100644
--- a/metropolis/cli/metroctl/cmd_node_metrics.go
+++ b/metropolis/cli/metroctl/cmd_node_metrics.go
@@ -39,7 +39,7 @@
`,
Use: "metrics [node-id] [exporter]",
- Args: cobra.MinimumNArgs(2),
+ Args: PrintUsageOnWrongArgs(cobra.MinimumNArgs(2)),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
diff --git a/metropolis/cli/metroctl/cmd_node_set.go b/metropolis/cli/metroctl/cmd_node_set.go
index 73d7f3c..59df43e 100644
--- a/metropolis/cli/metroctl/cmd_node_set.go
+++ b/metropolis/cli/metroctl/cmd_node_set.go
@@ -26,7 +26,7 @@
Short: "Updates node roles.",
Use: "role <KubernetesController|KubernetesWorker|ConsensusMember> [NodeID, ...]",
Example: "metroctl node add role KubernetesWorker metropolis-25fa5f5e9349381d4a5e9e59de0215e3",
- Args: cobra.ArbitraryArgs,
+ Args: PrintUsageOnWrongArgs(cobra.ArbitraryArgs),
Run: doAdd,
}
@@ -34,7 +34,7 @@
Short: "Updates node roles.",
Use: "role <KubernetesController|KubernetesWorker|ConsensusMember> [NodeID, ...]",
Example: "metroctl node remove role KubernetesWorker metropolis-25fa5f5e9349381d4a5e9e59de0215e3",
- Args: cobra.ArbitraryArgs,
+ Args: PrintUsageOnWrongArgs(cobra.ArbitraryArgs),
Run: doRemove,
}
diff --git a/metropolis/cli/metroctl/cmd_takeownership.go b/metropolis/cli/metroctl/cmd_takeownership.go
index 30b9f08..d421f71 100644
--- a/metropolis/cli/metroctl/cmd_takeownership.go
+++ b/metropolis/cli/metroctl/cmd_takeownership.go
@@ -24,7 +24,7 @@
cluster to issue an owner certificate to for the owner key generated by a
previous invocation of metroctl install on this machine. A single cluster
endpoint must be provided with the --endpoints parameter.`,
- Args: cobra.ExactArgs(0),
+ Args: PrintUsageOnWrongArgs(cobra.ExactArgs(0)),
Run: doTakeOwnership,
}
diff --git a/metropolis/cli/metroctl/main.go b/metropolis/cli/metroctl/main.go
index fcdbccd..21f87a6 100644
--- a/metropolis/cli/metroctl/main.go
+++ b/metropolis/cli/metroctl/main.go
@@ -15,8 +15,10 @@
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
- Use: "metroctl",
- Short: "metroctl controls Metropolis nodes and clusters.",
+ Use: "metroctl",
+ Short: "metroctl controls Metropolis nodes and clusters.",
+ SilenceUsage: true,
+ SilenceErrors: true,
}
type metroctlFlags struct {
@@ -60,6 +62,20 @@
rootCmd.PersistentFlags().StringVar(&flags.columns, "columns", "", "Comma-separated list of column names to show. If not set, all columns will be shown")
rootCmd.PersistentFlags().StringVarP(&flags.output, "output", "o", "", "Redirects output to the specified file")
rootCmd.PersistentFlags().BoolVar(&flags.acceptAnyCA, "insecure-accept-and-persist-first-encountered-ca", false, "Accept the first encountered CA while connecting as the trusted CA for future metroctl connections with this config path. This is very insecure and should only be used for testing.")
+ rootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error {
+ cmd.PrintErr(cmd.UsageString())
+ return err
+ })
+}
+
+func PrintUsageOnWrongArgs(pArgs cobra.PositionalArgs) cobra.PositionalArgs {
+ return func(cmd *cobra.Command, args []string) error {
+ err := pArgs(cmd, args)
+ if err != nil {
+ cmd.PrintErr(cmd.UsageString())
+ }
+ return err
+ }
}
func main() {