zabbix_manager 5.1.6 → 6.0.0

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -1
  3. data/README.md +69 -46
  4. data/lib/zabbix_manager/classes/actions.rb +3 -11
  5. data/lib/zabbix_manager/classes/applications.rb +2 -8
  6. data/lib/zabbix_manager/classes/configurations.rb +4 -9
  7. data/lib/zabbix_manager/classes/{drules.rb → discovery_rules.rb} +2 -8
  8. data/lib/zabbix_manager/classes/errors.rb +3 -0
  9. data/lib/zabbix_manager/classes/events.rb +2 -1
  10. data/lib/zabbix_manager/classes/graphs.rb +19 -15
  11. data/lib/zabbix_manager/classes/{hostgroups.rb → host_groups.rb} +5 -11
  12. data/lib/zabbix_manager/classes/host_interfaces.rb +261 -0
  13. data/lib/zabbix_manager/classes/hosts.rb +135 -89
  14. data/lib/zabbix_manager/classes/{httptests.rb → http_tests.rb} +2 -8
  15. data/lib/zabbix_manager/classes/items.rb +91 -87
  16. data/lib/zabbix_manager/classes/maintenance.rb +2 -1
  17. data/lib/zabbix_manager/classes/{mediatypes.rb → media_types.rb} +2 -7
  18. data/lib/zabbix_manager/classes/problems.rb +11 -40
  19. data/lib/zabbix_manager/classes/proxies.rb +5 -15
  20. data/lib/zabbix_manager/classes/proxy_groups.rb +16 -0
  21. data/lib/zabbix_manager/classes/roles.rb +13 -19
  22. data/lib/zabbix_manager/classes/screens.rb +11 -30
  23. data/lib/zabbix_manager/classes/scripts.rb +2 -8
  24. data/lib/zabbix_manager/classes/server.rb +1 -0
  25. data/lib/zabbix_manager/classes/templates.rb +2 -65
  26. data/lib/zabbix_manager/classes/triggers.rb +42 -45
  27. data/lib/zabbix_manager/classes/user_groups.rb +63 -0
  28. data/lib/zabbix_manager/classes/user_macros.rb +110 -0
  29. data/lib/zabbix_manager/classes/users.rb +15 -54
  30. data/lib/zabbix_manager/classes/value_maps.rb +52 -0
  31. data/lib/zabbix_manager/client.rb +148 -277
  32. data/lib/zabbix_manager/configuration.rb +107 -0
  33. data/lib/zabbix_manager/http_transport.rb +145 -97
  34. data/lib/zabbix_manager/log_sanitizer.rb +9 -19
  35. data/lib/zabbix_manager/monitoring/device.rb +393 -0
  36. data/lib/zabbix_manager/monitoring/expressions.rb +36 -0
  37. data/lib/zabbix_manager/monitoring/line.rb +175 -0
  38. data/lib/zabbix_manager/monitoring/line_items.rb +110 -0
  39. data/lib/zabbix_manager/monitoring/line_lifecycle.rb +169 -0
  40. data/lib/zabbix_manager/monitoring/line_plan.rb +113 -0
  41. data/lib/zabbix_manager/monitoring/thresholds.rb +182 -0
  42. data/lib/zabbix_manager/monitoring/traffic_items.rb +132 -0
  43. data/lib/zabbix_manager/monitoring/validation.rb +92 -0
  44. data/lib/zabbix_manager/monitoring.rb +216 -642
  45. data/lib/zabbix_manager/resource.rb +235 -0
  46. data/lib/zabbix_manager/traffic.rb +238 -0
  47. data/lib/zabbix_manager/version.rb +1 -1
  48. data/lib/zabbix_manager.rb +66 -179
  49. data/zabbix_manager.gemspec +6 -22
  50. metadata +41 -190
  51. data/lib/zabbix_manager/basic/basic_alias.rb +0 -42
  52. data/lib/zabbix_manager/basic/basic_func.rb +0 -55
  53. data/lib/zabbix_manager/basic/basic_init.rb +0 -50
  54. data/lib/zabbix_manager/basic/basic_logic.rb +0 -239
  55. data/lib/zabbix_manager/classes/hostinterfaces.rb +0 -189
  56. data/lib/zabbix_manager/classes/usergroups.rb +0 -75
  57. data/lib/zabbix_manager/classes/usermacros.rb +0 -222
  58. data/lib/zabbix_manager/classes/valuemaps.rb +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37c70888e6fd6b0e27a4945f2672d460243584724c67eed4eadc4d69b88d6ad7
4
- data.tar.gz: 6975d3b02322a81fe8923503e58b91f1888de4ec324f30846552305931fe6a59
3
+ metadata.gz: b40a4744edcbba667b1c548c576b6451e637dee80bce28755a151f58e02a553b
4
+ data.tar.gz: 5d5ee350721f10da7ea9f93582bf06fc6c5b6ac4e5a9bbaa445058f43c205a45
5
5
  SHA512:
6
- metadata.gz: 875b98496cffef36b128f8038f007c8d9a0a9bdb6635c14df0380545ef495903970c73ffca1cb26105a3e382d14e88517308edd81b11b57d5be64e30e0b6f486
7
- data.tar.gz: 9d2d60aa041e3e993b4c8aaf9c900570824a997537dca1f0fc34a88dbc7f2dd7286d86adc2ecda40e04b2ac0393fa9279cbbb2a29b65c92dab1a92463984d833
6
+ metadata.gz: db558e058564904b417225b8f59df28a741b7f73d787f104180dd878e017899fadfe077d4194b2e2f2b2995639cf9c42ab585abf25f0d06308af9f8a6549eeba
7
+ data.tar.gz: 5c6a2e519171dec793941f13ba766aad04679a008196dad090b784614fa59882c851c810554c0c8ee479ba8aa7493779c5c2f770bfc1d24c0efb8da4a730da7d
data/CHANGELOG.md CHANGED
@@ -1,6 +1,36 @@
1
1
  # CHANGELOG
2
2
 
3
- ## Unreleased
3
+ ## 6.0.0 (2026-10-01)
4
+
5
+ * Fix role ID queries and host-scoped value map identities, keeping immutable host fields out of updates.
6
+ * Reject incomplete interface creation and duplicate resolved interface targets before remote writes.
7
+ * Preserve distinct interface names, validate standard 32-bit octet conversion, and check effective numeric item configuration before writing monitoring updates.
8
+ * Bound network request duration and decompressed response size, close failed connections, and never replay uncertain mutations.
9
+ * Complete Chinese module comments and correct public return-type documentation.
10
+
11
+ * Extract reusable Motor monitoring scenarios through native Zabbix APIs only, without SQL or application persistence.
12
+ * Add `traffic.series` and `traffic.for_interface` for precise history/trend reads with missing-data and truncation states.
13
+ * Add device name resolution, proxy groups, SNMP secret macros and caller-owned membership receipts; preserve unrelated configuration.
14
+ * Add line previews, low-traffic/status/ICMP checks, dependencies, scoped problem reads and managed trigger retirement.
15
+ * Return device receipts and per-kind line `triggerids`; expand public method contracts and executable workflow examples.
16
+
17
+ * Validate mutation receipts against requested IDs; empty, malformed or mismatched receipts remain unconfirmed outcomes.
18
+ * Require desired trigger state during lost-response recovery and serialize dependency replacement with appends.
19
+ * Replace obsolete template-side host-link helpers with `hosts.link_templates`, `replace_templates`, and `unlink_templates` using current host APIs.
20
+ * Use explicit `user_groups.replace_users` and `replace_host_group_permissions` operations with version-correct server fields.
21
+ * Verify packaged source inventory and isolated authenticated requests, then publish the exact verified artifact; declare IRB for Ruby 4 development consoles.
22
+
23
+ * Normalize multiword resource classes, files and accessors to Ruby CamelCase/snake_case without compatibility aliases.
24
+
25
+ * Require Ruby 3.4 or newer; refresh the dependency lockfile and remove development-tool version pins and duplicate declarations.
26
+ * Replace the split `Basic` hierarchy with `Resource`, remove compatibility aliases and parameter logging, and use keyword connection/request options.
27
+ * Use ActiveSupport logger/tagging/parameter filtering; make logging failure independent of API results.
28
+ * Add explicit `from_env` loading for `ZABBIX_URL`, `ZABBIX_API_TOKEN`, `ZABBIX_USERNAME`, and `ZABBIX_PASSWORD` only.
29
+ * Remove `current`, `user`, `debug`, `manager_request`, low-level client request helpers and legacy inventory field aliases; use explicit managers, `username`, `logger`/`log_level` and canonical monitoring fields.
30
+ * Validate JSON-RPC response shapes and IDs, report unconfirmed responses as `ProtocolError`, and prevent server text or exception causes from leaking secrets.
31
+ * Delegate proxy discovery and exclusions to Ruby, validate finite timeouts, and avoid closing an inherited parent TLS session after fork.
32
+ * Validate complete interface/item batches before writes, refuse ambiguous macro ownership, and distinguish missing values from empty strings during updates.
33
+ * Separate monitoring input, threshold and traffic-item rules, reject invalid units/expressions, and retain unknown write outcomes in batch results.
4
34
 
5
35
  * Add Zabbix 7.x API-token authentication through the Bearer header while retaining the legacy 4.x-6.x authentication body.
6
36
  * Reuse a thread-safe persistent `Net::HTTP` session and add explicit `close` lifecycle handling.
data/README.md CHANGED
@@ -4,8 +4,7 @@
4
4
 
5
5
  [gem]: https://rubygems.org/gems/zabbix_manager
6
6
 
7
- Most codes borrowed from zabbixapi, but fit for my everyday works well!
8
- Simple and lightweight ruby module for working with [Zabbix][Zabbix] via the [Zabbix API][Zabbix API]
7
+ A Ruby client for the [Zabbix API][Zabbix API], with reusable device, interface and circuit monitoring workflows.
9
8
 
10
9
  ## Installation
11
10
  ```sh
@@ -41,6 +40,25 @@ zabbix.close
41
40
 
42
41
  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
42
 
43
+ ### Environment configuration
44
+
45
+ Environment loading is explicit. `connect` uses only its keyword arguments; `from_env` reads exactly four variables:
46
+
47
+ | Variable | Option |
48
+ | --- | --- |
49
+ | `ZABBIX_URL` | `url` |
50
+ | `ZABBIX_API_TOKEN` | `api_token` |
51
+ | `ZABBIX_USERNAME` | `username` |
52
+ | `ZABBIX_PASSWORD` | `password` |
53
+
54
+ ```ruby
55
+ zabbix = ZabbixManager.from_env(verify_ssl: true)
56
+ ```
57
+
58
+ Explicit keyword arguments override environment values, including `nil` to clear an inherited credential. Set either an API token or a username/password pair. Unknown options and non-boolean flags are rejected before connecting. Timeouts, logging and locking remain ordinary keyword options.
59
+
60
+ The HTTP transport uses Ruby's standard proxy discovery (`http_proxy`/`HTTP_PROXY`, `no_proxy`/`NO_PROXY`, with CGI protection). `no_proxy: true` disables proxies; `proxy: "http://proxy.example:8080"` selects an explicit HTTP proxy. HTTPS proxy URLs are rejected because this transport does not encrypt the connection to the proxy itself.
61
+
44
62
  ### Username and password
45
63
 
46
64
  ```ruby
@@ -61,7 +79,7 @@ A client keeps one persistent `Net::HTTP` session and serializes access to it, s
61
79
 
62
80
  ### Logging and HTTPS
63
81
 
64
- Pass any Ruby Logger-compatible object to receive connection, request completion, duration, and failure events:
82
+ Pass a Ruby Logger or ActiveSupport logger to receive connection, request completion, duration, and failure events:
65
83
 
66
84
  ```ruby
67
85
  zabbix = ZabbixManager.connect(
@@ -71,28 +89,31 @@ zabbix = ZabbixManager.connect(
71
89
  )
72
90
  ```
73
91
 
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.
92
+ Logging uses `ActiveSupport::Logger` and `ActiveSupport::TaggedLogging`; structured credential filtering uses `ActiveSupport::ParameterFilter`. Pass `log_level: :info` to create a logger on standard error, or inject your application's logger. Logging is disabled unless one of these options is supplied, and logging failures do not change API outcomes.
93
+
94
+ Passwords, API tokens, authorization values, cookies, and session IDs are filtered. Request parameters and response bodies are not logged. API exceptions expose the server error code and request ID, without remote messages or data that might echo arbitrary secrets. Malformed or mismatched JSON-RPC responses and invalid mutation ID receipts raise `ProtocolError < TransportError`: a write may already have happened, so it must not be blindly replayed.
75
95
 
76
96
  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
97
 
78
98
  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
99
 
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.
100
+ Timeouts can be set together with `timeout:` or independently with `open_timeout:`, `read_timeout:`, and `write_timeout:`. `keep_alive_timeout:` controls persistent connection reuse. `request_timeout:` bounds the complete network operation, including a continuously progressing response, and defaults to `timeout:`. Waiting for another request on the same client is outside that budget. `max_response_bytes:` limits the decompressed response body (64 MiB by default). Exceeding either limit closes the connection and raises `TransportError`; mutations are never automatically replayed.
81
101
 
82
102
  ### Device and interface monitoring
83
103
 
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.
104
+ `monitoring` provides device and line workflows using native Zabbix APIs only. There are no SQL operations, Rails models or persistence dependencies. Item identity is the stable pair `hostid + key_`; managed triggers use a dedicated `zabbix_manager_id` tag. Missing objects are created and existing ones are updated. Optional line checks removed from a definition are disabled after the remaining desired checks succeed; objects are never automatically deleted.
85
105
 
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.
106
+ For a line inventory that already has interface traffic items discovered by Zabbix, use `reconcile_line`. It locates the host and unique inbound/outbound items, then creates or updates the selected checks. Use canonical fields `host` (or `host_candidates`), `interface_name`, `capacity_mbps`, and a stable, non-secret endpoint `line_id`. Convert external inventory column names before calling the library.
107
+
108
+ The complete workflows and return values are documented in [device monitoring](examples/device_monitoring.md), [line monitoring](examples/line_monitoring.md), and [traffic queries](examples/traffic.md). Public method comments document input, output, failures and remote side effects.
87
109
 
88
110
  ```ruby
89
111
  zabbix.monitoring.reconcile_line(
90
112
  line_id: "line-42",
91
113
  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",
114
+ capacity_mbps: 200,
115
+ host_candidates: ["edge-switch-01", "192.0.2.10"],
116
+ interface_name: "Ten-GigabitEthernet1/0/49",
96
117
  isp: "Example ISP",
97
118
  high_water: 0.90,
98
119
  recovery_water: 0.80,
@@ -102,11 +123,11 @@ zabbix.monitoring.reconcile_line(
102
123
  )
103
124
  ```
104
125
 
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.
126
+ 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. Trigger ownership comes from the managed identity tag; matching descriptions alone never adopt unrelated triggers.
106
127
 
107
128
  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
129
 
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.
130
+ 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: retry discovery after the required items become available. Inspect any `:unknown` write outcome before repeating that entry.
110
131
 
111
132
  ```ruby
112
133
  result = zabbix.monitoring.reconcile_network(
@@ -114,16 +135,13 @@ result = zabbix.monitoring.reconcile_network(
114
135
  {
115
136
  host: "edge-router-01",
116
137
  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
- }]
138
+ groups: ["Network devices"],
139
+ snmp: { ip: "192.0.2.10", community: ENV.fetch("SNMP_COMMUNITY") }
122
140
  }
123
141
  ],
124
142
  lines: [
125
143
  {
126
- line_id: "line-42", device: "edge-router-01",
144
+ line_id: "line-42", host: "edge-router-01",
127
145
  interface_name: "Ten-GigabitEthernet1/0/49", capacity_mbps: 200,
128
146
  high_water: 0.90, recovery_water: 0.80
129
147
  }
@@ -134,7 +152,7 @@ result.fetch(:summary)
134
152
  ```
135
153
 
136
154
  ```ruby
137
- hostid = zabbix.monitoring.reconcile_device(
155
+ receipt = zabbix.monitoring.reconcile_device(
138
156
  host: "router-01",
139
157
  name: "Core router 01",
140
158
  groups: [{ groupid: 20 }],
@@ -148,10 +166,14 @@ hostid = zabbix.monitoring.reconcile_device(
148
166
  details: { version: 2, community: ENV.fetch("SNMP_COMMUNITY") }
149
167
  }]
150
168
  )
169
+ hostid = receipt.fetch(:hostid)
170
+ snmp_interface = zabbix.host_interfaces.for_host(hostid).find do |interface|
171
+ interface["type"] == "2" && interface["main"] == "1"
172
+ end
151
173
 
152
174
  zabbix.monitoring.reconcile_interface(
153
175
  host: { hostid: hostid, host: "router-01" },
154
- interface: { name: "GigabitEthernet1/0/1", interfaceid: 12 },
176
+ interface: { name: "GigabitEthernet1/0/1", interfaceid: snmp_interface.fetch("interfaceid") },
155
177
  items: {
156
178
  inbound_bps: {
157
179
  key_: "if.hc.in.bps[1]", name: "WAN inbound", type: 20, value_type: 0,
@@ -192,9 +214,9 @@ zabbix.monitoring.reconcile_interface(
192
214
  )
193
215
  ```
194
216
 
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.
217
+ 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. Line `high_water` and `recovery_water` are ratios greater than zero and at most one; percentages such as `90` are rejected. Interface threshold recovery is inclusive (`<=`), so a zero recovery threshold remains attainable.
196
218
 
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.
219
+ 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. Batch results distinguish `ok`, `error`, and `unknown`; summaries count each status. Transport failures during device reconciliation are conservatively `unknown`, since that workflow includes both lookup and write calls. Successful earlier remote writes are not rolled back if a later operation fails. After an uncertain outcome has been resolved, a retry can converge already-created items by stable keys. If a trigger create loses its response, readback must confirm both its managed identity and requested attributes. If that cannot be confirmed, `ResultUnknown` is raised and must not be automatically retried. A definite API rejection is propagated. The readback schedule can be set with `uncertain_write_delays:` (up to 60 seconds total). Trigger upserts and dependency read/modify/write operations are 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
220
 
199
221
  ```ruby
200
222
  ZabbixManager.connect(
@@ -204,40 +226,32 @@ ZabbixManager.connect(
204
226
  )
205
227
  ```
206
228
 
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.
229
+ 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`. The focused item/interface/trigger deletion, status and dependency helpers require `hostid:` and verify existing ownership before writing. Custom trigger expressions and raw resource methods accept trusted Zabbix definitions; the host lookup context does not replace application authorization. Dependencies default to the same host; cross-host dependencies require `allow_cross_host_dependencies: true`. Do not pass untrusted page parameters directly to `query`, raw resource methods, or custom expressions.
208
230
 
209
231
  ### High-frequency API modules
210
232
 
211
- The focused modules expose explicit current operations instead of compatibility aliases:
233
+ `traffic.series` reads explicit item IDs; `traffic.for_interface` discovers both interface directions. Both expose missing data and query truncation, preserve numeric precision, and keep raw history separate from hourly trends. They never substitute zero or a stale last value for missing samples.
212
234
 
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`
235
+ Multiword resource accessors use Ruby snake_case: `host_groups`, `host_interfaces`, `http_tests`, `media_types`, `proxy_groups`, `user_groups`, `user_macros`, `value_maps`, and `discovery_rules`.
236
+
237
+ The focused modules expose explicit operations:
238
+
239
+ * `hosts.reconcile`, `hosts.resolve`, `hosts.find_by_id`, `hosts.find_by_candidates`, `hosts.set_status`
240
+ * `monitoring.reconcile_device`, `monitoring.reconcile_devices`, `monitoring.reconcile_network`
241
+ * `monitoring.plan_line`, `monitoring.reconcile_line`, `monitoring.line_triggers`, `monitoring.line_problems`, `monitoring.disable_line`
242
+ * `hosts.link_templates`, `hosts.replace_templates`, `hosts.unlink_templates`
243
+ * `user_groups.replace_users`, `user_groups.replace_host_group_permissions`
244
+ * `host_interfaces.for_host`, `host_interfaces.reconcile_for_host`, `host_interfaces.delete_many`
215
245
  * `items.for_host`, `items.upsert_by_key`, `items.upsert_many`, `items.set_status`, `items.delete_many`
216
246
  * `triggers.for_host`, `triggers.upsert_for_host`, `triggers.add_dependencies`, `triggers.replace_dependencies`, `triggers.set_status`, `triggers.delete_many`
217
247
 
218
248
 
219
249
  ## Supported Ruby Versions
220
- This library aims to support and is [tested against][github-ci] the following Ruby
221
- versions:
222
-
223
- * Ruby 2.7 and newer
224
-
225
- If something doesn't work on one of these versions, it's a bug.
226
-
227
- This library may inadvertently work (or seem to work) on other Ruby versions,
228
- however support will only be provided for the versions listed above.
229
-
230
- If you would like this library to support another Ruby version or
231
- implementation, you may volunteer to be a maintainer. Being a maintainer
232
- entails making sure all tests run and pass on that implementation. When
233
- something breaks on your implementation, you will be responsible for providing
234
- patches in a timely fashion. If critical issues for a particular implementation
235
- exist at the time of a major release, support for that Ruby version may be
236
- dropped.
250
+ The minimum Ruby version is **3.4**. CI runs Ruby 3.4 and 4.0.
237
251
 
238
252
  ## Dependencies
239
253
 
240
- * net/http
254
+ * net-http
241
255
  * active_support
242
256
  * json
243
257
  * logger
@@ -247,11 +261,16 @@ dropped.
247
261
  * Fork the project.
248
262
  * Base your work on the master branch.
249
263
  * Make your feature addition or bug fix, write tests, write documentation/examples.
250
- * Commit, do not mess with rakefile, version.
264
+ * Run `bundle exec rake` and `bundle exec ruby script/verify_package.rb`.
251
265
  * Make a pull request.
252
266
 
253
267
  ## CI and release
254
268
 
269
+ `script/verify_package.rb` checks the complete library inventory, installs into an isolated gem directory, exercises authentication and a resource request over a local HTTP socket, then saves that exact verified archive under `pkg/`. It also works when invoked outside the checkout.
270
+
271
+ Development tools are declared once in `Gemfile`, without historical version pins. `Gemfile.lock` records the versions verified together. Runtime dependencies declare only the minimum API version needed by the library; update the lockfile and run the gates when changing dependencies.
272
+
273
+
255
274
  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
275
 
257
276
  ## Zabbix documentation
@@ -261,3 +280,7 @@ Pull requests and pushes to `master` run RSpec, documentation coverage, RuboCop,
261
280
 
262
281
  [Zabbix]: https://www.zabbix.com
263
282
  [Zabbix API]: https://www.zabbix.com/documentation/current/en/manual/api
283
+
284
+ ### Upgrading to 6.0
285
+
286
+ Version 6.0 requires Ruby 3.4 or newer. Use keyword connection and query arguments, snake_case resource accessors, the explicit exception classes, and the current monitoring result shapes shown above. Legacy aliases and the former `Basic` API are removed.
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Actions < Basic
4
+ # 告警动作资源;完整读取包含执行、恢复、确认操作及过滤条件。
5
+ class Actions < Resource
5
6
  # 返回操作对象对应的 Zabbix API 方法前缀。
6
7
  #
7
8
  # @return [String]
@@ -9,22 +10,13 @@ class ZabbixManager
9
10
  "action"
10
11
  end
11
12
 
12
- # 返回操作对象用于业务识别的字段名。
13
- #
14
- # @return [String]
15
- def identify
16
- "name"
17
- end
18
-
19
13
  # 获取操作及其执行、恢复、确认操作和过滤条件的完整数据。
20
14
  #
21
15
  # @param data [Hash] 包含识别字段及其值的查询条件
22
16
  # @raise [ApiError] Zabbix API 返回业务错误时抛出
23
17
  # @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
24
- # @return [Hash] 匹配的操作完整数据
18
+ # @return [Array<Hash>] 匹配的操作完整数据
25
19
  def get_full_data(data)
26
- log "[DEBUG] Call get_full_data with parameters: #{data.inspect}"
27
-
28
20
  @client.api_request(
29
21
  method: "#{method_name}.get",
30
22
  params: {
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Applications < Basic
4
+ # 应用集以 hostid + name 定位;端点是否可用由目标 Zabbix 版本决定。
5
+ class Applications < Resource
5
6
  # 返回应用集对象对应的 Zabbix API 方法前缀。
6
7
  #
7
8
  # @return [String]
@@ -9,13 +10,6 @@ class ZabbixManager
9
10
  "application"
10
11
  end
11
12
 
12
- # 返回应用集对象用于业务识别的字段名。
13
- #
14
- # @return [String]
15
- def identify
16
- "name"
17
- end
18
-
19
13
  # 生成由应用集名称和所属主机构成的稳定查询条件。
20
14
  # @param data [Hash] 包含 name 和 hostid 的应用集属性
21
15
  # @return [Hash] 应用集唯一查询条件
@@ -1,13 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Configurations < Basic
5
- # 标记配置接口使用数组形式处理 API 返回值。
6
- # @return [Boolean] 始终返回 true
7
- def array_flag
8
- true
9
- end
10
-
4
+ # 原生配置导入/导出入口;导入可能修改多个远端对象,不提供本地回滚。
5
+ class Configurations < Resource
11
6
  # 返回配置对象对应的 Zabbix API 方法前缀。
12
7
  #
13
8
  # @return [String]
@@ -27,7 +22,7 @@ class ZabbixManager
27
22
  # @param data [Hash] 配置导出参数
28
23
  # @raise [ApiError] Zabbix API 返回业务错误时抛出
29
24
  # @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
30
- # @return [Hash] 配置导出结果
25
+ # @return [String] 服务端按指定格式序列化的配置内容
31
26
  def export(data)
32
27
  @client.api_request(method: "configuration.export", params: data)
33
28
  end
@@ -37,7 +32,7 @@ class ZabbixManager
37
32
  # @param data [Hash] 配置导入参数及内容
38
33
  # @raise [ApiError] Zabbix API 返回业务错误时抛出
39
34
  # @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
40
- # @return [Hash] 配置导入结果
35
+ # @return [Boolean] 服务端确认的导入结果
41
36
  def import(data)
42
37
  @client.api_request(method: "configuration.import", params: data)
43
38
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Drules < Basic
4
+ # 网络发现规则(drule),区别于主机内的低级发现(discoveryrule)。
5
+ class DiscoveryRules < Resource
5
6
  # 返回网络发现规则对应的 Zabbix API 方法前缀。
6
7
  #
7
8
  # @return [String]
@@ -9,13 +10,6 @@ class ZabbixManager
9
10
  "drule"
10
11
  end
11
12
 
12
- # 返回网络发现规则用于业务识别的字段名。
13
- #
14
- # @return [String]
15
- def identify
16
- "name"
17
- end
18
-
19
13
  # 返回创建网络发现规则时使用的默认周期和启用状态。
20
14
  #
21
15
  # @return [Hash] 网络发现规则默认属性
@@ -22,6 +22,9 @@ class ZabbixManager
22
22
  # 表示 HTTP 状态或传输层失败。
23
23
  class TransportError < StandardError; end
24
24
 
25
+ # 响应无法确认远端操作是否已经完成。
26
+ class ProtocolError < TransportError; end
27
+
25
28
  # 表示远端可能已完成写入,调用方不得自动重放。
26
29
  class ResultUnknown < TransportError; end
27
30
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Events < Basic
4
+ # 原生事件查询入口;按当前客户端凭据可见范围返回服务端记录。
5
+ class Events < Resource
5
6
  # 返回事件对象对应的 Zabbix API 方法前缀。
6
7
  #
7
8
  # @return [String]
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Graphs < Basic
4
+ # 图形以 hostid + name 查询;写入所有者由 gitems 中的监控项确定。
5
+ class Graphs < Resource
5
6
  # 返回图形对象对应的 Zabbix API 方法前缀。
6
7
  #
7
8
  # @return [String]
@@ -9,22 +10,13 @@ class ZabbixManager
9
10
  "graph"
10
11
  end
11
12
 
12
- # 返回图形对象用于业务识别的字段名。
13
- #
14
- # @return [String]
15
- def identify
16
- "name"
17
- end
18
-
19
13
  # 按名称搜索并获取图形的完整数据。
20
14
  #
21
15
  # @param data [Hash] 包含图形识别字段及其值的查询条件
22
16
  # @raise [ApiError] Zabbix API 返回业务错误时抛出
23
17
  # @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
24
- # @return [Hash] 匹配的图形完整数据
18
+ # @return [Array<Hash>] 匹配的图形完整数据
25
19
  def get_full_data(data)
26
- log "[DEBUG] Call get_full_data with parameters: #{data.inspect}"
27
-
28
20
  @client.api_request(
29
21
  method: "#{method_name}.get",
30
22
  params: {
@@ -67,7 +59,7 @@ class ZabbixManager
67
59
  # @param data [Hash, String, Integer] 图形 ID
68
60
  # @raise [ApiError] Zabbix API 返回业务错误时抛出
69
61
  # @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
70
- # @return [Hash] 图形监控项数据
62
+ # @return [Array<Hash>] 图形监控项数据
71
63
  def get_items(data)
72
64
  @client.api_request(
73
65
  method: "graphitem.get",
@@ -78,12 +70,24 @@ class ZabbixManager
78
70
  )
79
71
  end
80
72
 
81
- # 生成由图形名称和所属模板构成的稳定查询条件。
82
- # @param data [Hash] 包含 name 和 templateid 的图形属性
73
+ # 生成由图形名称和所属主机或模板构成的稳定查询条件。
74
+ # graph.templateid 是继承源图形 ID,不是所属模板 ID。
75
+ # @param data [Hash] 包含 name 和 hostid 的图形属性
83
76
  # @return [Hash] 图形唯一查询条件
84
77
  def identity_filter(data)
85
78
  attributes = data.deep_symbolize_keys
86
- { name: attributes.fetch(:name), templateid: attributes.fetch(:templateid) }
79
+ { name: attributes.fetch(:name), hostid: attributes.fetch(:hostid) }
80
+ end
81
+
82
+ # 图形所有者由 gitems 确定,hostid 仅用于调用方的身份查询。
83
+ # @return [Integer, nil]
84
+ def create(data)
85
+ super(data.deep_symbolize_keys.except(:hostid))
86
+ end
87
+
88
+ # @return [Integer, nil] 更新的图形 ID
89
+ def update(data)
90
+ super(data.deep_symbolize_keys.except(:hostid))
87
91
  end
88
92
  end
89
93
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class HostGroups < Basic
4
+ # 主机群组名称解析与按需创建;批量创建按顺序执行,不是远端事务。
5
+ class HostGroups < Resource
5
6
  # 返回主机群组对应的 Zabbix API 方法前缀。
6
7
  #
7
8
  # @return [String]
@@ -9,13 +10,6 @@ class ZabbixManager
9
10
  "hostgroup"
10
11
  end
11
12
 
12
- # 返回主机群组用于业务识别的字段名。
13
- #
14
- # @return [String]
15
- def identify
16
- "name"
17
- end
18
-
19
13
  # 返回主机群组的 Zabbix ID 字段名。
20
14
  #
21
15
  # @return [String]
@@ -44,7 +38,7 @@ class ZabbixManager
44
38
  # 批量查询并创建缺失的主机群组,避免逐名称重复查询。
45
39
  # @param data [Array<String>, String] 待确保存在的群组名称
46
40
  # @return [Array<Hash>] 群组 ID 列表
47
- def get_or_create_hostgroups(data)
41
+ def get_or_create_host_groups(data)
48
42
  names = normalized_names(data)
49
43
  existing = @client.api_request(
50
44
  method: "hostgroup.get",
@@ -53,10 +47,10 @@ class ZabbixManager
53
47
 
54
48
  names.map do |name|
55
49
  group = existing[name]
56
- next({ groupid: group.fetch("groupid") }) if group
50
+ next({ groupid: response_identifier(group["groupid"]).to_s }) if group
57
51
 
58
52
  result = @client.api_request(method: "hostgroup.create", params: { name: name })
59
- { groupid: result.fetch("groupids").first }
53
+ { groupid: response_id(result).to_s }
60
54
  end
61
55
  end
62
56