-
Notifications
You must be signed in to change notification settings - Fork 33
Description
consider a config struct like
type Config struct {
Foo *CustomFoo `fig:"foo_config_file"`
}where CustomFoo:
type CustomFoo struct {
Bar string `json:"bar"`
Baz string `json:"baz"`
}
func (c *CustomFoo) UnmarshalString(s string) error {
fmt.Println(s)
file, err := os.ReadFile(s)
if err != nil {
return err
}
err = json.Unmarshal(file, &c)
if err != nil {
return err
}
return nil
}
if you attempt to fill CustomFoo by passing a filename to UnmarshalString, it should read that file, then unmarshal into the CustomFoo struct. However, if you attempt to override the config with environment variables, the struct will attempt to be built twice, the first time with the value from config.yaml and the second time with the environment variable. if UnmarshalString returns an error it fails the config loading process. I'm attaching a runnable reproducer at the bottom, but IMO fig should wait until it has merged the different sources of config before it attempts to actually construct the final struct it will return to the caller.
expected result:
the Config struct is generated with Foo.Bar and Foo.Baz populated
actual result:
the foo.json file referenced in config.yaml is opened (and doesn't exist), rather than the foo_custom.json file referenced in the environment variables
error: 1 error(s) decoding:
* error decoding 'foo_config_file': open foo.json: no such file or directory
exit status 1
full example
package main
import (
"encoding/json"
"fmt"
"os"
"github.com/kkyr/fig"
)
type CustomFoo struct {
Bar string `json:"bar"`
Baz string `json:"baz"`
}
func (c *CustomFoo) UnmarshalString(s string) error {
fmt.Println(s)
file, err := os.ReadFile(s)
if err != nil {
return err
}
err = json.Unmarshal(file, &c)
if err != nil {
return err
}
return nil
}
type Config struct {
Foo *CustomFoo `fig:"foo_config_file"`
}
func main() {
err := os.Setenv("MYAPP_FOO_CONFIG_FILE", "custom_foo.json")
if err != nil {
fmt.Printf("error: %v\n", err)
os.Exit(1)
}
var cfg Config
err = fig.Load(&cfg, fig.UseEnv("MYAPP"))
if err != nil {
fmt.Printf("error: %v\n", err)
os.Exit(1)
}
fmt.Printf("%v\n", cfg)
}config.yaml:
foo_config_file: "foo.json"
foo.json: non-existent
custom_foo.json:
{
"bar": "hello",
"baz": "world"
}