zabbix_manager 5.1.5 → 5.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -9
- data/LICENSE +1 -1
- data/README.md +202 -8
- data/lib/zabbix_manager/basic/basic_alias.rb +25 -3
- data/lib/zabbix_manager/basic/basic_func.rb +32 -61
- data/lib/zabbix_manager/basic/basic_init.rb +28 -13
- data/lib/zabbix_manager/basic/basic_logic.rb +172 -128
- data/lib/zabbix_manager/classes/actions.rb +21 -11
- data/lib/zabbix_manager/classes/applications.rb +12 -17
- data/lib/zabbix_manager/classes/configurations.rb +20 -5
- data/lib/zabbix_manager/classes/drules.rb +11 -23
- data/lib/zabbix_manager/classes/errors.rb +16 -28
- data/lib/zabbix_manager/classes/events.rb +6 -2
- data/lib/zabbix_manager/classes/graphs.rb +42 -35
- data/lib/zabbix_manager/classes/hostgroups.rb +53 -3
- data/lib/zabbix_manager/classes/hostinterfaces.rb +172 -12
- data/lib/zabbix_manager/classes/hosts.rb +191 -81
- data/lib/zabbix_manager/classes/httptests.rb +18 -20
- data/lib/zabbix_manager/classes/items.rb +193 -63
- data/lib/zabbix_manager/classes/maintenance.rb +6 -2
- data/lib/zabbix_manager/classes/mediatypes.rb +7 -63
- data/lib/zabbix_manager/classes/problems.rb +75 -57
- data/lib/zabbix_manager/classes/proxies.rb +48 -7
- data/lib/zabbix_manager/classes/roles.rb +47 -36
- data/lib/zabbix_manager/classes/screens.rb +45 -14
- data/lib/zabbix_manager/classes/scripts.rb +17 -7
- data/lib/zabbix_manager/classes/server.rb +7 -1
- data/lib/zabbix_manager/classes/templates.rb +59 -21
- data/lib/zabbix_manager/classes/triggers.rb +253 -66
- data/lib/zabbix_manager/classes/usergroups.rb +28 -6
- data/lib/zabbix_manager/classes/usermacros.rb +119 -33
- data/lib/zabbix_manager/classes/users.rb +39 -7
- data/lib/zabbix_manager/classes/valuemaps.rb +13 -19
- data/lib/zabbix_manager/client.rb +308 -133
- data/lib/zabbix_manager/http_transport.rb +192 -0
- data/lib/zabbix_manager/log_sanitizer.rb +68 -0
- data/lib/zabbix_manager/monitoring.rb +691 -0
- data/lib/zabbix_manager/version.rb +1 -1
- data/lib/zabbix_manager.rb +118 -40
- data/zabbix_manager.gemspec +21 -8
- metadata +208 -22
- data/lib/zabbix_manager/classes/unusable.rb +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 37c70888e6fd6b0e27a4945f2672d460243584724c67eed4eadc4d69b88d6ad7
|
|
4
|
+
data.tar.gz: 6975d3b02322a81fe8923503e58b91f1888de4ec324f30846552305931fe6a59
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 875b98496cffef36b128f8038f007c8d9a0a9bdb6635c14df0380545ef495903970c73ffca1cb26105a3e382d14e88517308edd81b11b57d5be64e30e0b6f486
|
|
7
|
+
data.tar.gz: 9d2d60aa041e3e993b4c8aaf9c900570824a997537dca1f0fc34a88dbc7f2dd7286d86adc2ecda40e04b2ac0393fa9279cbbb2a29b65c92dab1a92463984d833
|
data/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
* Add Zabbix 7.x API-token authentication through the Bearer header while retaining the legacy 4.x-6.x authentication body.
|
|
6
|
+
* Reuse a thread-safe persistent `Net::HTTP` session and add explicit `close` lifecycle handling.
|
|
7
|
+
* Add injectable, credential-filtered request logging and stable JSON-RPC error handling.
|
|
8
|
+
* Add idempotent device/interface monitoring workflows with bandwidth, error, and packet-loss hysteresis triggers.
|
|
9
|
+
* Remove experimental `mojo_*` host/trigger methods and unsafe hard-coded SNMP defaults.
|
|
10
|
+
* Remove environment-specific item lookup helpers with hard-coded host data; use `monitoring.reconcile_line` instead.
|
|
11
|
+
* Remove copied Role user-group methods and the hard-coded historical problem-closing workflow.
|
|
12
|
+
* Remove dormant live-Zabbix scripts that were not part of the RSpec test pattern and mutated remote systems by default.
|
|
13
|
+
* Use ActiveSupport for deep key normalization and blank-value semantics.
|
|
14
|
+
* Batch line reconciliation to reuse host/item discovery and reject ambiguous or dimensionally invalid traffic items.
|
|
15
|
+
* Simplify template reference lookup and fix partial final-row sizing in screen creation.
|
|
16
|
+
* Replace the inherited Rails RuboCop profile with project-scoped lint, security, performance, packaging, layout, and safe style gates.
|
|
17
|
+
* Keep HTTPS verification disabled by default for compatibility, with an opt-in `verify_ssl: true` mode.
|
|
18
|
+
* Remove the unused `http` runtime dependency and support the `logger` default gem on modern Ruby.
|
|
19
|
+
* Add two-phase batch reconciliation for devices and lines with full preflight validation, sanitized per-entry errors, and summaries.
|
|
20
|
+
* Add focused host-interface CRUD, item batch/status/delete, trigger status/delete, and current trigger dependency append/replace APIs.
|
|
21
|
+
* Replace legacy exception names with `Invalid`, `Conflict`, `ApiError`, and `TransportError`.
|
|
22
|
+
* Add CI jobs for tests, formatting, Gem packaging, and trusted tag-based RubyGems publishing.
|
|
23
|
+
* Move project metadata to `https://github.com/gatework/zabbix_manager/tree/master`.
|
|
24
|
+
* Scope destructive and dependency operations by host, serialize host/interface reconciliation, and expose uncertain writes as `ResultUnknown`.
|
|
25
|
+
* Validate current Zabbix item/interface create contracts before writes and publish the exact smoke-tested Gem artifact.
|
|
26
|
+
|
|
27
|
+
### 5.0.7
|
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[gem]: https://rubygems.org/gems/zabbix_manager
|
|
6
6
|
|
|
7
|
-
Most
|
|
7
|
+
Most codes borrowed from zabbixapi, but fit for my everyday works well!
|
|
8
8
|
Simple and lightweight ruby module for working with [Zabbix][Zabbix] via the [Zabbix API][Zabbix API]
|
|
9
9
|
|
|
10
10
|
## Installation
|
|
@@ -13,7 +13,7 @@ Simple and lightweight ruby module for working with [Zabbix][Zabbix] via the [Za
|
|
|
13
13
|
gem install zabbix_manager
|
|
14
14
|
|
|
15
15
|
# specific version
|
|
16
|
-
gem install zabbix_manager -v
|
|
16
|
+
gem install zabbix_manager -v 4.2.0
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Documentation
|
|
@@ -23,15 +23,204 @@ gem install zabbix_manager -v 5.1.1
|
|
|
23
23
|
|
|
24
24
|
## Examples
|
|
25
25
|
|
|
26
|
+
### API token (Zabbix 7.x)
|
|
27
|
+
|
|
28
|
+
The token can come from an application settings page or another secret store. Pass it directly to the client; do not copy it into request parameters or logs.
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
require "zabbix_manager"
|
|
32
|
+
|
|
33
|
+
zabbix = ZabbixManager.connect(
|
|
34
|
+
url: "https://zabbix.example.com/api_jsonrpc.php",
|
|
35
|
+
api_token: ENV.fetch("ZABBIX_API_TOKEN")
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
hosts = zabbix.hosts.get_raw(output: %w[hostid host])
|
|
39
|
+
zabbix.close
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Zabbix 7.x requests use the `Authorization: Bearer` header. Earlier supported servers use the JSON-RPC `auth` property. Supplying `api_token` skips `user.login`, and `logout` only closes the local connection because an API token is not a Zabbix user session. API tokens are rejected on plain HTTP unless `allow_insecure_http: true` is explicitly set.
|
|
43
|
+
|
|
44
|
+
### Username and password
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
zabbix = ZabbixManager.connect(
|
|
48
|
+
url: "https://zabbix.example.com/api_jsonrpc.php",
|
|
49
|
+
username: ENV.fetch("ZABBIX_USERNAME"),
|
|
50
|
+
password: ENV.fetch("ZABBIX_PASSWORD")
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
begin
|
|
54
|
+
zabbix.query(method: "host.get", params: { output: %w[hostid host] })
|
|
55
|
+
ensure
|
|
56
|
+
zabbix.logout
|
|
57
|
+
end
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
A client keeps one persistent `Net::HTTP` session and serializes access to it, so repeated API calls reuse the same TCP/TLS connection. Use one client per process or worker when parallel request throughput matters; a client deliberately permits only one in-flight request. Call `close` when the client is no longer needed. A failed HTTP request closes the connection; the next request establishes a fresh session without automatically replaying the failed JSON-RPC mutation.
|
|
61
|
+
|
|
62
|
+
### Logging and HTTPS
|
|
63
|
+
|
|
64
|
+
Pass any Ruby Logger-compatible object to receive connection, request completion, duration, and failure events:
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
zabbix = ZabbixManager.connect(
|
|
68
|
+
url: "https://zabbix.example.com/api_jsonrpc.php",
|
|
69
|
+
api_token: ENV.fetch("ZABBIX_API_TOKEN"),
|
|
70
|
+
logger: Rails.logger
|
|
71
|
+
)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Passwords, API tokens, authorization values, cookies, and session IDs are filtered. Request parameters and response bodies are not logged; debug events contain only operation metadata.
|
|
75
|
+
|
|
76
|
+
HTTPS certificate verification is disabled by default as required by this project. Set `verify_ssl: true` (and optionally `ca_file:`) to enable peer verification.
|
|
77
|
+
|
|
78
|
+
Zabbix 7 API-token requests need the `Authorization` header, so they cannot share that header with HTTP Basic authentication. The client rejects that combination instead of silently overwriting either credential.
|
|
79
|
+
|
|
80
|
+
Timeouts can be set together with `timeout:` or independently with `open_timeout:`, `read_timeout:`, and `write_timeout:`. `keep_alive_timeout:` controls persistent connection reuse.
|
|
81
|
+
|
|
82
|
+
### Device and interface monitoring
|
|
83
|
+
|
|
84
|
+
`monitoring` provides idempotent workflows for frequent device and line updates. Item identity is the stable pair `hostid + key_`; managed triggers use a dedicated `zabbix_manager_id` tag. Missing remote objects are created and existing ones are updated. Omitted objects are never deleted.
|
|
85
|
+
|
|
86
|
+
For a line inventory that already has interface traffic items discovered by Zabbix, use `reconcile_line`. It accepts the field names from the historical `add_line_monitors.rb` importer, locates the host and the unique inbound/outbound items, then creates or updates one combined trigger. Use a stable, non-secret `line_id` so interface renames update the same trigger.
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
zabbix.monitoring.reconcile_line(
|
|
90
|
+
line_id: "line-42",
|
|
91
|
+
description: "Example upstream circuit",
|
|
92
|
+
capacity: 200, # Mbps
|
|
93
|
+
device1: "edge-switch-01",
|
|
94
|
+
ipaddr1: "192.0.2.10",
|
|
95
|
+
iface1: "Ten-GigabitEthernet1/0/49",
|
|
96
|
+
isp: "Example ISP",
|
|
97
|
+
high_water: 0.90,
|
|
98
|
+
recovery_water: 0.80,
|
|
99
|
+
problem_window: "5m",
|
|
100
|
+
recovery_window: "15m",
|
|
101
|
+
severity: 4
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The lookup accepts full and abbreviated interface names such as `Ten-GigabitEthernet1/0/49` and `Te1/0/49`. It refuses zero or multiple direction matches instead of selecting an item by response order. Existing triggers from the importer can be adopted when their description and `category=line_bandwidth` tag match.
|
|
106
|
+
|
|
107
|
+
Use `reconcile_lines(lines)` for imports. It reuses host and item discovery results within the batch, avoiding a full `item.get` scan for every line.
|
|
108
|
+
|
|
109
|
+
For a device-and-line batch, use `reconcile_network`. The whole input is structurally validated before the first device write. Devices are reconciled first, then lines, and the return value contains per-entry results plus a summary. Template linking and low-level discovery are asynchronous in Zabbix: if a new device's traffic items are not available yet, its line result is an error and the same batch can be safely rerun later.
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
result = zabbix.monitoring.reconcile_network(
|
|
113
|
+
devices: [
|
|
114
|
+
{
|
|
115
|
+
host: "edge-router-01",
|
|
116
|
+
name: "Example edge router",
|
|
117
|
+
groups: [{ groupid: 20 }],
|
|
118
|
+
interfaces: [{
|
|
119
|
+
type: 2, main: 1, useip: 1, ip: "192.0.2.10", dns: "", port: "161",
|
|
120
|
+
details: { version: 2, community: ENV.fetch("SNMP_COMMUNITY") }
|
|
121
|
+
}]
|
|
122
|
+
}
|
|
123
|
+
],
|
|
124
|
+
lines: [
|
|
125
|
+
{
|
|
126
|
+
line_id: "line-42", device: "edge-router-01",
|
|
127
|
+
interface_name: "Ten-GigabitEthernet1/0/49", capacity_mbps: 200,
|
|
128
|
+
high_water: 0.90, recovery_water: 0.80
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
result.fetch(:summary)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
hostid = zabbix.monitoring.reconcile_device(
|
|
138
|
+
host: "router-01",
|
|
139
|
+
name: "Core router 01",
|
|
140
|
+
groups: [{ groupid: 20 }],
|
|
141
|
+
interfaces: [{
|
|
142
|
+
type: 2,
|
|
143
|
+
main: 1,
|
|
144
|
+
useip: 1,
|
|
145
|
+
ip: "192.0.2.1",
|
|
146
|
+
dns: "",
|
|
147
|
+
port: "161",
|
|
148
|
+
details: { version: 2, community: ENV.fetch("SNMP_COMMUNITY") }
|
|
149
|
+
}]
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
zabbix.monitoring.reconcile_interface(
|
|
153
|
+
host: { hostid: hostid, host: "router-01" },
|
|
154
|
+
interface: { name: "GigabitEthernet1/0/1", interfaceid: 12 },
|
|
155
|
+
items: {
|
|
156
|
+
inbound_bps: {
|
|
157
|
+
key_: "if.hc.in.bps[1]", name: "WAN inbound", type: 20, value_type: 0,
|
|
158
|
+
snmp_oid: "get[1.3.6.1.2.1.31.1.1.1.6.1]", delay: "1m", units: "bps",
|
|
159
|
+
preprocessing: [
|
|
160
|
+
{ type: 10, params: "", error_handler: 0, error_handler_params: "" },
|
|
161
|
+
{ type: 1, params: "8", error_handler: 0, error_handler_params: "" }
|
|
162
|
+
]
|
|
163
|
+
},
|
|
164
|
+
outbound_bps: {
|
|
165
|
+
key_: "if.hc.out.bps[1]", name: "WAN outbound", type: 20, value_type: 0,
|
|
166
|
+
snmp_oid: "get[1.3.6.1.2.1.31.1.1.1.10.1]", delay: "1m", units: "bps",
|
|
167
|
+
preprocessing: [
|
|
168
|
+
{ type: 10, params: "", error_handler: 0, error_handler_params: "" },
|
|
169
|
+
{ type: 1, params: "8", error_handler: 0, error_handler_params: "" }
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
in_errors: {
|
|
173
|
+
key_: "if.in.errors.rate[1]", name: "WAN input errors", type: 20, value_type: 0,
|
|
174
|
+
snmp_oid: "get[1.3.6.1.2.1.2.2.1.14.1]", delay: "1m",
|
|
175
|
+
preprocessing: [{ type: 10, params: "", error_handler: 0, error_handler_params: "" }]
|
|
176
|
+
},
|
|
177
|
+
out_errors: {
|
|
178
|
+
key_: "if.out.errors.rate[1]", name: "WAN output errors", type: 20, value_type: 0,
|
|
179
|
+
snmp_oid: "get[1.3.6.1.2.1.2.2.1.20.1]", delay: "1m",
|
|
180
|
+
preprocessing: [{ type: 10, params: "", error_handler: 0, error_handler_params: "" }]
|
|
181
|
+
},
|
|
182
|
+
packet_loss: {
|
|
183
|
+
key_: "icmppingloss[198.51.100.1]", name: "WAN packet loss",
|
|
184
|
+
type: 3, value_type: 0, delay: "1m", units: "%"
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
thresholds: {
|
|
188
|
+
bandwidth: { capacity_bps: 1_000_000_000, high_percent: 80, recovery_percent: 70 },
|
|
189
|
+
errors: { high: 100, recovery: 20, function: "max", window: "5m" },
|
|
190
|
+
packet_loss: { high: 5, recovery: 2 }
|
|
191
|
+
}
|
|
192
|
+
)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The library does not guess that SNMP discard/error counters equal packet-loss percentage. Supply an actual packet-loss item key (for example an ICMP loss item) and its item definition. Raw HC-octet traffic items must expose `bps` units and include change-per-second plus multiplier-8 preprocessing; otherwise line reconciliation refuses to build a dimensionally incorrect trigger. Thresholds use separate high and recovery values to avoid alert flapping.
|
|
196
|
+
|
|
197
|
+
Reconciliation is a sequence of remote API calls, not a transaction. Single-object methods raise immediately; batch methods return a sanitized error for each failed entry unless `fail_fast: true` is passed. A retry safely converges already-created items by stable keys. If a trigger create loses its response and cannot be confirmed by readback, `ResultUnknown` is raised and must not be automatically retried. The readback schedule can be set with `uncertain_write_delays:` (up to 60 seconds total). The trigger upsert is serialized within one client process. For multiple workers, inject a callable `upsert_lock` adapter that runs the block under an application-level distributed lock.
|
|
198
|
+
|
|
199
|
+
```ruby
|
|
200
|
+
ZabbixManager.connect(
|
|
201
|
+
url: "https://zabbix.example.com/api_jsonrpc.php",
|
|
202
|
+
api_token: ENV.fetch("ZABBIX_API_TOKEN"),
|
|
203
|
+
upsert_lock: ->(key, &work) { MonitoringLock.with(key, &work) }
|
|
204
|
+
)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Invalid caller input raises `ZabbixManager::Invalid`, ambiguous remote ownership raises `ZabbixManager::Conflict`, Zabbix JSON-RPC failures raise `ZabbixManager::ApiError`, HTTP/network failures raise `ZabbixManager::TransportError`, and uncertain remote writes raise `ZabbixManager::ResultUnknown`. Destructive/status/dependency methods require `hostid:` and verify ownership before writing. Dependencies default to the same host; cross-host dependencies require `allow_cross_host_dependencies: true`. Do not pass untrusted page parameters directly to raw `query` calls.
|
|
208
|
+
|
|
209
|
+
### High-frequency API modules
|
|
210
|
+
|
|
211
|
+
The focused modules expose explicit current operations instead of compatibility aliases:
|
|
212
|
+
|
|
213
|
+
* `hosts.reconcile`, `hosts.find_by_id`, `hosts.find_by_candidates`, `hosts.set_status`
|
|
214
|
+
* `hostinterfaces.for_host`, `hostinterfaces.reconcile_for_host`, `hostinterfaces.delete_many`
|
|
215
|
+
* `items.for_host`, `items.upsert_by_key`, `items.upsert_many`, `items.set_status`, `items.delete_many`
|
|
216
|
+
* `triggers.for_host`, `triggers.upsert_for_host`, `triggers.add_dependencies`, `triggers.replace_dependencies`, `triggers.set_status`, `triggers.delete_many`
|
|
217
|
+
|
|
26
218
|
|
|
27
219
|
## Supported Ruby Versions
|
|
28
220
|
This library aims to support and is [tested against][github-ci] the following Ruby
|
|
29
221
|
versions:
|
|
30
222
|
|
|
31
|
-
* Ruby 2.
|
|
32
|
-
* Ruby 2.6
|
|
33
|
-
* Ruby 2.7
|
|
34
|
-
* JRuby 9.2.10.0
|
|
223
|
+
* Ruby 2.7 and newer
|
|
35
224
|
|
|
36
225
|
If something doesn't work on one of these versions, it's a bug.
|
|
37
226
|
|
|
@@ -49,8 +238,9 @@ dropped.
|
|
|
49
238
|
## Dependencies
|
|
50
239
|
|
|
51
240
|
* net/http
|
|
241
|
+
* active_support
|
|
52
242
|
* json
|
|
53
|
-
*
|
|
243
|
+
* logger
|
|
54
244
|
|
|
55
245
|
## Contributing
|
|
56
246
|
|
|
@@ -60,10 +250,14 @@ dropped.
|
|
|
60
250
|
* Commit, do not mess with rakefile, version.
|
|
61
251
|
* Make a pull request.
|
|
62
252
|
|
|
253
|
+
## CI and release
|
|
254
|
+
|
|
255
|
+
Pull requests and pushes to `master` run RSpec, documentation coverage, RuboCop, whitespace checks, and a built-Gem install smoke test. A `v<gem-version>` tag repeats the project gate, validates the tag/version, builds and installs a release candidate, then publishes that exact file through RubyGems Trusted Publishing. Configure the RubyGems trusted publisher for repository `gatework/zabbix_manager`, workflow `release.yml`, and environment `release` before pushing a release tag.
|
|
256
|
+
|
|
63
257
|
## Zabbix documentation
|
|
64
258
|
|
|
65
259
|
* [Zabbix Project Homepage][Zabbix]
|
|
66
260
|
* [Zabbix API docs][Zabbix API]
|
|
67
261
|
|
|
68
262
|
[Zabbix]: https://www.zabbix.com
|
|
69
|
-
[Zabbix API]: https://www.zabbix.com/documentation/
|
|
263
|
+
[Zabbix API]: https://www.zabbix.com/documentation/current/en/manual/api
|
|
@@ -2,19 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
class ZabbixManager
|
|
4
4
|
class Basic
|
|
5
|
-
#
|
|
5
|
+
# 按标识字段从 Zabbix API 获取对象完整数据。
|
|
6
|
+
#
|
|
7
|
+
# @param data [Hash] 包含对象标识字段及其值
|
|
8
|
+
# @raise [ApiError] Zabbix API 调用失败时抛出
|
|
9
|
+
# @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
|
|
10
|
+
# @return [Hash] 对象完整数据
|
|
6
11
|
def get(data)
|
|
7
12
|
get_full_data(data)
|
|
8
13
|
end
|
|
9
14
|
|
|
10
|
-
#
|
|
15
|
+
# 通过 Zabbix API 创建对象。
|
|
16
|
+
#
|
|
17
|
+
# @param data [Hash] 待创建的对象属性
|
|
18
|
+
# @raise [ApiError] Zabbix API 调用失败时抛出
|
|
19
|
+
# @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
|
|
20
|
+
# @return [Integer] 创建单个对象时返回对象 ID
|
|
21
|
+
# @return [Boolean] 创建多个对象时返回操作结果
|
|
11
22
|
def add(data)
|
|
12
23
|
create(data)
|
|
13
24
|
end
|
|
14
25
|
|
|
15
|
-
#
|
|
26
|
+
# 通过 Zabbix API 删除对象。
|
|
27
|
+
#
|
|
28
|
+
# @param data [Hash] 包含对象标识字段及其值
|
|
29
|
+
# @raise [ApiError] Zabbix API 调用失败时抛出
|
|
30
|
+
# @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
|
|
31
|
+
# @return [Integer] 删除单个对象时返回对象 ID
|
|
32
|
+
# @return [Boolean] 删除多个对象时返回操作结果
|
|
16
33
|
def destroy(data)
|
|
17
34
|
delete(data)
|
|
18
35
|
end
|
|
36
|
+
|
|
37
|
+
# 返回子类对应的 Zabbix API 方法名;由具体资源类实现。
|
|
38
|
+
#
|
|
39
|
+
# @return [String, nil] API 方法名
|
|
40
|
+
def method_name; end
|
|
19
41
|
end
|
|
20
42
|
end
|
|
@@ -2,83 +2,54 @@
|
|
|
2
2
|
|
|
3
3
|
class ZabbixManager
|
|
4
4
|
class Basic
|
|
5
|
-
#
|
|
5
|
+
# 将调试信息交给客户端结构化日志,并移除可能包含请求参数的片段。
|
|
6
|
+
#
|
|
7
|
+
# @param message [String] 待记录的调试信息
|
|
8
|
+
# @return [void]
|
|
6
9
|
def log(message)
|
|
7
|
-
|
|
10
|
+
return unless @client.options[:debug]
|
|
11
|
+
|
|
12
|
+
raw_message = message.to_s
|
|
13
|
+
safe_message = if raw_message.start_with?("[DEBUG]")
|
|
14
|
+
raw_message[/\A\[DEBUG\]\s+Call\s+[a-z_]+/i] || "[DEBUG] domain operation"
|
|
15
|
+
else
|
|
16
|
+
raw_message
|
|
17
|
+
end
|
|
18
|
+
@client.log(:debug, "domain.operation", message: safe_message)
|
|
8
19
|
end
|
|
9
20
|
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
# 比较实际哈希是否包含期望哈希中的全部键值。
|
|
22
|
+
#
|
|
23
|
+
# @param first_hash [Hash] 实际数据
|
|
24
|
+
# @param second_hash [Hash] 期望数据
|
|
25
|
+
# @return [Boolean] 是否匹配
|
|
26
|
+
def hash_equals?(first_hash, second_hash)
|
|
27
|
+
actual = normalize_hash(first_hash)
|
|
28
|
+
expected = normalize_hash(second_hash)
|
|
29
|
+
actual.slice(*expected.keys) == expected
|
|
19
30
|
end
|
|
20
31
|
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
when Array
|
|
26
|
-
object.map(&method(:symbolize_keys))
|
|
27
|
-
when Hash
|
|
28
|
-
object.transform_keys(&:to_sym).transform_values(&method(:symbolize_keys))
|
|
29
|
-
else
|
|
30
|
-
object
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# 将所有哈希值规范化为字符串
|
|
32
|
+
# 将哈希值递归规范为字符串,并忽略 hostid。
|
|
33
|
+
#
|
|
34
|
+
# @param hash [Hash] 待规范化的哈希
|
|
35
|
+
# @return [Hash] 规范化后的副本
|
|
35
36
|
def normalize_hash(hash)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# 移除用于日志记录的 TODO 注释。TemplateID 和 HostID 具有不同的 ID
|
|
39
|
-
result.delete(:hostid)
|
|
40
|
-
|
|
41
|
-
result.transform_keys!(&:to_sym)
|
|
42
|
-
result.transform_values! { |value| value.is_a?(Array) ? normalize_array(value) : value.to_s }
|
|
43
|
-
|
|
44
|
-
result
|
|
37
|
+
hash.deep_symbolize_keys.except(:hostid).deep_transform_values(&:to_s)
|
|
45
38
|
end
|
|
46
39
|
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
array.each do |e|
|
|
52
|
-
if e.is_a?(Array)
|
|
53
|
-
result.push(normalize_array(e))
|
|
54
|
-
elsif e.is_a?(Hash)
|
|
55
|
-
result.push(normalize_hash(e))
|
|
56
|
-
else
|
|
57
|
-
result.push(e.to_s)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
result
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# 解析包含 ID 键或布尔值的数据哈希
|
|
40
|
+
# 从 API 结果中解析单个对象 ID,或透传布尔结果。
|
|
41
|
+
#
|
|
42
|
+
# @param data [Hash, Boolean] API 返回结果
|
|
43
|
+
# @return [Integer, Boolean, nil] 对象 ID、布尔结果或空值
|
|
65
44
|
def parse_keys(data)
|
|
66
45
|
case data
|
|
67
46
|
when Hash
|
|
68
|
-
data.empty? ?
|
|
47
|
+
data.empty? ? nil : data[keys][0].to_i
|
|
69
48
|
when TrueClass
|
|
70
49
|
true
|
|
71
50
|
when FalseClass
|
|
72
51
|
false
|
|
73
|
-
else
|
|
74
|
-
false
|
|
75
52
|
end
|
|
76
53
|
end
|
|
77
|
-
|
|
78
|
-
# 合并两个哈希为一个新的哈希
|
|
79
|
-
def merge_hashes(hash1, hash2)
|
|
80
|
-
new_hash = hash1.dup
|
|
81
|
-
new_hash.merge(hash2)
|
|
82
|
-
end
|
|
83
54
|
end
|
|
84
55
|
end
|
|
@@ -2,34 +2,49 @@
|
|
|
2
2
|
|
|
3
3
|
class ZabbixManager
|
|
4
4
|
class Basic
|
|
5
|
-
# 使用 ZabbixManager
|
|
5
|
+
# 使用 ZabbixManager 客户端初始化基础资源对象。
|
|
6
|
+
#
|
|
7
|
+
# @param client [ZabbixManager::Client] API 客户端
|
|
8
|
+
# @return [ZabbixManager::Basic] 基础资源对象
|
|
6
9
|
def initialize(client)
|
|
7
10
|
@client = client
|
|
8
11
|
end
|
|
9
12
|
|
|
10
|
-
#
|
|
13
|
+
# 定义资源对应的 API 方法名占位,要求子类覆盖。
|
|
14
|
+
#
|
|
15
|
+
# @raise [ApiError] 基础类不能直接提供方法名时抛出
|
|
16
|
+
# @return [String] API 方法名
|
|
11
17
|
def method_name
|
|
12
|
-
raise
|
|
18
|
+
raise Invalid, "Can't call method_name here"
|
|
13
19
|
end
|
|
14
20
|
|
|
15
|
-
#
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# 派生类可以重写此方法以提供特定的默认选项
|
|
21
|
+
# 返回资源创建时使用的默认选项,子类可按需覆盖。
|
|
22
|
+
#
|
|
23
|
+
# @return [Hash] 默认选项
|
|
21
24
|
def default_options
|
|
22
25
|
{}
|
|
23
26
|
end
|
|
24
27
|
|
|
25
|
-
#
|
|
28
|
+
# 根据单数 ID 字段名生成 API 返回结果中的复数字段名。
|
|
29
|
+
#
|
|
30
|
+
# @return [String] 复数 ID 字段名
|
|
31
|
+
def keys
|
|
32
|
+
"#{key}s"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# 根据 API 方法名生成对象 ID 字段名。
|
|
36
|
+
#
|
|
37
|
+
# @return [String] 对象 ID 字段名
|
|
26
38
|
def key
|
|
27
39
|
"#{method_name}id"
|
|
28
40
|
end
|
|
29
41
|
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
|
|
42
|
+
# 定义资源业务标识字段占位,要求子类覆盖。
|
|
43
|
+
#
|
|
44
|
+
# @raise [ApiError] 基础类不能直接提供标识字段时抛出
|
|
45
|
+
# @return [String] 业务标识字段名
|
|
46
|
+
def identify
|
|
47
|
+
raise Invalid, "Can't call identify here"
|
|
33
48
|
end
|
|
34
49
|
end
|
|
35
50
|
end
|