Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Commented out property in YAML yields inconsistencies between Get and Unmarshal when overriding using environment variables #725

Closed
yinonavraham opened this issue Jun 23, 2019 · 1 comment · Fixed by #1429

Comments

@yinonavraham
Copy link

Unmarshal does not resolve the correct value when using environment variable and a yaml config file with commented out property.
To reproduce, see the following unit test:

func Test(t *testing.T) {
	type FooConfig struct {
		Bar string
	}
	type Config struct {
		Foo FooConfig
	}

	yamlWithValueCommented := `---
foo:
#  bar: "value from file"`

	// Overriding with OS Environment Variable
	os.Setenv("FOO_BAR", "value from env")

	v := viper.New()
	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
	v.AutomaticEnv()
	v.SetConfigType("yaml")
	v.SetDefault("foo.bar", "default value")
	v.ReadConfig(strings.NewReader(yamlWithValueCommented))
	c := Config{}
	v.Unmarshal(&c)
	fmt.Println(v.Get("foo.bar")) // As expected: "value from env"
	fmt.Println(c.Foo.Bar) // Expected: "value from env", Actual: "default value"
}

Output:

=== RUN   Test
value from env
default value
--- PASS: Test (0.00s)

The full test, which includes some sanity tests:

func Test(t *testing.T) {
	type FooConfig struct {
		Bar string
	}
	type Config struct {
		Foo FooConfig
	}

	yamlWithValue := `---
foo:
  bar: "value from file"`

	yamlWithValueCommented := `---
foo:
#  bar: "value from file"`

	v := viper.New()
	v.SetConfigType("yaml")
	v.SetDefault("foo.bar", "default value")
	v.ReadConfig(strings.NewReader(yamlWithValue))
	c := Config{}
	v.Unmarshal(&c)
	fmt.Println(v.Get("foo.bar")) // As expected: "value from file"
	fmt.Println(c.Foo.Bar) // As expected: "value from file"

	v = viper.New()
	v.SetConfigType("yaml")
	v.SetDefault("foo.bar", "default value")
	v.ReadConfig(strings.NewReader(yamlWithValueCommented))
	c = Config{}
	v.Unmarshal(&c)
	fmt.Println(v.Get("foo.bar")) // As expected: "default value"
	fmt.Println(c.Foo.Bar) // As expected: "default value"

	// Now overriding with OS Environment Variable
	os.Setenv("FOO_BAR", "value from env")

	v = viper.New()
	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
	v.AutomaticEnv()
	v.SetConfigType("yaml")
	v.SetDefault("foo.bar", "default value")
	v.ReadConfig(strings.NewReader(yamlWithValue))
	c = Config{}
	v.Unmarshal(&c)
	fmt.Println(v.Get("foo.bar")) // As expected: "value from env"
	fmt.Println(c.Foo.Bar) // As expected: "value from env"

	v = viper.New()
	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
	v.AutomaticEnv()
	v.SetConfigType("yaml")
	v.SetDefault("foo.bar", "default value")
	v.ReadConfig(strings.NewReader(yamlWithValueCommented))
	c = Config{}
	v.Unmarshal(&c)
	fmt.Println(v.Get("foo.bar")) // As expected: "value from env"
	fmt.Println(c.Foo.Bar) // Expected: "value from env", Actual: "default value"
}

Output:

=== RUN   Test
value from file
value from file
default value
default value
value from env
value from env
value from env
default value
--- PASS: Test (0.00s)
@sagikazarmark
Copy link
Collaborator

Please see and follow the issue above. ☝️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants