Adds a LoadFiles function
This commit is contained in:
parent
0b733588c4
commit
a5b2b78546
5 changed files with 161 additions and 1 deletions
11
CHANGELOG.md
Normal file
11
CHANGELOG.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- Added License
|
||||||
|
- Changed the go version to 1.17
|
||||||
|
- Added a Loadfiles function to load at once several config files
|
||||||
|
|
||||||
|
## v0.1.0 (2020-03-17)
|
||||||
|
- Initial varsion
|
||||||
|
|
18
config.go
18
config.go
|
@ -4,6 +4,7 @@ package conf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
@ -16,6 +17,23 @@ func LoadFile(path string, data interface{}) error {
|
||||||
return read(path, data)
|
return read(path, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadFiles tries to load all the given paths in the given order.
|
||||||
|
//
|
||||||
|
// If a path does not exist, it is ignored.
|
||||||
|
//
|
||||||
|
// It returns an error only if the content of a file is invalid, i.e. it
|
||||||
|
// cannot be unmarshaled by json.
|
||||||
|
func LoadFiles(data interface{}, paths ...string) error {
|
||||||
|
for _, p := range paths {
|
||||||
|
err := read(p, data)
|
||||||
|
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
|
return fmt.Errorf("cannot load %q: %w", p, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SaveFile writes the given data serialized in JSON in the given path
|
// SaveFile writes the given data serialized in JSON in the given path
|
||||||
func SaveFile(path string, data interface{}) error {
|
func SaveFile(path string, data interface{}) error {
|
||||||
return write(path, data)
|
return write(path, data)
|
||||||
|
|
110
config_test.go
110
config_test.go
|
@ -3,6 +3,7 @@ package conf
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
@ -94,6 +95,115 @@ func TestLoadFile(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadFiles(t *testing.T) {
|
||||||
|
Convey("Given a config struct", t, func() {
|
||||||
|
c := &testconf{}
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
Convey("Given two existing files setting different options", func() {
|
||||||
|
content1 := []byte(`{"String": "foo"}`)
|
||||||
|
content2 := []byte(`{"Int": 42}`)
|
||||||
|
paths := []string{
|
||||||
|
filepath.Join(tmpDir, "file1.json"),
|
||||||
|
filepath.Join(tmpDir, "file2.json"),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := ioutil.WriteFile(paths[0], content1, 0o600)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
err = ioutil.WriteFile(paths[1], content2, 0o600)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("When LoadFiles is called", func() {
|
||||||
|
err := LoadFiles(&c, paths...)
|
||||||
|
|
||||||
|
Convey("Then there is no error", func() {
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("And the options from both files have been set", func() {
|
||||||
|
So(c.String, ShouldEqual, "foo")
|
||||||
|
So(c.Int, ShouldEqual, 42)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Given two existing files setting the same option", func() {
|
||||||
|
content1 := []byte(`{"String": "foo"}`)
|
||||||
|
content2 := []byte(`{"String": "bar"}`)
|
||||||
|
paths := []string{
|
||||||
|
filepath.Join(tmpDir, "file1.json"),
|
||||||
|
filepath.Join(tmpDir, "file2.json"),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := ioutil.WriteFile(paths[0], content1, 0o600)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
err = ioutil.WriteFile(paths[1], content2, 0o600)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("When LoadFiles is called", func() {
|
||||||
|
err := LoadFiles(&c, paths...)
|
||||||
|
|
||||||
|
Convey("Then there is no error", func() {
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("And the last file overwrote the first", func() {
|
||||||
|
So(c.String, ShouldEqual, "bar")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Given one non-existing and one existing files", func() {
|
||||||
|
content2 := []byte(`{"String": "bar"}`)
|
||||||
|
paths := []string{
|
||||||
|
"does-not-exist.json",
|
||||||
|
filepath.Join(tmpDir, "file2.json"),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := ioutil.WriteFile(paths[1], content2, 0o600)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("When LoadFiles is called", func() {
|
||||||
|
err := LoadFiles(&c, paths...)
|
||||||
|
|
||||||
|
Convey("Then there is no error", func() {
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("And the options from the last file have been set", func() {
|
||||||
|
So(c.String, ShouldEqual, "bar")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("Given one invalid and one valid files", func() {
|
||||||
|
content1 := []byte(`{"`)
|
||||||
|
content2 := []byte(`{"String": "bar"}`)
|
||||||
|
paths := []string{
|
||||||
|
filepath.Join(tmpDir, "file1.json"),
|
||||||
|
filepath.Join(tmpDir, "file2.json"),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := ioutil.WriteFile(paths[0], content1, 0o600)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
err = ioutil.WriteFile(paths[1], content2, 0o600)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
Convey("When LoadFiles is called", func() {
|
||||||
|
err := LoadFiles(&c, paths...)
|
||||||
|
|
||||||
|
Convey("Then an error is returned", func() {
|
||||||
|
So(err, ShouldBeError)
|
||||||
|
|
||||||
|
Convey("And the last file has not been read", func() {
|
||||||
|
So(c.String, ShouldNotEqual, "bar")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestSaveFile(t *testing.T) {
|
func TestSaveFile(t *testing.T) {
|
||||||
Convey("Given a config struct", t, func() {
|
Convey("Given a config struct", t, func() {
|
||||||
c := testconf{
|
c := testconf{
|
||||||
|
|
10
go.mod
10
go.mod
|
@ -1,3 +1,11 @@
|
||||||
module code.bcarlin.xyz/go/conf
|
module code.bcarlin.xyz/go/conf
|
||||||
|
|
||||||
go 1.14
|
go 1.17
|
||||||
|
|
||||||
|
require github.com/smartystreets/goconvey v1.7.2
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||||
|
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||||
|
)
|
||||||
|
|
13
go.sum
Normal file
13
go.sum
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||||
|
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||||
|
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
|
||||||
|
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
Loading…
Reference in a new issue