Skip to content

Commit 38668c2

Browse files
author
Aleksander Korelskiy
committed
add replaceFromStruct, GetBool methods
1 parent 96498d8 commit 38668c2

1 file changed

Lines changed: 100 additions & 19 deletions

File tree

consul.go

Lines changed: 100 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,15 @@ type Client interface {
5252
Get(key string) (*consulapi.KVPair, *consulapi.QueryMeta, error)
5353
// WatchGet
5454
WatchGet(key string) chan *consulapi.KVPair
55-
// GetStr get string value
5655
GetStr(key string) (string, error)
57-
// GetInt get string value
5856
GetInt(key string) (int, error)
57+
GetBool(key string) (bool, error)
5958
// Put put KVPair
6059
Put(key string, value string) (*consulapi.WriteMeta, error)
6160
// Load struct
6261
LoadStruct(parent string, i interface{}) error
62+
// Replace struct values
63+
ReplaceFromStruct(parent string, i interface{}) error
6364
}
6465

6566
type client struct {
@@ -153,6 +154,18 @@ func (c *client) GetInt(key string) (int, error) {
153154
return res, nil
154155
}
155156

157+
func (c *client) GetBool(key string) (bool, error) {
158+
v, err := c.GetStr(key)
159+
if err != nil {
160+
return false, err
161+
}
162+
res, err := strconv.ParseBool(string(v))
163+
if err != nil {
164+
return false, err
165+
}
166+
return res, nil
167+
}
168+
156169
// Put KVPair
157170
func (c *client) Put(key string, value string) (*consulapi.WriteMeta, error) {
158171
p := &consulapi.KVPair{Key: key, Value: []byte(value)}
@@ -216,11 +229,34 @@ func (c *client) GetServices(service string, tag string) ([]*consulapi.ServiceEn
216229
}
217230

218231
func (c *client) LoadStruct(parent string, i interface{}) error {
232+
return c.recursiveLoadStruct(c.getGroupName(parent), reflect.ValueOf(i).Elem())
233+
}
234+
235+
func (c *client) getGroupName(parent string) string {
219236
groupName := os.Getenv(groupEnvName)
220237
if groupName != "" {
221238
parent = fmt.Sprintf("%s/%s", strings.Trim(groupName, "/"), parent)
222239
}
223-
return c.recursiveLoadStruct(parent, reflect.ValueOf(i).Elem())
240+
return parent
241+
}
242+
243+
func (c *client) getKeyPath(parent string, field reflect.StructField) (string, error) {
244+
var tagOptions map[string]string
245+
var err error
246+
tagOptions, err = c.getTagOptions(field.Tag.Get("consul"))
247+
if err != nil {
248+
return "", err
249+
}
250+
251+
var kvName string
252+
if name, ok := tagOptions["name"]; ok {
253+
kvName = name
254+
} else {
255+
kvName = c.normalizeKeyName(field.Name)
256+
}
257+
258+
path := fmt.Sprintf("%s/%s", parent, kvName)
259+
return path, nil
224260
}
225261

226262
func (c *client) recursiveLoadStruct(parent string, val reflect.Value) error {
@@ -231,22 +267,12 @@ func (c *client) recursiveLoadStruct(parent string, val reflect.Value) error {
231267
var tagOptions map[string]string
232268
var err error
233269

234-
tag := field.Tag.Get("consul")
235-
if tag != "" {
236-
tagOptions, err = c.getTagOptions(tag)
237-
if err != nil {
238-
return err
239-
}
240-
}
241-
242-
var kvName string
243-
if name, ok := tagOptions["name"]; ok {
244-
kvName = name
245-
} else {
246-
kvName = c.normalizeKeyName(field.Name)
270+
tagOptions, err = c.getTagOptions(field.Tag.Get("consul"))
271+
if err != nil {
272+
return err
247273
}
248274

249-
path := fmt.Sprintf("%s/%s", parent, kvName)
275+
path, err := c.getKeyPath(parent, field)
250276

251277
if _, ok := value.Interface().(time.Time); ok {
252278
} else if field.Type.Kind() == reflect.Struct {
@@ -278,7 +304,7 @@ func (c *client) recursiveLoadStruct(parent string, val reflect.Value) error {
278304
fieldValue = kv.Value
279305
}
280306

281-
v, err := c.normalizeValue(field.Type, fieldValue)
307+
v, err := c.typifyValue(field.Type, fieldValue)
282308
if err != nil {
283309
return err
284310
}
@@ -288,7 +314,7 @@ func (c *client) recursiveLoadStruct(parent string, val reflect.Value) error {
288314
return nil
289315
}
290316

291-
func (c *client) normalizeValue(reflectType reflect.Type, value []byte) (interface{}, error) {
317+
func (c *client) typifyValue(reflectType reflect.Type, value []byte) (interface{}, error) {
292318
switch reflectType.Kind() {
293319
case reflect.String:
294320
return string(value), nil
@@ -328,6 +354,57 @@ func (c *client) normalizeValue(reflectType reflect.Type, value []byte) (interfa
328354
return nil, errors.New(fmt.Sprintf("unsupported type \"%s\"", reflectType.Kind().String()))
329355
}
330356

357+
func (c *client) ReplaceFromStruct(parent string, i interface{}) error {
358+
return c.recursiveReplaceStruct(c.getGroupName(parent), reflect.ValueOf(i).Elem())
359+
}
360+
361+
func (c *client) recursiveReplaceStruct(parent string, val reflect.Value) error {
362+
for i := 0; i < val.NumField(); i++ {
363+
value := val.Field(i)
364+
field := val.Type().Field(i)
365+
var err error
366+
367+
path, err := c.getKeyPath(parent, field)
368+
369+
if _, ok := value.Interface().(time.Time); ok {
370+
} else if field.Type.Kind() == reflect.Struct {
371+
err = c.recursiveReplaceStruct(path, value)
372+
if err != nil {
373+
return err
374+
}
375+
} else {
376+
fieldValue, err := c.stringifyValue(value)
377+
if err != nil {
378+
return err
379+
}
380+
_, err = c.Put(path, fieldValue)
381+
if err != nil {
382+
return err
383+
}
384+
}
385+
}
386+
return nil
387+
}
388+
389+
func (c *client) stringifyValue(value reflect.Value) (string, error) {
390+
switch value.Type().Kind() {
391+
case reflect.String:
392+
return value.String(), nil
393+
case reflect.Float32, reflect.Float64:
394+
return strconv.FormatFloat(value.Float(), 'f', -1, 64), nil
395+
case reflect.Int:
396+
return strconv.FormatInt(value.Int(), 10), nil
397+
case reflect.Bool:
398+
return strconv.FormatBool(value.Bool()), nil
399+
}
400+
401+
if _, ok := value.Interface().(time.Duration); ok {
402+
return strconv.FormatInt(value.Int(), 10), nil
403+
}
404+
405+
return "", errors.New(fmt.Sprintf("unsupported type \"%s\"", value.Type().Kind().String()))
406+
}
407+
331408
func (c *client) normalizeKeyName(name string) string {
332409
s := regexp.MustCompile("([A-Z]+[^A-Z]*)").FindAllString(name, -1)
333410
ss := strings.Join(s[:], ".")
@@ -337,6 +414,10 @@ func (c *client) normalizeKeyName(name string) string {
337414
func (c *client) getTagOptions(v string) (map[string]string, error) {
338415
res := make(map[string]string)
339416

417+
if v == "" {
418+
return res, nil
419+
}
420+
340421
options := strings.Split(v, ";")
341422
for _, option := range options {
342423
parts := tagOptionRegexp.FindAllStringSubmatch(option, 1)

0 commit comments

Comments
 (0)