Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Config file with cobra and viper

Basic information: I have created a go application and used Cobra for it. Cobra uses Viper for command line parameters and flags.

I have a command listen with a flag bind and I want to configure it in a yaml file.

Code:

The init function of the listen command looks like this:

func init() {
    RootCmd.AddCommand(listenCmd)
    listenCmd.Flags().StringP("bind", "b", ":50051", "Provide bind definition")
    viper.BindPFlag("bind", listenCmd.Flags().Lookup("bind"))
}

Code of my application is at https://github.com/sascha-andres/go-logsink

Problem:

When I call the app with listen --bind "bla" the flag is set correctly to bla, but I have not found a way to achieve this using a YAML file located in my home directory.

Config files tried:

---

connect:
  bind: "bla"

and

---

bind: "bla"

In both cases the config file was found but the flag had not the expected value but the default value.

How do I have to write the config file to have the flag populated correctly?

like image 411
Sascha Avatar asked Jan 10 '17 20:01

Sascha


1 Answers

Ok, thanks for the additional information, It helped a lot !

Problem

The problem arises from the way you're retrieving the value of the flag. Here is what you currently have:

bind := cmd.Flag("bind").Value.String()
fmt.Printf("Binding definition provided: %s\n", bind)
server.Listen(bind)

When binding a flag with viper, it's actually viper that will hold the final value, according to this priorities:

1. If present, use the flag value
2. Else, use the value from the config file
3. Else, use the default flag value

Your problem is that you retrieve the flag value from the flag set of the command, and not from viper.

Behavior

Here is the code I tested:

bind := cmd.Flag("bind").Value.String()
fmt.Printf("Binding definition provided: %s\n", bind)
fmt.Printf("Binding definition provided from viper: %s\n", viper.GetString("bind"))

Without the bind config param:

$ go-logsink listen
Using config file: /xxx/.go-logsink.yaml
Binding definition provided: :50051
Binding definition provided from viper: :50051

With the bind config param set to "bla" (not nested, second config file):

$ go-logsink listen
Using config file: /xxx/.go-logsink.yaml
Binding definition provided: :50051
Binding definition provided from viper: bla

With the bind config param set to "bla" (not nested, second config file) and an explicit flag:

$ go-logsink listen --bind ":3333"
Using config file: /xxx/.go-logsink.yaml
Binding definition provided: :3333
Binding definition provided from viper: :3333

Bottomline : when binding your flags with viper, use viper to retrieve them.

Additional note : In your README, the proper way to generate grpc compatible code is by adding the grpc plugin to protobuf generation: protoc --go_out=plugins=grpc:. *.proto

like image 112
T. Claverie Avatar answered Sep 28 '22 00:09

T. Claverie