spf13 / viper

Go configuration with fangs
MIT License
26.89k stars 2.01k forks source link

viper cannot unmarshal config #714

Open daixiang0 opened 5 years ago

daixiang0 commented 5 years ago

Reproduce: main.go:

package main

import (
    "flag"
    "os"
    "path"
    "fmt"
    "strings"

    "github.com/cortexproject/cortex/pkg/util/flagext"
    "github.com/spf13/pflag"
    "github.com/spf13/viper"
)

type Config struct {
    ClientConfig    clientConfig    `yaml:"client,omitempty"`
    ClientConfigs   []clientConfig  `yaml:"clients,omitempty"`
}

type clientConfig struct {
    URL       flagext.URLValue
}

func (c *Config) RegisterFlags(f *flag.FlagSet) {
        c.ClientConfig.RegisterFlags(f)
}

func (c *clientConfig) RegisterFlags(flags *flag.FlagSet) {
    flags.Var(&c.URL, "client.url", "URL of log server")
} 

func main() {
    var (
        configFile = "cmd/promtail/promtail-local-config.yaml"
        config     Config
    )

    flag.StringVar(&configFile, "config.file", "promtail.yml", "The config file.")
    flagext.RegisterFlags(&config)
    pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
    pflag.Parse()

    if err := viper.BindPFlags(pflag.CommandLine); err != nil {
        fmt.Println("msg", "error parsing flags", "err", err)
        os.Exit(1)
    }

    configFile = viper.GetString("config.file")
    viper.SetConfigType("yaml")
    viper.SetConfigName(strings.TrimSuffix(path.Base(configFile), path.Ext(configFile)))
    viper.AddConfigPath(path.Dir(configFile))
    if err := viper.ReadInConfig(); err != nil {
        fmt.Println("msg", "error reading config", "filename", configFile, "err", err)
        os.Exit(1)
    }

    if err := viper.Unmarshal(&config); err != nil {
        fmt.Println("msg", "error decoding config", "filename", configFile, "err", err)
        os.Exit(1)
    }
}

configfile:

clients:
  - url: http://localhost
$ go build main.go
$ ./main --config.file configfile

The bug is that config.ClientConfigs is empty.

daixiang0 commented 5 years ago

Hi, @sagikazarmark @spf13 mind have a look?

daixiang0 commented 5 years ago

I use 1.4.0 version.

daixiang0 commented 5 years ago

A more simple example:

package main

import (
    "os"
    "path"
    "fmt"
    "strings"

        "github.com/spf13/viper"
)

type Config struct {
    ClientConfig    clientConfig    `yaml:"client,omitempty"`
    ClientConfigs   []clientConfig  `yaml:"clients,omitempty"`
}

type clientConfig struct {
    URL       string `"yaml: url"`
}

func main() {
    var (
        configFile = "cmd/promtail/promtail-local-config.yaml"
        config     Config
    )

    configFile = "path/to/config.yml"
    viper.SetConfigType("yaml")
    viper.SetConfigName(strings.TrimSuffix(path.Base(configFile), path.Ext(configFile)))
    viper.AddConfigPath(path.Dir(configFile))
    if err := viper.ReadInConfig(); err != nil {
        fmt.Println("msg", "error reading config", "filename", configFile, "err", err)
        os.Exit(1)
    }

    if err := viper.Unmarshal(&config); err != nil {
        fmt.Println("msg", "error decoding config", "filename", configFile, "err", err)
        os.Exit(1)
    }
    viper.Debug()
    for i := range config.ClientConfigs {
        fmt.Println("config: ", i)
    }
    fmt.Println("url: ",config.ClientConfig.URL)
}

All fmt print is empty.

daixiang0 commented 5 years ago

Seems is mapstructure issue

daixiang0 commented 5 years ago

@sagikazarmark could help me?

sagikazarmark commented 5 years ago

Looks like you received an answer on the mapstructure issue tracker. Is your issue resolved?

daixiang0 commented 5 years ago

still not resolved :(

daixiang0 commented 5 years ago

@sagikazarmark hi, i add a hook but still failed, please help me!