config: add Save/Load options
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
		| @@ -20,25 +20,27 @@ var ( | |||||||
|  |  | ||||||
| // Config is an interface abstraction for dynamic configuration | // Config is an interface abstraction for dynamic configuration | ||||||
| type Config interface { | type Config interface { | ||||||
|  | 	// Name returns name of config | ||||||
| 	Name() string | 	Name() string | ||||||
| 	// Init the config | 	// Init the config | ||||||
| 	Init(opts ...Option) error | 	Init(opts ...Option) error | ||||||
| 	// Options in the config | 	// Options in the config | ||||||
| 	Options() Options | 	Options() Options | ||||||
| 	// Load config from sources | 	// Load config from sources | ||||||
| 	Load(context.Context) error | 	Load(context.Context, ...LoadOption) error | ||||||
| 	// Save config to sources | 	// Save config to sources | ||||||
| 	Save(context.Context) error | 	Save(context.Context, ...SaveOption) error | ||||||
| 	// Watch a value for changes | 	// Watch a value for changes | ||||||
| 	//	Watch(interface{}) (Watcher, error) | 	//Watch(context.Context) (Watcher, error) | ||||||
|  | 	// String returns config type name | ||||||
| 	String() string | 	String() string | ||||||
| } | } | ||||||
|  |  | ||||||
| // Watcher is the config watcher | // Watcher is the config watcher | ||||||
| // type Watcher interface { | type Watcher interface { | ||||||
| //	Next() (, error) | 	// Next() (, error) | ||||||
| //	Stop() error | 	Stop() error | ||||||
| // } | } | ||||||
|  |  | ||||||
| // Load loads config from config sources | // Load loads config from config sources | ||||||
| func Load(ctx context.Context, cs ...Config) error { | func Load(ctx context.Context, cs ...Config) error { | ||||||
|   | |||||||
| @@ -25,18 +25,27 @@ func (c *defaultConfig) Init(opts ...Option) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (c *defaultConfig) Load(ctx context.Context) error { | func (c *defaultConfig) Load(ctx context.Context, opts ...LoadOption) error { | ||||||
| 	for _, fn := range c.opts.BeforeLoad { | 	for _, fn := range c.opts.BeforeLoad { | ||||||
| 		if err := fn(ctx, c); err != nil && !c.opts.AllowFail { | 		if err := fn(ctx, c); err != nil && !c.opts.AllowFail { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	options := NewLoadOptions(opts...) | ||||||
|  | 	mopts := []func(*mergo.Config){mergo.WithTypeCheck} | ||||||
|  | 	if options.Override { | ||||||
|  | 		mopts = append(mopts, mergo.WithOverride) | ||||||
|  | 	} | ||||||
|  | 	if options.Append { | ||||||
|  | 		mopts = append(mopts, mergo.WithAppendSlice) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	src, err := rutil.Zero(c.opts.Struct) | 	src, err := rutil.Zero(c.opts.Struct) | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		valueOf := reflect.ValueOf(src) | 		valueOf := reflect.ValueOf(src) | ||||||
| 		if err = c.fillValues(valueOf); err == nil { | 		if err = c.fillValues(valueOf); err == nil { | ||||||
| 			err = mergo.Merge(c.opts.Struct, src, mergo.WithOverride, mergo.WithTypeCheck, mergo.WithAppendSlice) | 			err = mergo.Merge(c.opts.Struct, src, mopts...) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -232,7 +241,7 @@ func (c *defaultConfig) fillValues(valueOf reflect.Value) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (c *defaultConfig) Save(ctx context.Context) error { | func (c *defaultConfig) Save(ctx context.Context, opts ...SaveOption) error { | ||||||
| 	for _, fn := range c.opts.BeforeSave { | 	for _, fn := range c.opts.BeforeSave { | ||||||
| 		if err := fn(ctx, c); err != nil && !c.opts.AllowFail { | 		if err := fn(ctx, c); err != nil && !c.opts.AllowFail { | ||||||
| 			return err | 			return err | ||||||
|   | |||||||
| @@ -57,6 +57,52 @@ func NewOptions(opts ...Option) Options { | |||||||
| 	return options | 	return options | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // LoadOption function signature | ||||||
|  | type LoadOption func(o *LoadOptions) | ||||||
|  |  | ||||||
|  | // LoadOptions struct | ||||||
|  | type LoadOptions struct { | ||||||
|  | 	Override bool | ||||||
|  | 	Append   bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewLoadOptions(opts ...LoadOption) LoadOptions { | ||||||
|  | 	options := LoadOptions{} | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&options) | ||||||
|  | 	} | ||||||
|  | 	return options | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // LoadOverride override values when load | ||||||
|  | func LoadOverride(b bool) LoadOption { | ||||||
|  | 	return func(o *LoadOptions) { | ||||||
|  | 		o.Override = b | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // LoadAppend override values when load | ||||||
|  | func LoadAppend(b bool) LoadOption { | ||||||
|  | 	return func(o *LoadOptions) { | ||||||
|  | 		o.Append = b | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SaveOption function signature | ||||||
|  | type SaveOption func(o *SaveOptions) | ||||||
|  |  | ||||||
|  | // SaveOptions struct | ||||||
|  | type SaveOptions struct { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func NewSaveOptions(opts ...SaveOption) SaveOptions { | ||||||
|  | 	options := SaveOptions{} | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&options) | ||||||
|  | 	} | ||||||
|  | 	return options | ||||||
|  | } | ||||||
|  |  | ||||||
| // AllowFail allows config source to fail | // AllowFail allows config source to fail | ||||||
| func AllowFail(b bool) Option { | func AllowFail(b bool) Option { | ||||||
| 	return func(o *Options) { | 	return func(o *Options) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user