[feat] add load opts fromEnv
This commit is contained in:
		
							parent
							
								
									e73a6d66ba
								
							
						
					
					
						commit
						6d70d9dd0e
					
				
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								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
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								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=
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										77
									
								
								loader.go
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								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
 | 
			
		||||
 | 
			
		||||
@ -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")
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user