ba594d3c2a177e7f7b3b1740fe472f5aa527bbd0
[icn/sdwan.git] /
1 // SPDX-License-Identifier: Apache-2.0\r
2 // Copyright (c) 2020 Intel Corporation\r
3 \r
4 package contextdb\r
5 \r
6 import (\r
7         "context"\r
8         "encoding/json"\r
9         "os"\r
10         "time"\r
11 \r
12         pkgerrors "github.com/pkg/errors"\r
13         "go.etcd.io/etcd/clientv3"\r
14 )\r
15 \r
16 // EtcdConfig Configuration values needed for Etcd Client\r
17 type EtcdConfig struct {\r
18         Endpoint string\r
19         CertFile string\r
20         KeyFile  string\r
21         CAFile   string\r
22 }\r
23 \r
24 // EtcdClient for Etcd\r
25 type EtcdClient struct {\r
26         cli      *clientv3.Client\r
27         endpoint string\r
28 }\r
29 \r
30 // Etcd For Mocking purposes\r
31 type Etcd interface {\r
32         Put(ctx context.Context, key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error)\r
33         Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error)\r
34         Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error)\r
35 }\r
36 \r
37 var getEtcd = func(e *EtcdClient) Etcd {\r
38         return e.cli\r
39 }\r
40 \r
41 // NewEtcdClient function initializes Etcd client\r
42 func NewEtcdClient(store *clientv3.Client, c EtcdConfig) (ContextDb, error) {\r
43         var endpoint string\r
44         if store == nil {\r
45                 endpoint = "http://" + c.Endpoint + ":2379"\r
46 \r
47                 etcdClient := clientv3.Config{\r
48                         Endpoints:   []string{endpoint},\r
49                         DialTimeout: 5 * time.Second,\r
50                 }\r
51                 if len(os.Getenv("CONTEXTDB_EMCO_USERNAME")) > 0 && len(os.Getenv("CONTEXTDB_EMCO_PASSWORD")) > 0 {\r
52                         etcdClient.Username = os.Getenv("CONTEXTDB_EMCO_USERNAME")\r
53                         etcdClient.Password = os.Getenv("CONTEXTDB_EMCO_PASSWORD")\r
54                 }\r
55                 var err error\r
56                 store, err = clientv3.New(etcdClient)\r
57                 if err != nil {\r
58                         return nil, pkgerrors.Errorf("Error creating etcd client: %s", err.Error())\r
59                 }\r
60         }\r
61 \r
62         return &EtcdClient{\r
63                 cli:      store,\r
64                 endpoint: endpoint,\r
65         }, nil\r
66 }\r
67 \r
68 // Put values in Etcd DB\r
69 func (e *EtcdClient) Put(key string, value interface{}) error {\r
70         cli := getEtcd(e)\r
71         if cli == nil {\r
72                 return pkgerrors.Errorf("Etcd Client not initialized")\r
73         }\r
74         if key == "" {\r
75                 return pkgerrors.Errorf("Key is null")\r
76         }\r
77         if value == nil {\r
78                 return pkgerrors.Errorf("Value is nil")\r
79         }\r
80         v, err := json.Marshal(value)\r
81         if err != nil {\r
82                 return pkgerrors.Errorf("Json Marshal error: %s", err.Error())\r
83         }\r
84         _, err = cli.Put(context.Background(), key, string(v))\r
85         if err != nil {\r
86                 return pkgerrors.Errorf("Error creating etcd entry: %s", err.Error())\r
87         }\r
88         return nil\r
89 }\r
90 \r
91 // Get values from Etcd DB and decodes from json\r
92 func (e *EtcdClient) Get(key string, value interface{}) error {\r
93         cli := getEtcd(e)\r
94         if cli == nil {\r
95                 return pkgerrors.Errorf("Etcd Client not initialized")\r
96         }\r
97         if key == "" {\r
98                 return pkgerrors.Errorf("Key is null")\r
99         }\r
100         if value == nil {\r
101                 return pkgerrors.Errorf("Value is nil")\r
102         }\r
103         getResp, err := cli.Get(context.Background(), key)\r
104         if err != nil {\r
105                 return pkgerrors.Errorf("Error getting etcd entry: %s", err.Error())\r
106         }\r
107         if getResp.Count == 0 {\r
108                 return pkgerrors.Errorf("Key doesn't exist")\r
109         }\r
110         return json.Unmarshal(getResp.Kvs[0].Value, value)\r
111 }\r
112 \r
113 // GetAllKeys values from Etcd DB\r
114 func (e *EtcdClient) GetAllKeys(key string) ([]string, error) {\r
115         cli := getEtcd(e)\r
116         if cli == nil {\r
117                 return nil, pkgerrors.Errorf("Etcd Client not initialized")\r
118         }\r
119         getResp, err := cli.Get(context.Background(), key, clientv3.WithPrefix())\r
120         if err != nil {\r
121                 return nil, pkgerrors.Errorf("Error getting etcd entry: %s", err.Error())\r
122         }\r
123         if getResp.Count == 0 {\r
124                 return nil, pkgerrors.Errorf("Key doesn't exist")\r
125         }\r
126         var keys []string\r
127         for _, ev := range getResp.Kvs {\r
128                 keys = append(keys, string(ev.Key))\r
129         }\r
130         return keys, nil\r
131 }\r
132 \r
133 // DeleteAll keys from Etcd DB\r
134 func (e *EtcdClient) DeleteAll(key string) error {\r
135         cli := getEtcd(e)\r
136         if cli == nil {\r
137                 return pkgerrors.Errorf("Etcd Client not initialized")\r
138         }\r
139         _, err := cli.Delete(context.Background(), key, clientv3.WithPrefix())\r
140         if err != nil {\r
141                 return pkgerrors.Errorf("Delete failed etcd entry: %s", err.Error())\r
142         }\r
143         return nil\r
144 }\r
145 \r
146 // Delete values from Etcd DB\r
147 func (e *EtcdClient) Delete(key string) error {\r
148         cli := getEtcd(e)\r
149         if cli == nil {\r
150                 return pkgerrors.Errorf("Etcd Client not initialized")\r
151         }\r
152         _, err := cli.Delete(context.Background(), key)\r
153         if err != nil {\r
154                 return pkgerrors.Errorf("Delete failed etcd entry: %s", err.Error())\r
155         }\r
156         return nil\r
157 }\r
158 \r
159 // HealthCheck for checking health of the etcd cluster\r
160 func (e *EtcdClient) HealthCheck() error {\r
161         return nil\r
162 }\r