Add Makefile
[vaultmon/.git] / etcd.go
CommitLineData
9a72579f
SB
1package main
2
3import (
4 "encoding/json"
5 "fmt"
6 "io/ioutil"
7 "strconv"
8
9 log "github.com/sirupsen/logrus"
10)
11
12type Etcd struct {
13 URL string
14 ConnectionStatus string
15 ClusterStatus string
16}
17
18type EtcdHealthResult struct {
19 Health string `json:"health"`
20}
21
22type EtcdMembersEntry struct {
23 ClientURLs []string `json:"clientURLs"`
24}
25
26type EtcdMembersResult struct {
27 Members []EtcdMembersEntry `json:"members"`
28}
29
30func (e *Etcd) CheckHealth() (bool, error) {
31 healthURL := e.URL + "/health"
32 cnx := NewConnection(healthURL)
33 log.Debugf("Etcd connection on %s", healthURL)
34 resp, err := cnx.Get()
35 if err != nil {
36 return false, err
37 }
38 defer resp.Body.Close()
39
40 log.Debugf("Etcd CheckHealth response: %s", resp.Status)
41
42 buf, err := ioutil.ReadAll(resp.Body)
43 if err != nil {
44 return false, err
45 }
46
47 var result EtcdHealthResult
48
49 err = json.Unmarshal(buf, &result)
50 if err != nil {
51 return false, err
52 }
53
54 log.Debugf("Etcd CheckHealth JSON result: %+v", result)
55
56 boolResult, err := strconv.ParseBool(result.Health)
57 if err != nil {
58 return false, err
59 }
60
61 return boolResult == true, nil
62}
63
64func (e *Etcd) CheckCluster() (bool, error) {
65 clusterURL := e.URL + "/v2/members"
66 cnx := NewConnection(clusterURL)
67 log.Debugf("Etcd connection on %s", clusterURL)
68 resp, err := cnx.Get()
69 if err != nil {
70 return false, err
71 }
72 defer resp.Body.Close()
73
74 log.Debugf("Etcd CheckCluster response: %s", resp.Status)
75
76 buf, err := ioutil.ReadAll(resp.Body)
77 if err != nil {
78 return false, err
79 }
80
81 var result EtcdMembersResult
82
83 err = json.Unmarshal(buf, &result)
84 if err != nil {
85 return false, err
86 }
87
88 alives := make([]bool, 0, len(result.Members))
89 for _, member := range result.Members {
90 for _, client := range member.ClientURLs {
91 alives = append(alives, getMemberHealth(client))
92 }
93 }
94
95 log.Debugf("Etcd CheckCluster JSON result: %+v", result)
96
97 log.Debugf("Etcd Cluster Members alive result: %+v", alives)
98
99 return ensureMembersAlive(alives), nil
100}
101
102func getMemberHealth(memberUrl string) bool {
103 url := memberUrl + "/health"
104 cnx := NewConnection(url)
105 log.Debugf("Etcd Member connection on %s", url)
106 resp, err := cnx.Get()
107 if err != nil {
108 log.Fatalf("Error Get: %s", err)
109 }
110 defer resp.Body.Close()
111
112 buf, err := ioutil.ReadAll(resp.Body)
113 if err != nil {
114 log.Fatalf("Error ReadAll: %s", err)
115 }
116
117 var result EtcdHealthResult
118
119 err = json.Unmarshal(buf, &result)
120 if err != nil {
121 log.Fatalf("Error Unmarshal: %s", err)
122 }
123
124 boolResult, err := strconv.ParseBool(result.Health)
125 if err != nil {
126 log.Fatalf("Error ParseBool: %s", err)
127 }
128
129 return boolResult
130}
131
132func ensureMembersAlive(alives []bool) bool {
133 for _, alive := range alives {
134 if alive != true {
135 return false
136 }
137 }
138
139 return true
140}
141
142func (e *Etcd) Test() (bool, string) {
143 // test health
144 result, err := e.CheckHealth()
145 if err != nil {
146 log.Errorf("CheckHealth error: %s", err)
147 e.ConnectionStatus = "KO"
148 }
149 e.ConnectionStatus = "OK"
150 log.Debugf("Etcd CheckHealth result: %t", result)
151
152 // test cluster
153 result, err = e.CheckCluster()
154 if err != nil {
155 log.Errorf("CheckCluster error: %s", err)
156 e.ClusterStatus = "KO"
157 }
158 e.ClusterStatus = "OK"
159 log.Debugf("Etcd CheckCluster result: %t", result)
160
161 return result, fmt.Sprintf("> %s `%s` status *%s*. Cluster status *%s*.", e.Name(), e.URL, e.ConnectionStatus, e.ClusterStatus)
162}
163
164func (e *Etcd) Name() string {
165 return "Etcd"
166}
167
168func NewEtcd(url string) CheckProvider {
169 return &Etcd{URL: url}
170}