package etcd
import (
"context"
"fmt"
"github.com/golang/glog"
"go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/pkg/transport"
"sync"
"time"
)
type ThreadSafeEtcd struct {
client *clientv3.Client
lock sync.Mutex
certdir string
endpoints []string
}
type KvPair struct {
Key string
Value string
}
var (
dialTimeout = 5 * time.Second
requestTimeout = 10 * time.Second
instance *ThreadSafeEtcd
once sync.Once
)
func (etcd *ThreadSafeEtcd) KV_delete(key string) error {
etcd.lock.Lock()
defer etcd.lock.Unlock()
tlsInfo := transport.TLSInfo{
CertFile: fmt.Sprintf("%s%s", etcd.certdir, "/peer.crt"),
KeyFile: fmt.Sprintf("%s%s", etcd.certdir, "/peer.key"),
TrustedCAFile: fmt.Sprintf("%s%s", etcd.certdir, "/ca.crt"),
}
tlsConfig, err := tlsInfo.ClientConfig()
if err != nil {
return err
}
cli, err := clientv3.New(clientv3.Config{
Endpoints: etcd.endpoints,
DialTimeout: dialTimeout,
TLS: tlsConfig,
})
if err != nil {
return err
}
defer cli.Close() // make sure to close the client
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
_, err = cli.Delete(ctx, key)
cancel()
if err != nil {
return err
}
return nil
}
func (etcd *ThreadSafeEtcd) KV_put(kv *KvPair) error {
etcd.lock.Lock()
defer etcd.lock.Unlock()
tlsInfo := transport.TLSInfo{
CertFile: fmt.Sprintf("%s%s", etcd.certdir, "/peer.crt"),
KeyFile: fmt.Sprintf("%s%s", etcd.certdir, "/peer.key"),
TrustedCAFile: fmt.Sprintf("%s%s", etcd.certdir, "/ca.crt"),
}
tlsConfig, err := tlsInfo.ClientConfig()
if err != nil {
return err
}
cli, err := clientv3.New(clientv3.Config{
Endpoints: etcd.endpoints,
DialTimeout: dialTimeout,
TLS: tlsConfig,
})
if err != nil {
return err
}
defer cli.Close() // make sure to close the client
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
_, err = cli.Put(ctx, kv.Key, kv.Value)
cancel()
if err != nil {
return err
}
return nil
}
func (etcd *ThreadSafeEtcd) KV_get(key string) (*KvPair, error) {
etcd.lock.Lock()
defer etcd.lock.Unlock()
var kv KvPair
tlsInfo := transport.TLSInfo{
CertFile: fmt.Sprintf("%s%s", etcd.certdir, "/peer.crt"),
KeyFile: fmt.Sprintf("%s%s", etcd.certdir, "/peer.key"),
TrustedCAFile: fmt.Sprintf("%s%s", etcd.certdir, "/ca.crt"),
}
tlsConfig, err := tlsInfo.ClientConfig()
if err != nil {
return nil, err
}
cli, err := clientv3.New(clientv3.Config{
Endpoints: etcd.endpoints,
DialTimeout: dialTimeout,
TLS: tlsConfig,
})
if err != nil {
return nil, err
}
defer cli.Close() // make sure to close the client
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
resp, err := cli.Get(ctx, key)
cancel()
if err != nil {
glog.V(5).Infof("etcd KV_get, Get %s fail, err %v", key, err)
return nil, err
}
for _, ev := range resp.Kvs {
kv.Key = string(ev.Key)
kv.Value = string(ev.Value)
break
}
glog.V(5).Infof("KV_get, key: %s, value %s", kv.Key, kv.Value)
return &kv, nil
}
func (etcd *ThreadSafeEtcd) Init(endpoints []string, certdir string) (*ThreadSafeEtcd, error) {
etcd.lock.Lock()
defer etcd.lock.Unlock()
tlsInfo := transport.TLSInfo{
CertFile: fmt.Sprintf("%s%s", certdir, "/peer.crt"),
KeyFile: fmt.Sprintf("%s%s", certdir, "/peer.key"),
TrustedCAFile: fmt.Sprintf("%s%s", certdir, "/ca.crt"),
}
tlsConfig, err := tlsInfo.ClientConfig()
if err != nil {
return nil, err
}
cli, err := clientv3.New(clientv3.Config{
Endpoints: endpoints,
DialTimeout: dialTimeout,
TLS: tlsConfig,
})
if err != nil {
return nil, err
}
defer cli.Close() // make sure to close the client
etcd.certdir = certdir
etcd.endpoints = endpoints
return etcd, nil
}
func GetInstance() *ThreadSafeEtcd {
once.Do(func() {
instance = &ThreadSafeEtcd{}
})
return instance
}