Skip to content

Commit

Permalink
add new feature: load config from cmd flags
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Nov 23, 2018
1 parent 201a3b7 commit 584fe03
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 6 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ golang application config manage tool library.
- support multi format: `JSON`(default), `INI`, `YAML`, `TOML`, `HCL`
- `JSON` content support comments. will auto clear comments
- support multi file/data load
- support data override merge
- support for loading configuration data from remote URLs
- support for setting configuration data from command line arguments
- support data overlay and merge, automatically load by key when loading multiple copies of data
- support get sub value by path, like `map.key` `arr.2`
- support parse ENV name. like `envKey: ${SHELL}` -> `envKey: /bin/zsh`
- generic api `Get` `Int` `String` `Bool` `Ints` `IntMap` `Strings` `StringMap` ...
Expand Down Expand Up @@ -154,8 +156,10 @@ fmt.Print(ok, name) // true "new name"
### Load Config

- `LoadData(dataSource ...interface{}) (err error)`
- `LoadFlags(keys []string) (err error)`
- `LoadExists(sourceFiles ...string) (err error)`
- `LoadFiles(sourceFiles ...string) (err error)`
- `LoadRemote(format, url string) (err error)`
- `LoadSources(format string, src []byte, more ...[]byte) (err error)`
- `LoadStrings(format string, str string, more ...string) (err error)`

Expand Down
6 changes: 5 additions & 1 deletion README_cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ golang应用程序配置管理工具库。
- 支持多种格式: `JSON`(default), `INI`, `YAML`, `TOML`, `HCL`
- `JSON` 内容支持注释,将自动清除注释
- 支持多个文件/数据加载
- 支持数据覆盖合并,将按key自动合并
- 支持数据覆盖合并,加载多份数据时将按key自动合并
- 支持从远程URL加载配置数据
- 支持从命令行参数设置配置数据
- 支持按路径获取子级值。 e.g `map.key` `arr.2`
- 支持解析ENV变量名称。 like `shell: ${SHELL}` -> `shell: /bin/zsh`
- 简洁的使用API `Get` `Int` `String` `Bool` `Ints` `IntMap` `Strings` `StringMap` ...
Expand Down Expand Up @@ -155,8 +157,10 @@ fmt.Print(ok, name) // true "new name"
### 载入配置

- `LoadData(dataSource ...interface{}) (err error)`
- `LoadFlags(keys []string) (err error)`
- `LoadExists(sourceFiles ...string) (err error)`
- `LoadFiles(sourceFiles ...string) (err error)`
- `LoadRemote(format, url string) (err error)`
- `LoadSources(format string, src []byte, more ...[]byte) (err error)`
- `LoadStrings(format string, str string, more ...string) (err error)`

Expand Down
6 changes: 4 additions & 2 deletions config_get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ func TestGet(t *testing.T) {
st.Equal("", str)

// get float
c.Set("flVal", 23.45)
err = c.Set("flVal", 23.45)
st.Nil(err)
flt, ok := c.Float("flVal")
st.True(ok)
st.Equal(23.45, flt)
Expand Down Expand Up @@ -196,7 +197,8 @@ func TestGet(t *testing.T) {
st.False(ok)

// set a intMap
Set("intMap0", map[string]int{"a": 1, "b": 2})
err = Set("intMap0", map[string]int{"a": 1, "b": 2})
st.Nil(err)
imp, ok = IntMap("intMap0")
st.True(ok)
st.NotEmpty(imp)
Expand Down
31 changes: 31 additions & 0 deletions config_load.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package config

import (
"errors"
"flag"
"fmt"
"github.com/imdario/mergo"
"io/ioutil"
Expand Down Expand Up @@ -99,6 +100,36 @@ func (c *Config) LoadRemote(format, url string) (err error) {
return
}

// LoadFlags parse command line arguments, based on provide keys.
// Usage:
// c.LoadFlags([]string{"env", "debug"})
func (c *Config) LoadFlags(keys []string) (err error) {
hash := map[string]*string{}
for _, key := range keys {
hash[key] = new(string)
defVal, _ := c.String(key)
flag.StringVar(hash[key], key, defVal, "")
}

flag.Parse()
flag.Visit(func(f *flag.Flag) {
name := f.Name
// name := strings.Replace(f.Name, "-", ".", -1)

// only get name in the keys.
if _, ok := hash[name]; !ok {
return
}

err = c.Set(name, f.Value.String())
if err != nil {
return
}
})

return
}

// LoadData load data from map OR struct
func (c *Config) LoadData(dataSources ...interface{}) (err error) {
for _, ds := range dataSources {
Expand Down
39 changes: 37 additions & 2 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"github.com/stretchr/testify/assert"
"os"
"testing"
)

Expand Down Expand Up @@ -53,7 +54,10 @@ func Example() {
}

// load from string
LoadSources(JSON, []byte(jsonStr))
err = LoadSources(JSON, []byte(jsonStr))
if err != nil {
panic(err)
}

// fmt.Printf("config data: \n %#v\n", Data())
fmt.Print("get config example:\n")
Expand Down Expand Up @@ -274,6 +278,30 @@ func TestConfig_LoadRemote(t *testing.T) {
is.Error(err)
}

func TestConfig_LoadFlags(t *testing.T) {
is := assert.New(t)

// load flag info
c := New("flag")
bakArgs := os.Args
os.Args = []string{
"./cliapp",
"--name", "my-app",
"--env", "dev",
"--debug", "true",
}

err := c.LoadFlags([]string{"name", "env", "debug"})
is.Nil(err)
is.Equal("my-app", c.DefString("name", ""))
is.Equal("dev", c.DefString("env", ""))
is.True(c.DefBool("debug", false))

fmt.Printf("%#v\n",c.Data())

os.Args = bakArgs
}

func TestJSONDriver(t *testing.T) {
st := assert.New(t)

Expand Down Expand Up @@ -322,7 +350,11 @@ func TestOptions(t *testing.T) {
err := c.LoadStrings(JSON, jsonStr)
st.Nil(err)

str, ok := c.String("envKey")
str, ok := c.String("name")
st.True(ok)
st.Equal("app", str)

str, ok = c.String("envKey")
st.True(ok)
st.NotContains(str, "${")

Expand Down Expand Up @@ -371,6 +403,9 @@ func TestExport(t *testing.T) {
_, err = c.DumpTo(buf, "invalid")
at.Error(err)

_, err = c.DumpTo(buf, Yml)
at.Error(err)

_, err = c.DumpTo(buf, JSON)
at.Nil(err)
}
Expand Down

0 comments on commit 584fe03

Please sign in to comment.