From 6d70d9dd0e8437426477e2aac908c8603ef45431 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 11 Jun 2020 02:57:46 +0000 Subject: [PATCH 1/3] [feat] add load opts fromEnv --- go.mod | 1 + go.sum | 2 ++ loader.go | 77 +++++++++++++++++++++++++++----------------------- loader_test.go | 52 ++++++++++++++++++++++++++++------ 4 files changed, 88 insertions(+), 44 deletions(-) diff --git a/go.mod b/go.mod index a68b5cd..8b8f830 100644 --- a/go.mod +++ b/go.mod @@ -5,5 +5,6 @@ go 1.14 require ( git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349 github.com/BurntSushi/toml v0.3.1 + github.com/otakukaze/envconfig v1.0.4 gopkg.in/yaml.v2 v2.3.0 ) diff --git a/go.sum b/go.sum index a50e755..313e2e2 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349 h1:V6ifeiJ3ExnjaUylTO git.trj.tw/golang/utils v0.0.0-20190225142552-b019626f0349/go.mod h1:yE+qbsUsijCTdwsaQRkPT1CXYk7ftMzXsCaaYx/0QI0= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/otakukaze/envconfig v1.0.4 h1:/rZ8xq1vFpgWzqsqUkk61doDGNv9pIXqrog/mCvSx8Y= +github.com/otakukaze/envconfig v1.0.4/go.mod h1:v2dNv5NX1Lakw3FTAkbxYURyaiOy68M8QpMTZz+ogfs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= diff --git a/loader.go b/loader.go index 9deffd0..7a6639a 100644 --- a/loader.go +++ b/loader.go @@ -9,6 +9,7 @@ import ( "git.trj.tw/golang/utils" "github.com/BurntSushi/toml" + "github.com/otakukaze/envconfig" "gopkg.in/yaml.v2" ) @@ -27,6 +28,7 @@ type ConfigFile struct { type LoadOptions struct { ConfigFile *ConfigFile + FromEnv bool } func Load(i interface{}, opts *LoadOptions) error { @@ -50,48 +52,51 @@ func Load(i interface{}, opts *LoadOptions) error { return nil } - // no config file - if opts.ConfigFile == nil { - return nil - } + // load config file + if opts.ConfigFile != nil { + if opts.ConfigFile.Path == "" { + return errors.New("config file path empty") + } - if opts.ConfigFile.Path == "" { - return errors.New("config file path empty") - } + // resolve file path + opts.ConfigFile.Path = utils.ParsePath(opts.ConfigFile.Path) + // check file exists + if !utils.CheckExists(opts.ConfigFile.Path, false) { + return errors.New("config file not found") + } - // resolve file path - opts.ConfigFile.Path = utils.ParsePath(opts.ConfigFile.Path) - // check file exists - if !utils.CheckExists(opts.ConfigFile.Path, false) { - return errors.New("config file not found") - } - - filebyte, err := ioutil.ReadFile(opts.ConfigFile.Path) - if err != nil { - return err - } - - switch opts.ConfigFile.Type { - case ConfigFileTypeJSON: - err := json.Unmarshal(filebyte, i) + filebyte, err := ioutil.ReadFile(opts.ConfigFile.Path) if err != nil { return err } - break - case ConfigFileTypeTOML: - err := toml.Unmarshal(filebyte, i) - if err != nil { - return err + + switch opts.ConfigFile.Type { + case ConfigFileTypeJSON: + err := json.Unmarshal(filebyte, i) + if err != nil { + return err + } + break + case ConfigFileTypeTOML: + err := toml.Unmarshal(filebyte, i) + if err != nil { + return err + } + break + case ConfigFileTypeYAML: + err := yaml.Unmarshal(filebyte, i) + if err != nil { + return err + } + break + default: + return errors.New("file type not impl") } - break - case ConfigFileTypeYAML: - err := yaml.Unmarshal(filebyte, i) - if err != nil { - return err - } - break - default: - return errors.New("file type not impl") + } + + // load config from env + if opts.FromEnv { + envconfig.Parse(i) } return nil diff --git a/loader_test.go b/loader_test.go index 9430508..ba1d375 100644 --- a/loader_test.go +++ b/loader_test.go @@ -1,6 +1,7 @@ package confloader import ( + "os" "reflect" "testing" ) @@ -13,8 +14,8 @@ func TestLoad(t *testing.T) { Key string `json:"key" yaml:"key" toml:"key"` } type Config struct { - StrKey string `json:"strKey" yaml:"strKey" toml:"strKey" default:"def value"` - IntKey int `json:"intKey" yaml:"intKey" toml:"intKey"` + StrKey string `json:"strKey" yaml:"strKey" toml:"strKey" default:"def value" env:"TEST_STR"` + IntKey int `json:"intKey" yaml:"intKey" toml:"intKey" env:"TEST_INT"` BoolKey bool `json:"boolKey" yaml:"boolKey" toml:"boolKey"` FloatKey float64 `json:"floatKey" yaml:"floatKey" toml:"floatKey"` StrArr []string `json:"strArr" yaml:"strArr" toml:"strArr" default:"arrval" length:"1"` @@ -23,6 +24,9 @@ func TestLoad(t *testing.T) { ArrObj []ArrObj `json:"arrObj" yaml:"arrObj" toml:"arrObj"` } + os.Setenv("TEST_STR", "string value2") + os.Setenv("TEST_INT", "2000") + expected := Config{ StrKey: "string value", IntKey: 1000, @@ -35,8 +39,20 @@ func TestLoad(t *testing.T) { }, ArrObj: []ArrObj{{Key: "val"}}, } + expectedWithEnv := Config{ + StrKey: "string value2", + IntKey: 2000, + BoolKey: true, + FloatKey: 1.2345, + StrArr: []string{"arr1"}, + StrArr2: []string{"arrval2", "arrval2"}, + ObjKey: ObjKey{ + Name: "name", + }, + ArrObj: []ArrObj{{Key: "val"}}, + } - src := Config{} + // src := Config{} type args struct { i interface{} @@ -51,7 +67,7 @@ func TestLoad(t *testing.T) { { name: "test load json file with default", args: args{ - i: &src, + i: &Config{}, opts: &LoadOptions{ ConfigFile: &ConfigFile{ Type: ConfigFileTypeJSON, @@ -64,7 +80,7 @@ func TestLoad(t *testing.T) { { name: "test load yaml file with default", args: args{ - i: &src, + i: &Config{}, opts: &LoadOptions{ ConfigFile: &ConfigFile{ Type: ConfigFileTypeYAML, @@ -77,7 +93,7 @@ func TestLoad(t *testing.T) { { name: "test load toml file with default", args: args{ - i: &src, + i: &Config{}, opts: &LoadOptions{ ConfigFile: &ConfigFile{ Type: ConfigFileTypeTOML, @@ -87,14 +103,34 @@ func TestLoad(t *testing.T) { }, wantErr: false, }, + { + name: "test load json file with default and env", + args: args{ + i: &Config{}, + opts: &LoadOptions{ + ConfigFile: &ConfigFile{ + Type: ConfigFileTypeJSON, + Path: "./test/config.json", + }, + FromEnv: true, + }, + }, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := Load(tt.args.i, tt.args.opts); (err != nil) != tt.wantErr { t.Errorf("Load() error = %v, wantErr %v", err, tt.wantErr) } - if !reflect.DeepEqual(src, expected) { - t.Errorf("Load and expected not match") + if tt.args.opts != nil && tt.args.opts.FromEnv { + if !reflect.DeepEqual(tt.args.i, expectedWithEnv) { + t.Errorf("Load and expected not match") + } + } else { + if !reflect.DeepEqual(tt.args.i, expected) { + t.Errorf("Load and expected not match") + } } }) } From 855a1f508cf5f04e88dec6be13129edd05ed7ca0 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 11 Jun 2020 03:03:35 +0000 Subject: [PATCH 2/3] [fix] fix type error --- loader_test.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/loader_test.go b/loader_test.go index ba1d375..35da841 100644 --- a/loader_test.go +++ b/loader_test.go @@ -67,7 +67,6 @@ func TestLoad(t *testing.T) { { name: "test load json file with default", args: args{ - i: &Config{}, opts: &LoadOptions{ ConfigFile: &ConfigFile{ Type: ConfigFileTypeJSON, @@ -80,7 +79,6 @@ func TestLoad(t *testing.T) { { name: "test load yaml file with default", args: args{ - i: &Config{}, opts: &LoadOptions{ ConfigFile: &ConfigFile{ Type: ConfigFileTypeYAML, @@ -93,7 +91,6 @@ func TestLoad(t *testing.T) { { name: "test load toml file with default", args: args{ - i: &Config{}, opts: &LoadOptions{ ConfigFile: &ConfigFile{ Type: ConfigFileTypeTOML, @@ -106,7 +103,6 @@ func TestLoad(t *testing.T) { { name: "test load json file with default and env", args: args{ - i: &Config{}, opts: &LoadOptions{ ConfigFile: &ConfigFile{ Type: ConfigFileTypeJSON, @@ -120,15 +116,17 @@ func TestLoad(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + src := Config{} + tt.args.i = &src if err := Load(tt.args.i, tt.args.opts); (err != nil) != tt.wantErr { t.Errorf("Load() error = %v, wantErr %v", err, tt.wantErr) } if tt.args.opts != nil && tt.args.opts.FromEnv { - if !reflect.DeepEqual(tt.args.i, expectedWithEnv) { + if !reflect.DeepEqual(src, expectedWithEnv) { t.Errorf("Load and expected not match") } } else { - if !reflect.DeepEqual(tt.args.i, expected) { + if !reflect.DeepEqual(src, expected) { t.Errorf("Load and expected not match") } } From 83dd096a9a24f2214bc68056c5be930efa5fbff8 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 11 Jun 2020 03:04:06 +0000 Subject: [PATCH 3/3] [chore] add ignore file --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp