-
Notifications
You must be signed in to change notification settings - Fork 29
/
zabbix.go
246 lines (204 loc) · 5.42 KB
/
zabbix.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
package zabbix
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
/**
Zabbix and Go's RPC implementations don't play with each other.. at all.
So I've re-created the wheel at bit.
*/
type JsonRPCResponse struct {
Jsonrpc string `json:"jsonrpc"`
Error ZabbixError `json:"error"`
Result interface{} `json:"result"`
Id int `json:"id"`
}
type JsonRPCRequest struct {
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params interface{} `json:"params"`
// Zabbix 2.0:
// The "user.login" method must be called without the "auth" parameter
Auth string `json:"auth,omitempty"`
Id int `json:"id"`
}
type ZabbixError struct {
Code int `json:"code"`
Message string `json:"message"`
Data string `json:"data"`
}
func (z *ZabbixError) Error() string {
return z.Data
}
type ZabbixHost map[string]interface{}
type ZabbixGraph map[string]interface{}
type ZabbixGraphItem map[string]interface{}
type ZabbixHistoryItem struct {
Clock string `json:"clock"`
Value string `json:"value"`
Itemid string `json:"itemid"`
}
type API struct {
url string
user string
passwd string
id int
auth string
Client *http.Client
}
func NewAPI(server, user, passwd string) (*API, error) {
return &API{server, user, passwd, 0, "", &http.Client{}}, nil
}
func (api *API) GetAuth() string {
return api.auth
}
/**
Each request establishes its own connection to the server. This makes it easy
to keep request/responses in order without doing any concurrency
*/
func (api *API) ZabbixRequest(method string, data interface{}) (JsonRPCResponse, error) {
// Setup our JSONRPC Request data
id := api.id
api.id = api.id + 1
jsonobj := JsonRPCRequest{"2.0", method, data, api.auth, id}
encoded, err := json.Marshal(jsonobj)
if err != nil {
return JsonRPCResponse{}, err
}
// Setup our HTTP request
request, err := http.NewRequest("POST", api.url, bytes.NewBuffer(encoded))
if err != nil {
return JsonRPCResponse{}, err
}
request.Header.Add("Content-Type", "application/json-rpc")
if api.auth != "" {
// XXX Not required in practice, check spec
//request.SetBasicAuth(api.user, api.passwd)
//request.Header.Add("Authorization", api.auth)
}
// Execute the request
response, err := api.Client.Do(request)
if err != nil {
return JsonRPCResponse{}, err
}
/**
We can't rely on response.ContentLength because it will
be set at -1 for large responses that are chunked. So
we treat each API response as streamed data.
*/
var result JsonRPCResponse
var buf bytes.Buffer
_, err = io.Copy(&buf, response.Body)
if err != nil {
return JsonRPCResponse{}, err
}
json.Unmarshal(buf.Bytes(), &result)
response.Body.Close()
return result, nil
}
func (api *API) Login() (bool, error) {
params := make(map[string]string, 0)
params["user"] = api.user
params["password"] = api.passwd
response, err := api.ZabbixRequest("user.login", params)
if err != nil {
fmt.Printf("Error: %s\n", err)
return false, err
}
if response.Error.Code != 0 {
return false, &response.Error
}
api.auth = response.Result.(string)
return true, nil
}
func (api *API) Logout() (bool, error) {
emptyparams := make(map[string]string, 0)
response, err := api.ZabbixRequest("user.logout", emptyparams)
if err != nil {
return false, err
}
if response.Error.Code != 0 {
return false, &response.Error
}
return true, nil
}
func (api *API) Version() (string, error) {
response, err := api.ZabbixRequest("APIInfo.version", make(map[string]string, 0))
if err != nil {
return "", err
}
if response.Error.Code != 0 {
return "", &response.Error
}
return response.Result.(string), nil
}
/**
Interface to the user.* calls
*/
func (api *API) User(method string, data interface{}) ([]interface{}, error) {
response, err := api.ZabbixRequest("user."+method, data)
if err != nil {
return nil, err
}
if response.Error.Code != 0 {
return nil, &response.Error
}
return response.Result.([]interface{}), nil
}
/**
Interface to the host.* calls
*/
func (api *API) Host(method string, data interface{}) ([]ZabbixHost, error) {
response, err := api.ZabbixRequest("host."+method, data)
if err != nil {
return nil, err
}
if response.Error.Code != 0 {
return nil, &response.Error
}
// XXX uhg... there has got to be a better way to convert the response
// to the type I want to return
res, err := json.Marshal(response.Result)
var ret []ZabbixHost
err = json.Unmarshal(res, &ret)
return ret, nil
}
/**
Interface to the graph.* calls
*/
func (api *API) Graph(method string, data interface{}) ([]ZabbixGraph, error) {
response, err := api.ZabbixRequest("graph."+method, data)
if err != nil {
return nil, err
}
if response.Error.Code != 0 {
return nil, &response.Error
}
// XXX uhg... there has got to be a better way to convert the response
// to the type I want to return
res, err := json.Marshal(response.Result)
var ret []ZabbixGraph
err = json.Unmarshal(res, &ret)
return ret, nil
}
/**
Interface to the history.* calls
*/
func (api *API) History(method string, data interface{}) ([]ZabbixHistoryItem, error) {
response, err := api.ZabbixRequest("history."+method, data)
if err != nil {
return nil, err
}
if response.Error.Code != 0 {
return nil, &response.Error
}
// XXX uhg... there has got to be a better way to convert the response
// to the type I want to return
res, err := json.Marshal(response.Result)
var ret []ZabbixHistoryItem
err = json.Unmarshal(res, &ret)
return ret, nil
}