0

I've been exploring configuration management in Go using the viper package, which I learned about in another question. I'm having trouble understanding how to initialize a new configuration. What I want to do is to find system configurations if they exist, then user configuration, and then, if all else fails, to create (and then use) a new user configuration from defaults. The next time I run the app, I'd expect to find the configuration that I previously created. I'm using it like this:

import (
    "fmt"
    "github.com/spf13/viper"
    "os"
    "os/user"
    "path/filepath"
)

usr, err := user.Current()
appMode := "test" // or "production" or...
configDir := filepath.Join(usr.HomeDir, ".myapp")
config := viper.New()

config.SetConfigName(appMode)
config.SetConfigType("json")

config.SetDefault("group1.key1", "value1.1")
config.SetDefault("group1.key2", 1234)
config.SetDefault("group2.key1", "value2.1")
config.SetDefault("group2.key2", 5678)

config.AddConfigPath("/usr/share/myapp/config")
config.AddConfigPath("/usr/local/share/myapp/config")
config.AddConfigPath(configDir)

if err := config.ReadInConfig(); err != nil {
    filename := filepath(configDir, fmt.Sprintf("%s.json", appMode))
    _, err := os.Create(filename)
    if err != nil {
        panic(fmt.Stringf("Failed to create %s", filename))
    }
}

if err := config.ReadInConfig(); err != nil {
    panic("Created %s, but Viper failed to read it: %s",
          filename, err)
}

At this point, I would like for ~/.myapp/test.json to be created for me with the following:

{
    "group1": {
        "key1": "value1.1",
        "key2": 1234
    },
    "group2": {
        "key1": "value2.1",
        "key2": 5678
    }
}

The result is that the file is empty, and the second attempt to read the file also fails with the message "open : no such file or directory" even though it exists. If I hand-edit the file, Viper finds it and parses it. Obviously I can create the JSON file programatically, but this seems like such an obvious use case that I must be missing something here.

Community
  • 1
  • 1
Scott Deerwester
  • 3,503
  • 4
  • 33
  • 56
  • 1
    Posting this as an issue / question on the Viper Github project may get you some good feedback there too. I investigated that project a bit and then just went with JSON so I could use the standard library and not have a dependency on something else. Defined a struct the way I wanted and then you can serialize to a file very easily. Viper looks to provide a lot of extra bits if you need it though. – Chris Townsend Jan 02 '16 at 18:24
  • I think this is intended behavior, iirc. Since the first two configuration locations most likely do not hold a config file, but viper is supposed to read them, it throws an error. The error handling simply is a bit rough, imho. What happens if you remove the ConfigPaths under `/usr`? – Markus W Mahlberg Jan 03 '16 at 03:40
  • There's already a issue on viper's repo: https://github.com/spf13/viper/issues/33 – yee Jan 06 '16 at 10:00

0 Answers0