-
Notifications
You must be signed in to change notification settings - Fork 0
/
nodeping.go
140 lines (121 loc) · 3.25 KB
/
nodeping.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"encoding/json"
"fmt"
"net/http"
"github.com/prometheus/common/log"
)
// NodePing is nodeping.com API endpoint access config
type NodePing struct {
APIURL string
Token string
}
// Check describe nodeping response about it
type Check struct {
ID string `json:"_id,omitempty"`
Label string `json:"label"`
Type string `json:"type"`
Parameters struct {
Target string `json:"target"`
Follow bool `json:"follow,omitempty"`
Threshold int `json:"threshold"`
Sens int `json:"sens"`
} `json:"parameters"`
State int `json:"state"`
}
// CheckStats describe nodeping response about it
type CheckStats struct {
Type string `json:"t"`
Target string `json:"tg"`
Result string `json:"sc"`
Message string `json:"m"`
Success bool `json:"su"`
Duration int `json:"rt"`
}
// NodePingError custom error
type NodePingError struct {
e string
statusCode int
}
func (npe NodePingError) Error() string {
return fmt.Sprintf("%s, got status code %d", npe.e, npe.statusCode)
}
func (np NodePing) request(m string) (*http.Response, error) {
reqURL := fmt.Sprintf("%s/%s", np.APIURL, m)
client := &http.Client{}
req, err := http.NewRequest("GET", reqURL, nil)
if err != nil {
log.Errorf("Cannot create new request: %v", err)
return nil, err
}
req.SetBasicAuth(np.Token, "")
r, err := client.Do(req)
if err != nil {
log.Errorf("Cannot make new request to %s: %v", reqURL, err)
return nil, err
}
switch r.StatusCode {
case http.StatusOK:
return r, nil
case http.StatusForbidden:
return nil, fmt.Errorf("Can't access with provided token")
default:
return nil, NodePingError{
e: fmt.Sprintf("Error occurred on %s", reqURL),
statusCode: r.StatusCode,
}
}
}
// GetAllChecks return list of all available checks
func (np NodePing) GetAllChecks() (map[string]Check, error) {
r, err := np.request("checks")
if err != nil {
return nil, err
}
defer r.Body.Close()
checks := map[string]Check{}
err = json.NewDecoder(r.Body).Decode(&checks)
if err != nil {
log.Errorf("Can't decode received body of all checks: %v", err)
return nil, fmt.Errorf("Can't decode received body of all checks: %v", err)
}
return checks, nil
}
// GetCheckStats return info and status about check
func (np NodePing) GetCheckStats(checkID string) (CheckStats, error) {
r, err := np.request(fmt.Sprintf("results/%s?limit=1", checkID))
if err != nil {
return CheckStats{}, err
}
defer r.Body.Close()
cs := []CheckStats{}
err = json.NewDecoder(r.Body).Decode(&cs)
if err != nil {
log.Errorf("Can't decode received body of check stats: %v", err)
return CheckStats{}, fmt.Errorf("Can't decode received body of check stats: %v", err)
}
return cs[0], nil
}
// CheckAccess simple availability check
func (np NodePing) CheckAccess() error {
_, err := np.request("info/probe")
if err != nil {
return err
}
return nil
}
// NewNodePing create new NodePing structure
func NewNodePing(apiURL, token string) (NodePing, error) {
if token == "" {
return NodePing{}, fmt.Errorf("Token should be specified")
}
np := NodePing{
APIURL: apiURL,
Token: token,
}
err := np.CheckAccess()
if err != nil {
return NodePing{}, fmt.Errorf("Can't proceed initial check: %v", err)
}
return np, nil
}