rc: add ability for options blocks to register reload functions

This commit is contained in:
Nick Craig-Wood 2019-03-06 12:36:51 +00:00
parent 1b52f8d2a5
commit cccadfa7ae
2 changed files with 46 additions and 3 deletions

View File

@ -8,13 +8,23 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
var optionBlock = map[string]interface{}{} var (
optionBlock = map[string]interface{}{}
optionReload = map[string]func() error{}
)
// AddOption adds an option set // AddOption adds an option set
func AddOption(name string, option interface{}) { func AddOption(name string, option interface{}) {
optionBlock[name] = option 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() { func init() {
Add(Call{ Add(Call{
Path: "options/blocks", Path: "options/blocks",
@ -103,7 +113,12 @@ func rcOptionsSet(in Params) (out Params, err error) {
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to write options from block %q", name) 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 return out, nil
} }

View File

@ -1,8 +1,10 @@
package rc package rc
import ( import (
"fmt"
"testing" "testing"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -24,9 +26,21 @@ func TestAddOption(t *testing.T) {
assert.Equal(t, len(optionBlock), 0) assert.Equal(t, len(optionBlock), 0)
AddOption("potato", &testOptions) AddOption("potato", &testOptions)
assert.Equal(t, len(optionBlock), 1) assert.Equal(t, len(optionBlock), 1)
assert.Equal(t, len(optionReload), 0)
assert.Equal(t, &testOptions, optionBlock["potato"]) 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) { func TestOptionsBlocks(t *testing.T) {
defer clearOptionBlock() defer clearOptionBlock()
AddOption("potato", &testOptions) AddOption("potato", &testOptions)
@ -53,7 +67,14 @@ func TestOptionsGet(t *testing.T) {
func TestOptionsSet(t *testing.T) { func TestOptionsSet(t *testing.T) {
defer clearOptionBlock() 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") call := Calls.Get("options/set")
require.NotNil(t, call) require.NotNil(t, call)
@ -67,6 +88,12 @@ func TestOptionsSet(t *testing.T) {
require.Nil(t, out) require.Nil(t, out)
assert.Equal(t, 50, testOptions.Int) assert.Equal(t, 50, testOptions.Int)
assert.Equal(t, "hello", testOptions.String) 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 // unknown option block
in = Params{ in = Params{
@ -85,4 +112,5 @@ func TestOptionsSet(t *testing.T) {
_, err = call.Fn(in) _, err = call.Fn(in)
require.Error(t, err) require.Error(t, err)
assert.Contains(t, err.Error(), "failed to write options") assert.Contains(t, err.Error(), "failed to write options")
} }