2019-10-03 11:22:35 +01:00
|
|
|
package etcd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/coreos/etcd/clientv3"
|
|
|
|
"github.com/coreos/etcd/mvcc/mvccpb"
|
2020-08-19 17:47:17 +03:00
|
|
|
"github.com/unistack-org/micro/v3/config/encoder"
|
2019-10-03 11:22:35 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func makeEvMap(e encoder.Encoder, data map[string]interface{}, kv []*clientv3.Event, stripPrefix string) map[string]interface{} {
|
|
|
|
if data == nil {
|
|
|
|
data = make(map[string]interface{})
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, v := range kv {
|
|
|
|
switch mvccpb.Event_EventType(v.Type) {
|
|
|
|
case mvccpb.DELETE:
|
|
|
|
data = update(e, data, (*mvccpb.KeyValue)(v.Kv), "delete", stripPrefix)
|
|
|
|
default:
|
|
|
|
data = update(e, data, (*mvccpb.KeyValue)(v.Kv), "insert", stripPrefix)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return data
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeMap(e encoder.Encoder, kv []*mvccpb.KeyValue, stripPrefix string) map[string]interface{} {
|
|
|
|
data := make(map[string]interface{})
|
|
|
|
|
|
|
|
for _, v := range kv {
|
|
|
|
data = update(e, data, v, "put", stripPrefix)
|
|
|
|
}
|
|
|
|
|
|
|
|
return data
|
|
|
|
}
|
|
|
|
|
|
|
|
func update(e encoder.Encoder, data map[string]interface{}, v *mvccpb.KeyValue, action, stripPrefix string) map[string]interface{} {
|
|
|
|
// remove prefix if non empty, and ensure leading / is removed as well
|
|
|
|
vkey := strings.TrimPrefix(strings.TrimPrefix(string(v.Key), stripPrefix), "/")
|
|
|
|
// split on prefix
|
|
|
|
haveSplit := strings.Contains(vkey, "/")
|
|
|
|
keys := strings.Split(vkey, "/")
|
|
|
|
|
|
|
|
var vals interface{}
|
|
|
|
e.Decode(v.Value, &vals)
|
|
|
|
|
|
|
|
if !haveSplit && len(keys) == 1 {
|
|
|
|
switch action {
|
|
|
|
case "delete":
|
|
|
|
data = make(map[string]interface{})
|
|
|
|
default:
|
|
|
|
v, ok := vals.(map[string]interface{})
|
|
|
|
if ok {
|
|
|
|
data = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return data
|
|
|
|
}
|
|
|
|
|
|
|
|
// set data for first iteration
|
|
|
|
kvals := data
|
|
|
|
// iterate the keys and make maps
|
|
|
|
for i, k := range keys {
|
|
|
|
kval, ok := kvals[k].(map[string]interface{})
|
|
|
|
if !ok {
|
|
|
|
// create next map
|
|
|
|
kval = make(map[string]interface{})
|
|
|
|
// set it
|
|
|
|
kvals[k] = kval
|
|
|
|
}
|
|
|
|
|
|
|
|
// last key: write vals
|
|
|
|
if l := len(keys) - 1; i == l {
|
|
|
|
switch action {
|
|
|
|
case "delete":
|
|
|
|
delete(kvals, k)
|
|
|
|
default:
|
|
|
|
kvals[k] = vals
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
// set kvals for next iterator
|
|
|
|
kvals = kval
|
|
|
|
}
|
|
|
|
|
|
|
|
return data
|
|
|
|
}
|