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
How to make it works for subcommands #7
Comments
@carolynvs sorry for bothering you, but back on the topic and still stuck, so any help would be welcomed 😖 |
Hey @rgarrigue I can't provide support / troubleshooting for cobra. But I can point you towards my codebase, https://github.com/getporter/porter/blob/main/cmd/porter/main.go and https://github.com/getporter/porter/blob/main/pkg/cli/config.go (helpers for cobra) which works with subcommands and everything outlined in stingoftheviper. Hopefully that helps give you an idea of what's different that is causing your subcommands to not work! 👍 |
This is how I ended up solving it package main
import (
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)
type App struct {
}
func main() {
cli := New()
cli.HelloCli()
}
func New() *App {
return &App{}
}
func (c *App) HelloCli() {
rootCmd := &cobra.Command{
Use: "do",
Short: "do things",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return InitializeConfig(cmd)
},
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
hello := rootCmd.PersistentFlags().String("hello", "name", "your name")
rootCmd.AddCommand((&DoStuff{}).Hello(hello))
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
type DoStuff struct {
}
func (c *DoStuff) Hello(hello *string) *cobra.Command {
cmd := &cobra.Command{
Use: "hello",
Short: "say hello",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("hello %s\n", *hello)
},
}
return cmd
}
func InitializeConfig(cmd *cobra.Command) error {
v := viper.New()
v.SetEnvPrefix("MYCLI")
v.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
v.AutomaticEnv()
bindFlags(cmd, v)
return nil
}
// Bind each cobra flag to its associated viper configuration environment variable
func bindFlags(cmd *cobra.Command, v *viper.Viper) {
cmd.Flags().VisitAll(func(f *pflag.Flag) {
configName := f.Name
if !f.Changed && v.IsSet(configName) {
val := v.Get(configName)
cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val))
}
})
} MYCLI_HELLO=bob go run main.go hello
# hello bob
go run main.go hello --hello=world
# hello world |
Hi there
Long story short, I started from cobra-cli boilerplate, and taking snippets of this repository I got a root command working.
But my issue now is that subcommands don't take env / config file in account, just flags. After trials & errors, seems I would need to add
ViperCfg.ReadInConfig()
in all the subcommands' init. Not really elegant, I guess I'm missing something as PersistentPreRun should propagate the viper config reading. But well, beginner's struggles.So wondering what I'm missing here / how would you deal with subcommands in your setup ?
Here's my
root.go
And the shortened
generate.go
The text was updated successfully, but these errors were encountered: