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 | ||||
| type Config interface { | ||||
| 	// Name returns name of config | ||||
| 	Name() string | ||||
| 	// Init the config | ||||
| 	Init(opts ...Option) error | ||||
| 	// Options in the config | ||||
| 	Options() Options | ||||
| 	// Load config from sources | ||||
| 	Load(context.Context) error | ||||
| 	Load(context.Context, ...LoadOption) error | ||||
| 	// Save config to sources | ||||
| 	Save(context.Context) error | ||||
| 	Save(context.Context, ...SaveOption) error | ||||
| 	// Watch a value for changes | ||||
| 	//	Watch(interface{}) (Watcher, error) | ||||
| 	//Watch(context.Context) (Watcher, error) | ||||
| 	// String returns config type name | ||||
| 	String() string | ||||
| } | ||||
|  | ||||
| // Watcher is the config watcher | ||||
| // type Watcher interface { | ||||
| //	Next() (, error) | ||||
| //	Stop() error | ||||
| // } | ||||
| type Watcher interface { | ||||
| 	// Next() (, error) | ||||
| 	Stop() error | ||||
| } | ||||
|  | ||||
| // Load loads config from config sources | ||||
| func Load(ctx context.Context, cs ...Config) error { | ||||
|   | ||||
| @@ -25,18 +25,27 @@ func (c *defaultConfig) Init(opts ...Option) error { | ||||
| 	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 { | ||||
| 		if err := fn(ctx, c); err != nil && !c.opts.AllowFail { | ||||
| 			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) | ||||
| 	if err == nil { | ||||
| 		valueOf := reflect.ValueOf(src) | ||||
| 		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 | ||||
| } | ||||
|  | ||||
| func (c *defaultConfig) Save(ctx context.Context) error { | ||||
| func (c *defaultConfig) Save(ctx context.Context, opts ...SaveOption) error { | ||||
| 	for _, fn := range c.opts.BeforeSave { | ||||
| 		if err := fn(ctx, c); err != nil && !c.opts.AllowFail { | ||||
| 			return err | ||||
|   | ||||
| @@ -57,6 +57,52 @@ func NewOptions(opts ...Option) 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 | ||||
| func AllowFail(b bool) Option { | ||||
| 	return func(o *Options) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user