forked from AlekSi/zabbix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
base.go
148 lines (125 loc) · 3.52 KB
/
base.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
package zabbix
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"sync/atomic"
)
type (
Params map[string]interface{}
)
type request struct {
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params interface{} `json:"params"`
Auth string `json:"auth,omitempty"`
Id int32 `json:"id"`
}
type Response struct {
Jsonrpc string `json:"jsonrpc"`
Error *Error `json:"error"`
Result interface{} `json:"result"`
Id int32 `json:"id"`
}
type Error struct {
Code int `json:"code"`
Message string `json:"message"`
Data string `json:"data"`
}
func (e *Error) Error() string {
return fmt.Sprintf("%d (%s): %s", e.Code, e.Message, e.Data)
}
type ExpectedOneResult int
func (e *ExpectedOneResult) Error() string {
return fmt.Sprintf("Expected exactly one result, got %d.", *e)
}
type ExpectedMore struct {
Expected int
Got int
}
func (e *ExpectedMore) Error() string {
return fmt.Sprintf("Expected %d, got %d.", e.Expected, e.Got)
}
type API struct {
Auth string // auth token, filled by Login()
Logger *log.Logger // request/response logger, nil by default
url string
c http.Client
id int32
}
// Creates new API access object.
// Typical URL is http://host/api_jsonrpc.php or http://host/zabbix/api_jsonrpc.php.
// It also may contain HTTP basic auth username and password like
// http://username:password@host/api_jsonrpc.php.
func NewAPI(url string) (api *API) {
return &API{url: url, c: http.Client{}}
}
func (api *API) printf(format string, v ...interface{}) {
if api.Logger != nil {
api.Logger.Printf(format, v...)
}
}
func (api *API) callBytes(method string, params interface{}) (b []byte, err error) {
id := atomic.AddInt32(&api.id, 1)
jsonobj := request{"2.0", method, params, api.Auth, id}
b, err = json.Marshal(jsonobj)
if err != nil {
return
}
api.printf("Request : %s", b)
req, err := http.NewRequest("POST", api.url, bytes.NewReader(b))
if err != nil {
return
}
req.ContentLength = int64(len(b))
req.Header.Add("Content-Type", "application/json-rpc")
req.Header.Add("User-Agent", "github.com/AlekSi/zabbix")
res, err := api.c.Do(req)
if err != nil {
return
}
defer res.Body.Close()
b, err = ioutil.ReadAll(res.Body)
api.printf("Response: %s", b)
return
}
// Calls specified API method. Uses api.Auth if not empty.
// err is something network or marshaling related. Caller should inspect response.Error to get API error.
func (api *API) Call(method string, params interface{}) (response Response, err error) {
b, err := api.callBytes(method, params)
if err == nil {
err = json.Unmarshal(b, &response)
}
return
}
// Uses Call() and then sets err to response.Error if former is nil and latter is not.
func (api *API) CallWithError(method string, params interface{}) (response Response, err error) {
response, err = api.Call(method, params)
if err == nil && response.Error != nil {
err = response.Error
}
return
}
// Calls "user.authenticate" API method and fills api.Auth field.
func (api *API) Login(user, password string) (auth string, err error) {
params := map[string]string{"user": user, "password": password}
response, err := api.CallWithError("user.authenticate", params)
if err != nil {
return
}
auth = response.Result.(string)
api.Auth = auth
return
}
// Calls "APIInfo.version" API method
func (api *API) Version() (v string, err error) {
response, err := api.CallWithError("APIInfo.version", Params{})
if err != nil {
return
}
v = response.Result.(string)
return
}