Add skeleton of a config
Took way longer than it should had because I was researching exisiting options. As it turns out, nothing nice exists that would handle: - Multiple overridiable config files - Defaults provided in a struct - Output in a struct License: MIT Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
This commit is contained in:
parent
46a5019c8d
commit
808a1e9deb
@ -18,6 +18,7 @@ linters:
|
|||||||
issues:
|
issues:
|
||||||
exclude:
|
exclude:
|
||||||
- "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this"
|
- "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this"
|
||||||
|
- "Potential file inclusion via variable"
|
||||||
|
|
||||||
exclude-use-default: false
|
exclude-use-default: false
|
||||||
exclude-rules:
|
exclude-rules:
|
||||||
|
5
go.mod
5
go.mod
@ -3,6 +3,9 @@ module github.com/filecoin-project/go-lotus
|
|||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/BurntSushi/toml v0.3.1
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/golang/protobuf v1.3.1 // indirect
|
||||||
github.com/ipfs/go-datastore v0.0.5
|
github.com/ipfs/go-datastore v0.0.5
|
||||||
github.com/ipfs/go-ipfs-routing v0.1.0
|
github.com/ipfs/go-ipfs-routing v0.1.0
|
||||||
github.com/ipfs/go-log v0.0.2-0.20190703113630-0c3cfb1eccc4
|
github.com/ipfs/go-log v0.0.2-0.20190703113630-0c3cfb1eccc4
|
||||||
@ -25,9 +28,11 @@ require (
|
|||||||
github.com/libp2p/go-maddr-filter v0.0.4
|
github.com/libp2p/go-maddr-filter v0.0.4
|
||||||
github.com/multiformats/go-multiaddr v0.0.4
|
github.com/multiformats/go-multiaddr v0.0.4
|
||||||
github.com/multiformats/go-multihash v0.0.5
|
github.com/multiformats/go-multihash v0.0.5
|
||||||
|
github.com/stretchr/testify v1.3.0
|
||||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
|
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
|
||||||
go.uber.org/dig v1.7.0 // indirect
|
go.uber.org/dig v1.7.0 // indirect
|
||||||
go.uber.org/fx v1.9.0
|
go.uber.org/fx v1.9.0
|
||||||
go.uber.org/goleak v0.10.0 // indirect
|
go.uber.org/goleak v0.10.0 // indirect
|
||||||
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8
|
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 // indirect
|
||||||
)
|
)
|
||||||
|
7
go.sum
7
go.sum
@ -1,5 +1,6 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||||
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
|
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
|
||||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||||
@ -22,6 +23,8 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
|||||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0=
|
github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0=
|
||||||
github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4=
|
github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4=
|
||||||
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
|
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
|
||||||
@ -40,6 +43,8 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
|||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk=
|
github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk=
|
||||||
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
||||||
|
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
@ -364,4 +369,6 @@ gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8 h1:Ggy3mWN4l3PUFPfSG0Y
|
|||||||
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8/go.mod h1:cKXr3E0k4aosgycml1b5z33BVV6hai1Kh7uDgFOkbcs=
|
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8/go.mod h1:cKXr3E0k4aosgycml1b5z33BVV6hai1Kh7uDgFOkbcs=
|
||||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
38
node/config/def.go
Normal file
38
node/config/def.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Root is starting point of the config
|
||||||
|
type Root struct {
|
||||||
|
API API
|
||||||
|
}
|
||||||
|
|
||||||
|
// API contains configs for API endpoint
|
||||||
|
type API struct {
|
||||||
|
ListenAddress string
|
||||||
|
Timeout Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default returns the default config
|
||||||
|
func Default() *Root {
|
||||||
|
def := Root{
|
||||||
|
API: API{
|
||||||
|
ListenAddress: "/ip6/::1/tcp/1234/http",
|
||||||
|
Timeout: Duration(30 * time.Second),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &def
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration is a wrapper type for time.Duration for decoding it from TOML
|
||||||
|
type Duration time.Duration
|
||||||
|
|
||||||
|
// UnmarshalText implements interface for TOML decoding
|
||||||
|
func (dur *Duration) UnmarshalText(text []byte) error {
|
||||||
|
d, err := time.ParseDuration(string(text))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*dur = Duration(d)
|
||||||
|
return err
|
||||||
|
}
|
34
node/config/load.go
Normal file
34
node/config/load.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FromFile loads config from a specified file overriding defaults specified in
|
||||||
|
// the source code. If file does not exist or is empty defaults are asummed.
|
||||||
|
func FromFile(path string) (*Root, error) {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
switch {
|
||||||
|
case os.IsNotExist(err):
|
||||||
|
return Default(), nil
|
||||||
|
case err != nil:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer file.Close() //nolint:errcheck // The file is RO
|
||||||
|
return FromReader(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromReader loads config from a reader instance.
|
||||||
|
func FromReader(reader io.Reader) (*Root, error) {
|
||||||
|
cfg := Default()
|
||||||
|
_, err := toml.DecodeReader(reader, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
63
node/config/load_test.go
Normal file
63
node/config/load_test.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDecodeNothing(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
{
|
||||||
|
cfg, err := FromFile(os.DevNull)
|
||||||
|
assert.Nil(err, "error should be nil")
|
||||||
|
assert.Equal(Default(), cfg,
|
||||||
|
"config from empty file should be the same as default")
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cfg, err := FromFile("./does-not-exist.toml")
|
||||||
|
assert.Nil(err, "error should be nil")
|
||||||
|
assert.Equal(Default(), cfg,
|
||||||
|
"config from not exisiting file should be the same as default")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParitalConfig(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
cfgString := `
|
||||||
|
[API]
|
||||||
|
Timeout = "10s"
|
||||||
|
`
|
||||||
|
expected := Default()
|
||||||
|
expected.API.Timeout = Duration(10 * time.Second)
|
||||||
|
|
||||||
|
{
|
||||||
|
cfg, err := FromReader(bytes.NewReader([]byte(cfgString)))
|
||||||
|
assert.NoError(err, "error should be nil")
|
||||||
|
assert.Equal(expected, cfg,
|
||||||
|
"config from reader should contain changes")
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
f, err := ioutil.TempFile("", "config-*.toml")
|
||||||
|
fname := f.Name()
|
||||||
|
|
||||||
|
assert.NoError(err, "tmp file shold not error")
|
||||||
|
_, err = f.WriteString(cfgString)
|
||||||
|
assert.NoError(err, "writing to tmp file should not error")
|
||||||
|
err = f.Close()
|
||||||
|
assert.NoError(err, "closing tmp file should not error")
|
||||||
|
defer os.Remove(fname) //nolint:errcheck
|
||||||
|
|
||||||
|
cfg, err := FromFile(fname)
|
||||||
|
assert.Nil(err, "error should be nil")
|
||||||
|
assert.Equal(expected, cfg,
|
||||||
|
"config from reader should contain changes")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user