diff --git a/cmd/cli/flavor.go b/cmd/cli/flavor.go index 4d17fff40..853540445 100644 --- a/cmd/cli/flavor.go +++ b/cmd/cli/flavor.go @@ -28,6 +28,14 @@ func flavorPluginCommand(plugins func() discovery.Plugins) *cobra.Command { name := cmd.PersistentFlags().String("name", "", "Name of plugin") cmd.PersistentPreRunE = func(c *cobra.Command, args []string) error { + if err := upTree(c, func(x *cobra.Command, argv []string) error { + if x.PersistentPreRunE != nil { + return x.PersistentPreRunE(x, argv) + } + return nil + }); err != nil { + return err + } endpoint, err := plugins().Find(plugin.Name(*name)) if err != nil { diff --git a/cmd/cli/group.go b/cmd/cli/group.go index b46e06d83..0f1746a66 100644 --- a/cmd/cli/group.go +++ b/cmd/cli/group.go @@ -31,6 +31,14 @@ func groupPluginCommand(plugins func() discovery.Plugins) *cobra.Command { } name := cmd.PersistentFlags().String("name", DefaultGroupPluginName, "Name of plugin") cmd.PersistentPreRunE = func(c *cobra.Command, args []string) error { + if err := upTree(c, func(x *cobra.Command, argv []string) error { + if x.PersistentPreRunE != nil { + return x.PersistentPreRunE(x, argv) + } + return nil + }); err != nil { + return err + } endpoint, err := plugins().Find(plugin.Name(*name)) if err != nil { diff --git a/cmd/cli/instance.go b/cmd/cli/instance.go index 84a50b1b6..665730a5a 100644 --- a/cmd/cli/instance.go +++ b/cmd/cli/instance.go @@ -26,6 +26,14 @@ func instancePluginCommand(plugins func() discovery.Plugins) *cobra.Command { } name := cmd.PersistentFlags().String("name", "", "Name of plugin") cmd.PersistentPreRunE = func(c *cobra.Command, args []string) error { + if err := upTree(c, func(x *cobra.Command, argv []string) error { + if x.PersistentPreRunE != nil { + return x.PersistentPreRunE(x, argv) + } + return nil + }); err != nil { + return err + } endpoint, err := plugins().Find(plugin.Name(*name)) if err != nil { diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 018b86152..c4d541358 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -19,8 +19,9 @@ func main() { Short: "infrakit cli", } logLevel := cmd.PersistentFlags().Int("log", cli.DefaultLogLevel, "Logging level. 0 is least verbose. Max is 5") - cmd.PersistentPreRun = func(c *cobra.Command, args []string) { + cmd.PersistentPreRunE = func(c *cobra.Command, args []string) error { cli.SetLogLevel(*logLevel) + return nil } // Don't print usage text for any error returned from a RunE function. Only print it when explicitly requested. @@ -57,3 +58,14 @@ func assertNotNil(message string, f interface{}) { os.Exit(1) } } + +// upTree traverses up the command tree and starts executing the do function in the order from top +// of the command tree to the bottom. Cobra commands executes only one level of PersistentPreRunE +// in reverse order. This breaks our model of setting log levels at the very top and have the log level +// set throughout the entire hierarchy of command execution. +func upTree(c *cobra.Command, do func(*cobra.Command, []string) error) error { + if p := c.Parent(); p != nil { + return upTree(p, do) + } + return do(c, c.Flags().Args()) +} diff --git a/cmd/cli/manager.go b/cmd/cli/manager.go index d93922eb7..5f0ded79e 100644 --- a/cmd/cli/manager.go +++ b/cmd/cli/manager.go @@ -27,6 +27,14 @@ func managerCommand(plugins func() discovery.Plugins) *cobra.Command { Short: "Access the manager", } cmd.PersistentPreRunE = func(c *cobra.Command, args []string) error { + if err := upTree(c, func(x *cobra.Command, argv []string) error { + if x.PersistentPreRunE != nil { + return x.PersistentPreRunE(x, argv) + } + return nil + }); err != nil { + return err + } // Scan for a manager pm, err := plugins().List()