diff --git a/viper.go b/viper.go index 3db9cd2..5a0b180 100644 --- a/viper.go +++ b/viper.go @@ -749,6 +749,42 @@ func (v *Viper) ReadConfig(in io.Reader) error { return nil } +// Loads configuration from a directory tree where filenames are keys +// and file contents are values. +func ReadDir(dirname string) error { return v.ReadDir(dirname) } +func (v *Viper) ReadDir(dirname string) error { + config, err := v.readDir(dirname, "") + if err == nil { + v.config = config + } + return err +} + +func (v *Viper) readDir(dirname, keyPrefix string) (map[string]interface{}, error) { + entries, err := ioutil.ReadDir(dirname) + if err != nil { + return nil, err + } + + node := make(map[string]interface{}) + for _, entry := range entries { + path := filepath.Join(dirname, entry.Name()) + if entry.IsDir() { + node[entry.Name()], err = v.readDir(path, keyPrefix+v.keyDelim+entry.Name()) + if err != nil { + return nil, err + } + } else { + value, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + node[entry.Name()] = strings.TrimRight(string(value), "\r\n") + } + } + return node, nil +} + // func ReadBufConfig(buf *bytes.Buffer) error { return v.ReadBufConfig(buf) } // func (v *Viper) ReadBufConfig(buf *bytes.Buffer) error { // v.config = make(map[string]interface{}) diff --git a/viper_test.go b/viper_test.go index 8d7d152..94c2e96 100644 --- a/viper_test.go +++ b/viper_test.go @@ -8,7 +8,9 @@ package viper import ( "bytes" "fmt" + "io/ioutil" "os" + "path/filepath" "sort" "strings" "testing" @@ -557,3 +559,30 @@ func TestReadBufConfig(t *testing.T) { assert.Equal(t, map[interface{}]interface{}{"jacket": "leather", "trousers": "denim", "pants": map[interface{}]interface{}{"size": "large"}}, v.Get("clothing")) assert.Equal(t, 35, v.Get("age")) } + +func TestReadDir(t *testing.T) { + dir, err := ioutil.TempDir("", "viper_test") + if err != nil { + t.Fatalf("unable to create temporary directory, %v", err) + } + if err := os.MkdirAll(filepath.Join(dir, "app", "service"), 0700); err != nil { + t.Fatalf("unable to create directory, %v", err) + } + if err := ioutil.WriteFile(filepath.Join(dir, "app", "service", "url"), []byte(`https://donuts/api/1/`), 0600); err != nil { + t.Fatalf("unable to create file, %v", err) + } + if err := ioutil.WriteFile(filepath.Join(dir, "app", "service", "key"), []byte(`0123456789abcdef`), 0600); err != nil { + t.Fatalf("unable to create file, %v", err) + } + if err := ioutil.WriteFile(filepath.Join(dir, "app", "debug"), []byte(`true`), 0600); err != nil { + t.Fatalf("unable to create file, %v", err) + } + + v := New() + v.ReadDir(dir) + t.Log(v.AllSettings()) + + assert.True(t, v.GetBool("app.debug")) + assert.Equal(t, "https://donuts/api/1/", v.Get("app.service.url")) + assert.Equal(t, "0123456789abcdef", v.Get("app.service.key")) +}