add support for replacing config after node starts

- TODO: does a "locked repo" need fine-grained (i.e. field-level) locking?
This commit is contained in:
laser 2020-06-09 16:37:18 -07:00
parent 2d6b2e3811
commit cf321f7667
5 changed files with 62 additions and 7 deletions

View File

@ -412,7 +412,7 @@ func Repo(r repo.Repo) Option {
if err != nil {
return err
}
c, err := lr.GetConfig()
c, err := lr.Config()
if err != nil {
return err
}

View File

@ -11,6 +11,7 @@ import (
"strings"
"sync"
"github.com/BurntSushi/toml"
"github.com/ipfs/go-datastore"
fslock "github.com/ipfs/go-fs-lock"
logging "github.com/ipfs/go-log/v2"
@ -271,6 +272,29 @@ func (fsr *fsLockedRepo) Config() (interface{}, error) {
return config.FromFile(fsr.join(fsConfig), defConfForType(fsr.repoType))
}
func (fsr *fsLockedRepo) SetConfig(cfg interface{}) error {
if err := fsr.stillValid(); err != nil {
return err
}
tmp, err := ioutil.TempFile("", "lotus-config-temp")
if err != nil {
return err
}
err = toml.NewEncoder(tmp).Encode(cfg)
if err != nil {
return err
}
err = os.Rename(tmp.Name(), fsr.join(fsConfig))
if err != nil {
return err
}
return nil
}
func (fsr *fsLockedRepo) GetStorage() (stores.StorageConfig, error) {
fsr.storageLk.Lock()
defer fsr.storageLk.Unlock()

View File

@ -37,7 +37,8 @@ type LockedRepo interface {
Datastore(namespace string) (datastore.Batching, error)
// Returns config in this repo
GetConfig() (interface{}, error)
Config() (interface{}, error)
SetConfig(interface{}) error
GetStorage() (stores.StorageConfig, error)
SetStorage(func(*stores.StorageConfig)) error

View File

@ -30,8 +30,13 @@ type MemRepo struct {
token *byte
datastore datastore.Datastore
configF func(t RepoType) interface{}
keystore map[string]types.KeyInfo
// given a repo type, produce the default config
configF func(t RepoType) interface{}
// holds the current config value
config interface{}
}
type lockedMemRepo struct {
@ -217,11 +222,22 @@ func (lmem *lockedMemRepo) Datastore(ns string) (datastore.Batching, error) {
return namespace.Wrap(lmem.mem.datastore, datastore.NewKey(ns)), nil
}
func (lmem *lockedMemRepo) GetConfig() (interface{}, error) {
func (lmem *lockedMemRepo) Config() (interface{}, error) {
if err := lmem.checkToken(); err != nil {
return nil, err
}
return lmem.mem.configF(lmem.t), nil
if lmem.mem.config == nil {
lmem.mem.config = lmem.mem.configF(lmem.t)
}
return lmem.mem.config, nil
}
func (lmem *lockedMemRepo) SetConfig(cfg interface{}) error {
lmem.mem.config = cfg
return nil
}
func (lmem *lockedMemRepo) Storage() (stores.StorageConfig, error) {

View File

@ -9,6 +9,8 @@ import (
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/config"
"github.com/stretchr/testify/require"
)
func basicTest(t *testing.T, repo Repo) {
@ -47,10 +49,22 @@ func basicTest(t *testing.T, repo Repo) {
assert.NoError(t, err, "setting multiaddr shouldn't error")
assert.Equal(t, ma, apima, "returned API multiaddr should be the same")
cfg, err := lrepo.Config()
assert.Equal(t, config.DefaultFullNode(), cfg, "there should be a default config")
c1, err := lrepo.Config()
assert.Equal(t, config.DefaultFullNode(), c1, "there should be a default config")
assert.NoError(t, err, "config should not error")
// mutate config and persist back to repo
cfg1 := c1.(*config.FullNode)
cfg1.Client.IpfsMAddr = "duvall"
err = lrepo.SetConfig(cfg1)
assert.NoError(t, err)
// load config and verify changes
c2, err := lrepo.Config()
require.NoError(t, err)
cfg2 := c2.(*config.FullNode)
require.Equal(t, cfg2.Client.IpfsMAddr, "duvall")
err = lrepo.Close()
assert.NoError(t, err, "should be able to close")