Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Cobra not reading my configuration file?

Tags:

go

cobra

viper-go

The documentation in Cobra and Viper are confusing me. I did cobra init fooproject and then inside the project dir I did cobra add bar. I have a PersistentFlag that is named foo and here is the init function from the root command.

func Execute() {
    if err := RootCmd.Execute(); err != nil {
        fmt.Println(err)
        os.Exit(-1)
    }

    fmt.Println(cfgFile)
    fmt.Println("fooString is: ", fooString)
}


func init() {
    cobra.OnInitialize(initConfig)

    // Here you will define your flags and configuration settings.
    // Cobra supports Persistent Flags, which, if defined here,
    // will be global for your application.

    RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.fooproject.yaml)")
    RootCmd.PersistentFlags().StringVar(&fooString, "foo", "", "loaded from config")

    viper.BindPFlag("foo", RootCmd.PersistentFlags().Lookup("foo"))
    // Cobra also supports local flags, which will only run
    // when this action is called directly.
    RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

My configuration file looks like this...

---
foo: aFooString

And when I call go run main.go I see this...

A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.

Usage:
  fooproject [command]

Available Commands:
  bar         A brief description of your command
  help        Help about any command

Flags:
      --config string   config file (default is $HOME/.fooproject.yaml)
      --foo string      loaded from config
  -h, --help            help for fooproject
  -t, --toggle          Help message for toggle

Use "fooproject [command] --help" for more information about a command.

fooString is:

When I call go run main.go bar I see this...

Using config file: my/gopath/github.com/user/fooproject/.fooproject.yaml
bar called

fooString is:

So it is using the configuration file, but neither one of them seems to be reading it. Maybe I am misunderstanding the way that Cobra and Viper work. Any ideas?

like image 998
Joff Avatar asked May 08 '17 12:05

Joff


People also ask

How do I update Cobra software via Internet?

1) Start the COBRA Administration Manager. 2) Choose the ‘File’ menu option. 3) Select the ‘Update Software via Internet’ option. 4) Choose the type of Internet connection you have. 5) Click the ‘Next’ button. 6) Wait for the files to be downloaded and then click ‘Next’ to proceed.

What if the Cobra Administration Manager is missing a file?

At this point the COBRA Administration Manager should start with all your existing data. If you receive an error after attempting to start the COBRA Administration Manager stating you are missing a file called "DFINFO32.OCX" or some other "OCX" or "DLL", you will need to download and install the Windows System Files.

What happens if you don’t pay your Cobra?

“This can be caused by banking errors, technical errors, and using the wrong information,” Cummins notes. “You are at risk of losing all your COBRA rights if your payments are not paid within the grace period, so do not delay.”

Why is my employer not giving me my Cobra enrollment packet?

“This can occur when employers — often smaller companies without in-house human resources personnel — neglect to provide the required COBRA information notice,” says Brian Martucci, finance editor with Money Crashers. “If this happens to you, ask your HR point of contact to provide the enrollment packet.”


2 Answers

To combine spf13/cobra and spf13/viper, first define the flag with Cobra:

RootCmd.PersistentFlags().StringP("foo", "", "loaded from config")

Bind it with Viper:

viper.BindPFlag("foo", RootCmd.PersistentFlags().Lookup("foo"))

And get the variable via the Viper's method:

fmt.Println("fooString is: ", viper.GetString("foo"))
like image 88
minamijoyo Avatar answered Oct 03 '22 08:10

minamijoyo


Since Viper values are somewhat inferior to pflags (e.g. no support for custom data types), I was not satisfied with answer "use Viper to retrieve values", and ended up writing small helper type to put values back in pflags.

type viperPFlagBinding struct {
        configName string
        flagValue  pflag.Value
}

type viperPFlagHelper struct {
        bindings []viperPFlagBinding
}

func (vch *viperPFlagHelper) BindPFlag(configName string, flag *pflag.Flag) (err error) {
        err = viper.BindPFlag(configName, flag)
        if err == nil {
                vch.bindings = append(vch.bindings, viperPFlagBinding{configName, flag.Value})
        }
        return
}

func (vch *viperPFlagHelper) setPFlagsFromViper() {
        for _, v := range vch.bindings {
                v.flagValue.Set(viper.GetString(v.configName))
        }
}


func main() {
        var rootCmd = &cobra.Command{}
        var viperPFlagHelper viperPFlagHelper

        rootCmd.PersistentFlags().StringVar(&config.Password, "password", "", "API server password (remote HTTPS mode only)")
        viperPFlagHelper.BindPFlag("password", rootCmd.Flag("password"))

        rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
                err := viper.ReadInConfig()
                if err != nil {
                        if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
                                return err
                        }
                }

                viperPFlagHelper.setPFlagsFromViper()

                return nil
        }
}
like image 22
WGH Avatar answered Oct 03 '22 08:10

WGH