config icon indicating copy to clipboard operation
config copied to clipboard

Breaking change for NewProviderGroup in 1.3.0?

Open tormoder opened this issue 5 years ago • 2 comments

I'm reading a single config file where I want to override values based on priority. My initial code below worked with 1.1.0, but does not with 1.3.0. I understand that some functions have been marked deprecated in 1.3.0, but the README explicitly states that "no breaking changes will be made in the 1.x series of releases".

I see that the new NewYAML function can take multiple files with priority, but I want to read and merge a single file. Is there another way to do this in 1.3.0?

Reproduction:

config.yml file:

---
default:
  foo: Base
other:
  foo: Override

main.go:

package main

import (
        "fmt"

        "go.uber.org/config"
)

func main() {
        var conf struct {
                Foo string `yaml:"foo"`
        }

        provider, err := fromSpecificEnvs("config.yml", "default", "other")
        if err != nil {
                panic(err)
        }

        if err := provider.Get(config.Root).Populate(&conf); err != nil {
                panic(err)
        }

        fmt.Printf("Foo: %q\n", conf.Foo)
}

func fromSpecificEnvs(filepath string, envs ...string) (config.Provider, error) {
        baseProvider, err := config.NewYAMLProviderFromFiles(filepath)
        if err != nil {
                return nil, fmt.Errorf("error parsing config file: %v", err)
        }

        var subProviders []config.Provider
        for _, env := range envs {
                sp := config.NewScopedProvider(env, baseProvider)
                subProviders = append(subProviders, sp)
        }

        return config.NewProviderGroup("config", subProviders...)
}

Result using 1.1.0: Foo: "Override"

Result using 1.3.0: Foo: ""

tormoder avatar Sep 07 '18 07:09 tormoder

Any suggestions on what I'm doing wrong/how to adjust?

tormoder avatar Mar 31 '19 09:03 tormoder

@tormoder Apologies for a long turn-around. This seems to have slipped under the cracks.

It's not entirely clear what you are trying to do since you're doing overrides in the same file. I can only assume that you have some sort of a base configuration object and you introduce new flavors as you go along. If that is the case, you can use YAML itself, rather than relying on the config library.

The Go yaml parser supports anchors as far as I can tell (although I've never used it in any meaningful capacity).

Here is an example.

Config file that has an object with base values and a,b that inherit and override values.

❯ cat config.yaml
base: &base
  foo: bar
  herp: derp
a:
  <<: *base
  foo: baz
b:
  <<: *base
  herp: NOPE
❯ cat main.go
package main

import (
        "fmt"

        "go.uber.org/config"
)

func main() {
        type obj struct {
                Foo  string `yaml:"foo"`
                Herp string `yaml:"herp"`
        }
        var conf struct {
                A obj `yaml:"a"`
                B obj `yaml:"b"`
        }

        provider, err := config.NewYAMLProviderFromFiles("config.yaml")
        if err != nil {
                panic(err)
        }

        if err := provider.Get(config.Root).Populate(&conf); err != nil {
                panic(err)
        }

        fmt.Println("A >>", conf.A)
        fmt.Println("B >>", conf.B)
}

As you can see running it produces the correct A,B structs that contain the override values, and the inheritance from default.

❯ go run main.go
A >> {baz derp}
B >> {bar NOPE}

Perhaps that is what you are looking for?

glibsm avatar Apr 01 '19 16:04 glibsm