diff --git a/fs/rc/config.go b/fs/rc/config.go index 741a7c55c..6e068c10d 100644 --- a/fs/rc/config.go +++ b/fs/rc/config.go @@ -8,13 +8,23 @@ import ( "github.com/pkg/errors" ) -var optionBlock = map[string]interface{}{} +var ( + optionBlock = map[string]interface{}{} + optionReload = map[string]func() error{} +) // AddOption adds an option set func AddOption(name string, option interface{}) { optionBlock[name] = option } +// AddOptionReload adds an option set with a reload function to be +// called when options are changed +func AddOptionReload(name string, option interface{}, reload func() error) { + optionBlock[name] = option + optionReload[name] = reload +} + func init() { Add(Call{ Path: "options/blocks", @@ -103,7 +113,12 @@ func rcOptionsSet(in Params) (out Params, err error) { if err != nil { return nil, errors.Wrapf(err, "failed to write options from block %q", name) } - + if reload := optionReload[name]; reload != nil { + err = reload() + if err != nil { + return nil, errors.Wrapf(err, "failed to reload options from block %q", name) + } + } } return out, nil } diff --git a/fs/rc/config_test.go b/fs/rc/config_test.go index 071dc0185..55800d58c 100644 --- a/fs/rc/config_test.go +++ b/fs/rc/config_test.go @@ -1,8 +1,10 @@ package rc import ( + "fmt" "testing" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -24,9 +26,21 @@ func TestAddOption(t *testing.T) { assert.Equal(t, len(optionBlock), 0) AddOption("potato", &testOptions) assert.Equal(t, len(optionBlock), 1) + assert.Equal(t, len(optionReload), 0) assert.Equal(t, &testOptions, optionBlock["potato"]) } +func TestAddOptionReload(t *testing.T) { + defer clearOptionBlock() + assert.Equal(t, len(optionBlock), 0) + reload := func() error { return nil } + AddOptionReload("potato", &testOptions, reload) + assert.Equal(t, len(optionBlock), 1) + assert.Equal(t, len(optionReload), 1) + assert.Equal(t, &testOptions, optionBlock["potato"]) + assert.Equal(t, fmt.Sprintf("%p", reload), fmt.Sprintf("%p", optionReload["potato"])) +} + func TestOptionsBlocks(t *testing.T) { defer clearOptionBlock() AddOption("potato", &testOptions) @@ -53,7 +67,14 @@ func TestOptionsGet(t *testing.T) { func TestOptionsSet(t *testing.T) { defer clearOptionBlock() - AddOption("potato", &testOptions) + var reloaded int + AddOptionReload("potato", &testOptions, func() error { + if reloaded > 0 { + return errors.New("error while reloading") + } + reloaded++ + return nil + }) call := Calls.Get("options/set") require.NotNil(t, call) @@ -67,6 +88,12 @@ func TestOptionsSet(t *testing.T) { require.Nil(t, out) assert.Equal(t, 50, testOptions.Int) assert.Equal(t, "hello", testOptions.String) + assert.Equal(t, 1, reloaded) + + // error from reload + _, err = call.Fn(in) + require.Error(t, err) + assert.Contains(t, err.Error(), "error while reloading") // unknown option block in = Params{ @@ -85,4 +112,5 @@ func TestOptionsSet(t *testing.T) { _, err = call.Fn(in) require.Error(t, err) assert.Contains(t, err.Error(), "failed to write options") + }