zabbix_manager 5.1.5 → 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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -9
  3. data/LICENSE +1 -1
  4. data/README.md +241 -24
  5. data/lib/zabbix_manager/classes/actions.rb +19 -17
  6. data/lib/zabbix_manager/classes/applications.rb +11 -22
  7. data/lib/zabbix_manager/classes/configurations.rb +20 -10
  8. data/lib/zabbix_manager/classes/discovery_rules.rb +23 -0
  9. data/lib/zabbix_manager/classes/errors.rb +18 -27
  10. data/lib/zabbix_manager/classes/events.rb +8 -3
  11. data/lib/zabbix_manager/classes/graphs.rb +48 -37
  12. data/lib/zabbix_manager/classes/host_groups.rb +64 -0
  13. data/lib/zabbix_manager/classes/host_interfaces.rb +261 -0
  14. data/lib/zabbix_manager/classes/hosts.rb +232 -76
  15. data/lib/zabbix_manager/classes/http_tests.rb +32 -0
  16. data/lib/zabbix_manager/classes/items.rb +206 -72
  17. data/lib/zabbix_manager/classes/maintenance.rb +8 -3
  18. data/lib/zabbix_manager/classes/media_types.rb +18 -0
  19. data/lib/zabbix_manager/classes/problems.rb +51 -62
  20. data/lib/zabbix_manager/classes/proxies.rb +45 -14
  21. data/lib/zabbix_manager/classes/proxy_groups.rb +16 -0
  22. data/lib/zabbix_manager/classes/roles.rb +46 -41
  23. data/lib/zabbix_manager/classes/screens.rb +36 -24
  24. data/lib/zabbix_manager/classes/scripts.rb +16 -12
  25. data/lib/zabbix_manager/classes/server.rb +8 -1
  26. data/lib/zabbix_manager/classes/templates.rb +26 -51
  27. data/lib/zabbix_manager/classes/triggers.rb +251 -67
  28. data/lib/zabbix_manager/classes/user_groups.rb +63 -0
  29. data/lib/zabbix_manager/classes/user_macros.rb +110 -0
  30. data/lib/zabbix_manager/classes/users.rb +16 -23
  31. data/lib/zabbix_manager/classes/value_maps.rb +52 -0
  32. data/lib/zabbix_manager/client.rb +183 -137
  33. data/lib/zabbix_manager/configuration.rb +107 -0
  34. data/lib/zabbix_manager/http_transport.rb +240 -0
  35. data/lib/zabbix_manager/log_sanitizer.rb +58 -0
  36. data/lib/zabbix_manager/monitoring/device.rb +393 -0
  37. data/lib/zabbix_manager/monitoring/expressions.rb +36 -0
  38. data/lib/zabbix_manager/monitoring/line.rb +175 -0
  39. data/lib/zabbix_manager/monitoring/line_items.rb +110 -0
  40. data/lib/zabbix_manager/monitoring/line_lifecycle.rb +169 -0
  41. data/lib/zabbix_manager/monitoring/line_plan.rb +113 -0
  42. data/lib/zabbix_manager/monitoring/thresholds.rb +182 -0
  43. data/lib/zabbix_manager/monitoring/traffic_items.rb +132 -0
  44. data/lib/zabbix_manager/monitoring/validation.rb +92 -0
  45. data/lib/zabbix_manager/monitoring.rb +265 -0
  46. data/lib/zabbix_manager/resource.rb +235 -0
  47. data/lib/zabbix_manager/traffic.rb +238 -0
  48. data/lib/zabbix_manager/version.rb +1 -1
  49. data/lib/zabbix_manager.rb +110 -145
  50. data/zabbix_manager.gemspec +12 -15
  51. metadata +67 -30
  52. data/lib/zabbix_manager/basic/basic_alias.rb +0 -20
  53. data/lib/zabbix_manager/basic/basic_func.rb +0 -84
  54. data/lib/zabbix_manager/basic/basic_init.rb +0 -35
  55. data/lib/zabbix_manager/basic/basic_logic.rb +0 -195
  56. data/lib/zabbix_manager/classes/drules.rb +0 -41
  57. data/lib/zabbix_manager/classes/hostgroups.rb +0 -20
  58. data/lib/zabbix_manager/classes/hostinterfaces.rb +0 -29
  59. data/lib/zabbix_manager/classes/httptests.rb +0 -40
  60. data/lib/zabbix_manager/classes/mediatypes.rb +0 -79
  61. data/lib/zabbix_manager/classes/unusable.rb +0 -11
  62. data/lib/zabbix_manager/classes/usergroups.rb +0 -53
  63. data/lib/zabbix_manager/classes/usermacros.rb +0 -136
  64. data/lib/zabbix_manager/classes/valuemaps.rb +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72554dfff6fd4d60ac8be48bc766c9367e4b07f9fa2e3df7500cb21b49a6b033
4
- data.tar.gz: 01bea1ff565779f4ce5dab0b9a53d1832e80f9581b58dcc2e9bc943e83da9a46
3
+ metadata.gz: b40a4744edcbba667b1c548c576b6451e637dee80bce28755a151f58e02a553b
4
+ data.tar.gz: 5d5ee350721f10da7ea9f93582bf06fc6c5b6ac4e5a9bbaa445058f43c205a45
5
5
  SHA512:
6
- metadata.gz: 28bfea0b7a7bd6d99d394a0168a3399275af50fe139609141d03a996e6f488f484e8601529a58bf8710c492edd401514d66771e3b1411a53500898a05e8b6974
7
- data.tar.gz: a25a5c306cffa53d2b601c6f281e5ab5afbfb72fd8cef106683668f7d4b907b047b5d4ab76fcc2aa1e62b9df979ba5129628443c53601effe0de95facb69dd90
6
+ metadata.gz: db558e058564904b417225b8f59df28a741b7f73d787f104180dd878e017899fadfe077d4194b2e2f2b2995639cf9c42ab585abf25f0d06308af9f8a6549eeba
7
+ data.tar.gz: 5c6a2e519171dec793941f13ba766aad04679a008196dad090b784614fa59882c851c810554c0c8ee479ba8aa7493779c5c2f770bfc1d24c0efb8da4a730da7d
data/CHANGELOG.md CHANGED
@@ -1,11 +1,57 @@
1
1
  # CHANGELOG
2
2
 
3
- ## 5.1.1
4
- * 新增基类查询方法:
5
- * get_key_ids_by_identify:基于监控对象索引键(#{identify})查询 { "#{key}": id };
6
- * get_key_ids:基于监控对象索引建"#{identify}"查询 { "#{key}": id };
7
- * get_or_create_keys:批量创建或更新监控对象并返回 [{ "#{key}": id }];
8
- * 优化 Client 对象实例化逻辑:
9
- * 增加入参检查:必须提供 url、user和password,以及 @id 缓存;
10
- * 优化 debug 模式,接口请求入参和出参打印,均使用 JSON.pretty_unparse(data) 美化;
11
- * 完善项目注释,项目注释覆盖率90%;
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.
34
+
35
+ * Add Zabbix 7.x API-token authentication through the Bearer header while retaining the legacy 4.x-6.x authentication body.
36
+ * Reuse a thread-safe persistent `Net::HTTP` session and add explicit `close` lifecycle handling.
37
+ * Add injectable, credential-filtered request logging and stable JSON-RPC error handling.
38
+ * Add idempotent device/interface monitoring workflows with bandwidth, error, and packet-loss hysteresis triggers.
39
+ * Remove experimental `mojo_*` host/trigger methods and unsafe hard-coded SNMP defaults.
40
+ * Remove environment-specific item lookup helpers with hard-coded host data; use `monitoring.reconcile_line` instead.
41
+ * Remove copied Role user-group methods and the hard-coded historical problem-closing workflow.
42
+ * Remove dormant live-Zabbix scripts that were not part of the RSpec test pattern and mutated remote systems by default.
43
+ * Use ActiveSupport for deep key normalization and blank-value semantics.
44
+ * Batch line reconciliation to reuse host/item discovery and reject ambiguous or dimensionally invalid traffic items.
45
+ * Simplify template reference lookup and fix partial final-row sizing in screen creation.
46
+ * Replace the inherited Rails RuboCop profile with project-scoped lint, security, performance, packaging, layout, and safe style gates.
47
+ * Keep HTTPS verification disabled by default for compatibility, with an opt-in `verify_ssl: true` mode.
48
+ * Remove the unused `http` runtime dependency and support the `logger` default gem on modern Ruby.
49
+ * Add two-phase batch reconciliation for devices and lines with full preflight validation, sanitized per-entry errors, and summaries.
50
+ * Add focused host-interface CRUD, item batch/status/delete, trigger status/delete, and current trigger dependency append/replace APIs.
51
+ * Replace legacy exception names with `Invalid`, `Conflict`, `ApiError`, and `TransportError`.
52
+ * Add CI jobs for tests, formatting, Gem packaging, and trusted tag-based RubyGems publishing.
53
+ * Move project metadata to `https://github.com/gatework/zabbix_manager/tree/master`.
54
+ * Scope destructive and dependency operations by host, serialize host/interface reconciliation, and expose uncertain writes as `ResultUnknown`.
55
+ * Validate current Zabbix item/interface create contracts before writes and publish the exact smoke-tested Gem artifact.
56
+
57
+ ### 5.0.7
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 WENWU YAN
3
+ Copyright (c) 2022 WENWU YAN
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -4,8 +4,7 @@
4
4
 
5
5
  [gem]: https://rubygems.org/gems/zabbix_manager
6
6
 
7
- Most of the code in the project is based on rewriting the ZabbixApi
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
@@ -13,7 +12,7 @@ Simple and lightweight ruby module for working with [Zabbix][Zabbix] via the [Za
13
12
  gem install zabbix_manager
14
13
 
15
14
  # specific version
16
- gem install zabbix_manager -v 5.1.1
15
+ gem install zabbix_manager -v 4.2.0
17
16
  ```
18
17
 
19
18
  ## Documentation
@@ -23,47 +22,265 @@ gem install zabbix_manager -v 5.1.1
23
22
 
24
23
  ## Examples
25
24
 
25
+ ### API token (Zabbix 7.x)
26
26
 
27
- ## Supported Ruby Versions
28
- This library aims to support and is [tested against][github-ci] the following Ruby
29
- versions:
27
+ 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.
28
+
29
+ ```ruby
30
+ require "zabbix_manager"
31
+
32
+ zabbix = ZabbixManager.connect(
33
+ url: "https://zabbix.example.com/api_jsonrpc.php",
34
+ api_token: ENV.fetch("ZABBIX_API_TOKEN")
35
+ )
36
+
37
+ hosts = zabbix.hosts.get_raw(output: %w[hostid host])
38
+ zabbix.close
39
+ ```
40
+
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.
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
+
62
+ ### Username and password
63
+
64
+ ```ruby
65
+ zabbix = ZabbixManager.connect(
66
+ url: "https://zabbix.example.com/api_jsonrpc.php",
67
+ username: ENV.fetch("ZABBIX_USERNAME"),
68
+ password: ENV.fetch("ZABBIX_PASSWORD")
69
+ )
70
+
71
+ begin
72
+ zabbix.query(method: "host.get", params: { output: %w[hostid host] })
73
+ ensure
74
+ zabbix.logout
75
+ end
76
+ ```
77
+
78
+ 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.
79
+
80
+ ### Logging and HTTPS
81
+
82
+ Pass a Ruby Logger or ActiveSupport logger to receive connection, request completion, duration, and failure events:
83
+
84
+ ```ruby
85
+ zabbix = ZabbixManager.connect(
86
+ url: "https://zabbix.example.com/api_jsonrpc.php",
87
+ api_token: ENV.fetch("ZABBIX_API_TOKEN"),
88
+ logger: Rails.logger
89
+ )
90
+ ```
91
+
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.
95
+
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.
97
+
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.
99
+
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.
101
+
102
+ ### Device and interface monitoring
103
+
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.
30
105
 
31
- * Ruby 2.5
32
- * Ruby 2.6
33
- * Ruby 2.7
34
- * JRuby 9.2.10.0
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.
35
107
 
36
- If something doesn't work on one of these versions, it's a bug.
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.
37
109
 
38
- This library may inadvertently work (or seem to work) on other Ruby versions,
39
- however support will only be provided for the versions listed above.
110
+ ```ruby
111
+ zabbix.monitoring.reconcile_line(
112
+ line_id: "line-42",
113
+ description: "Example upstream circuit",
114
+ capacity_mbps: 200,
115
+ host_candidates: ["edge-switch-01", "192.0.2.10"],
116
+ interface_name: "Ten-GigabitEthernet1/0/49",
117
+ isp: "Example ISP",
118
+ high_water: 0.90,
119
+ recovery_water: 0.80,
120
+ problem_window: "5m",
121
+ recovery_window: "15m",
122
+ severity: 4
123
+ )
124
+ ```
125
+
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.
127
+
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.
129
+
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.
131
+
132
+ ```ruby
133
+ result = zabbix.monitoring.reconcile_network(
134
+ devices: [
135
+ {
136
+ host: "edge-router-01",
137
+ name: "Example edge router",
138
+ groups: ["Network devices"],
139
+ snmp: { ip: "192.0.2.10", community: ENV.fetch("SNMP_COMMUNITY") }
140
+ }
141
+ ],
142
+ lines: [
143
+ {
144
+ line_id: "line-42", host: "edge-router-01",
145
+ interface_name: "Ten-GigabitEthernet1/0/49", capacity_mbps: 200,
146
+ high_water: 0.90, recovery_water: 0.80
147
+ }
148
+ ]
149
+ )
150
+
151
+ result.fetch(:summary)
152
+ ```
153
+
154
+ ```ruby
155
+ receipt = zabbix.monitoring.reconcile_device(
156
+ host: "router-01",
157
+ name: "Core router 01",
158
+ groups: [{ groupid: 20 }],
159
+ interfaces: [{
160
+ type: 2,
161
+ main: 1,
162
+ useip: 1,
163
+ ip: "192.0.2.1",
164
+ dns: "",
165
+ port: "161",
166
+ details: { version: 2, community: ENV.fetch("SNMP_COMMUNITY") }
167
+ }]
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
173
+
174
+ zabbix.monitoring.reconcile_interface(
175
+ host: { hostid: hostid, host: "router-01" },
176
+ interface: { name: "GigabitEthernet1/0/1", interfaceid: snmp_interface.fetch("interfaceid") },
177
+ items: {
178
+ inbound_bps: {
179
+ key_: "if.hc.in.bps[1]", name: "WAN inbound", type: 20, value_type: 0,
180
+ snmp_oid: "get[1.3.6.1.2.1.31.1.1.1.6.1]", delay: "1m", units: "bps",
181
+ preprocessing: [
182
+ { type: 10, params: "", error_handler: 0, error_handler_params: "" },
183
+ { type: 1, params: "8", error_handler: 0, error_handler_params: "" }
184
+ ]
185
+ },
186
+ outbound_bps: {
187
+ key_: "if.hc.out.bps[1]", name: "WAN outbound", type: 20, value_type: 0,
188
+ snmp_oid: "get[1.3.6.1.2.1.31.1.1.1.10.1]", delay: "1m", units: "bps",
189
+ preprocessing: [
190
+ { type: 10, params: "", error_handler: 0, error_handler_params: "" },
191
+ { type: 1, params: "8", error_handler: 0, error_handler_params: "" }
192
+ ]
193
+ },
194
+ in_errors: {
195
+ key_: "if.in.errors.rate[1]", name: "WAN input errors", type: 20, value_type: 0,
196
+ snmp_oid: "get[1.3.6.1.2.1.2.2.1.14.1]", delay: "1m",
197
+ preprocessing: [{ type: 10, params: "", error_handler: 0, error_handler_params: "" }]
198
+ },
199
+ out_errors: {
200
+ key_: "if.out.errors.rate[1]", name: "WAN output errors", type: 20, value_type: 0,
201
+ snmp_oid: "get[1.3.6.1.2.1.2.2.1.20.1]", delay: "1m",
202
+ preprocessing: [{ type: 10, params: "", error_handler: 0, error_handler_params: "" }]
203
+ },
204
+ packet_loss: {
205
+ key_: "icmppingloss[198.51.100.1]", name: "WAN packet loss",
206
+ type: 3, value_type: 0, delay: "1m", units: "%"
207
+ }
208
+ },
209
+ thresholds: {
210
+ bandwidth: { capacity_bps: 1_000_000_000, high_percent: 80, recovery_percent: 70 },
211
+ errors: { high: 100, recovery: 20, function: "max", window: "5m" },
212
+ packet_loss: { high: 5, recovery: 2 }
213
+ }
214
+ )
215
+ ```
216
+
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.
218
+
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.
220
+
221
+ ```ruby
222
+ ZabbixManager.connect(
223
+ url: "https://zabbix.example.com/api_jsonrpc.php",
224
+ api_token: ENV.fetch("ZABBIX_API_TOKEN"),
225
+ upsert_lock: ->(key, &work) { MonitoringLock.with(key, &work) }
226
+ )
227
+ ```
228
+
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.
40
230
 
41
- If you would like this library to support another Ruby version or
42
- implementation, you may volunteer to be a maintainer. Being a maintainer
43
- entails making sure all tests run and pass on that implementation. When
44
- something breaks on your implementation, you will be responsible for providing
45
- patches in a timely fashion. If critical issues for a particular implementation
46
- exist at the time of a major release, support for that Ruby version may be
47
- dropped.
231
+ ### High-frequency API modules
232
+
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.
234
+
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`
245
+ * `items.for_host`, `items.upsert_by_key`, `items.upsert_many`, `items.set_status`, `items.delete_many`
246
+ * `triggers.for_host`, `triggers.upsert_for_host`, `triggers.add_dependencies`, `triggers.replace_dependencies`, `triggers.set_status`, `triggers.delete_many`
247
+
248
+
249
+ ## Supported Ruby Versions
250
+ The minimum Ruby version is **3.4**. CI runs Ruby 3.4 and 4.0.
48
251
 
49
252
  ## Dependencies
50
253
 
51
- * net/http
254
+ * net-http
255
+ * active_support
52
256
  * json
53
- * activesupport
257
+ * logger
54
258
 
55
259
  ## Contributing
56
260
 
57
261
  * Fork the project.
58
262
  * Base your work on the master branch.
59
263
  * Make your feature addition or bug fix, write tests, write documentation/examples.
60
- * Commit, do not mess with rakefile, version.
264
+ * Run `bundle exec rake` and `bundle exec ruby script/verify_package.rb`.
61
265
  * Make a pull request.
62
266
 
267
+ ## CI and release
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
+
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.
275
+
63
276
  ## Zabbix documentation
64
277
 
65
278
  * [Zabbix Project Homepage][Zabbix]
66
279
  * [Zabbix API docs][Zabbix API]
67
280
 
68
281
  [Zabbix]: https://www.zabbix.com
69
- [Zabbix API]: https://www.zabbix.com/documentation/5.2/manual/api
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,31 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Actions < Basic
5
- # 用于与 Zabbix API 交互的方法名称
4
+ # 告警动作资源;完整读取包含执行、恢复、确认操作及过滤条件。
5
+ class Actions < Resource
6
+ # 返回操作对象对应的 Zabbix API 方法前缀。
7
+ #
8
+ # @return [String]
6
9
  def method_name
7
10
  "action"
8
11
  end
9
12
 
10
- # 用于通过 Zabbix API 标识特定 Action 对象的 id 字段名称
11
- def identify
12
- "name"
13
- end
14
-
15
- # 从 API 获取完整/扩展的 Action 对象数据
13
+ # 获取操作及其执行、恢复、确认操作和过滤条件的完整数据。
14
+ #
15
+ # @param data [Hash] 包含识别字段及其值的查询条件
16
+ # @raise [ApiError] Zabbix API 返回业务错误时抛出
17
+ # @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
18
+ # @return [Array<Hash>] 匹配的操作完整数据
16
19
  def get_full_data(data)
17
- log "[DEBUG] 调用 get_full_data,参数为:#{data.inspect}"
18
-
19
- get_raw(
20
- {
21
- filter: {
20
+ @client.api_request(
21
+ method: "#{method_name}.get",
22
+ params: {
23
+ filter: {
22
24
  identify.to_sym => data[identify.to_sym]
23
25
  },
24
- output: "extend",
25
- selectOperations: "extend",
26
- selectRecoveryOperations: "extend",
26
+ output: "extend",
27
+ selectOperations: "extend",
28
+ selectRecoveryOperations: "extend",
27
29
  selectAcknowledgeOperations: "extend",
28
- selectFilter: "extend"
30
+ selectFilter: "extend"
29
31
  }
30
32
  )
31
33
  end
@@ -1,32 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Applications < Basic
5
- # 用于通过 Zabbix API 与 Applications 交互的方法名称
4
+ # 应用集以 hostid + name 定位;端点是否可用由目标 Zabbix 版本决定。
5
+ class Applications < Resource
6
+ # 返回应用集对象对应的 Zabbix API 方法前缀。
7
+ #
8
+ # @return [String]
6
9
  def method_name
7
10
  "application"
8
11
  end
9
12
 
10
- # 用于通过 Zabbix API 标识特定 Application 对象的 id 字段名称
11
- def identify
12
- "name"
13
- end
14
-
15
- # 通过 Zabbix API 获取或创建 Application 对象
16
- def get_or_create(data)
17
- log "[DEBUG] 调用 get_or_create,参数为:#{data.inspect}"
18
-
19
- if (id = get_id(name: data[:name], hostid: data[:hostid]))
20
- id
21
- else
22
- create(data)
23
- end
24
- end
25
-
26
- # 通过 Zabbix API 创建或更新 Application 对象
27
- def create_or_update(data)
28
- applicationid = get_id(name: data[:name], hostid: data[:hostid])
29
- applicationid ? update(data.merge(applicationid: applicationid)) : create(data)
13
+ # 生成由应用集名称和所属主机构成的稳定查询条件。
14
+ # @param data [Hash] 包含 name 和 hostid 的应用集属性
15
+ # @return [Hash] 应用集唯一查询条件
16
+ def identity_filter(data)
17
+ attributes = data.deep_symbolize_keys
18
+ { name: attributes.fetch(:name), hostid: attributes.fetch(:hostid) }
30
19
  end
31
20
  end
32
21
  end
@@ -1,28 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Configurations < Basic
5
- # 用于标识返回结果是否为数组
6
- def array_flag
7
- true
8
- end
9
-
10
- # 用于通过 Zabbix API 与 Configurations 交互的方法名称
4
+ # 原生配置导入/导出入口;导入可能修改多个远端对象,不提供本地回滚。
5
+ class Configurations < Resource
6
+ # 返回配置对象对应的 Zabbix API 方法前缀。
7
+ #
8
+ # @return [String]
11
9
  def method_name
12
10
  "configuration"
13
11
  end
14
12
 
15
- # 用于通过 Zabbix API 标识特定 Configuration 对象的 id 字段名称
13
+ # 返回配置对象用于业务识别的字段名。
14
+ #
15
+ # @return [String]
16
16
  def identify
17
17
  "host"
18
18
  end
19
19
 
20
- # 使用 Zabbix API 导出配置数据
20
+ # 通过 Zabbix API 导出配置数据。
21
+ #
22
+ # @param data [Hash] 配置导出参数
23
+ # @raise [ApiError] Zabbix API 返回业务错误时抛出
24
+ # @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
25
+ # @return [String] 服务端按指定格式序列化的配置内容
21
26
  def export(data)
22
27
  @client.api_request(method: "configuration.export", params: data)
23
28
  end
24
29
 
25
- # 使用 Zabbix API 导入配置数据
30
+ # 通过 Zabbix API 导入配置数据。
31
+ #
32
+ # @param data [Hash] 配置导入参数及内容
33
+ # @raise [ApiError] Zabbix API 返回业务错误时抛出
34
+ # @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
35
+ # @return [Boolean] 服务端确认的导入结果
26
36
  def import(data)
27
37
  @client.api_request(method: "configuration.import", params: data)
28
38
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ZabbixManager
4
+ # 网络发现规则(drule),区别于主机内的低级发现(discoveryrule)。
5
+ class DiscoveryRules < Resource
6
+ # 返回网络发现规则对应的 Zabbix API 方法前缀。
7
+ #
8
+ # @return [String]
9
+ def method_name
10
+ "drule"
11
+ end
12
+
13
+ # 返回创建网络发现规则时使用的默认周期和启用状态。
14
+ #
15
+ # @return [Hash] 网络发现规则默认属性
16
+ def default_options
17
+ {
18
+ delay: "1h",
19
+ status: 0
20
+ }
21
+ end
22
+ end
23
+ end
@@ -1,39 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- # BaseError 是 ZabbixManager 模块中处理异常的基类
5
- class BaseError < RuntimeError
6
- # 用于存储响应对象
7
- attr_accessor :response
8
- # 用于存储 Zabbix API 错误信息
9
- attr_accessor :error
10
- # 用于存储格式化后的错误消息
11
- attr_accessor :error_message
4
+ # 表示调用方输入或配置无效。
5
+ class Invalid < ArgumentError; end
12
6
 
13
- # 初始化异常对象
14
- def initialize(message, response = nil)
7
+ # 表示 Zabbix JSON-RPC 返回的业务错误或无效响应。
8
+ class ApiError < StandardError
9
+ attr_reader :response
10
+
11
+ # 保存经过脱敏的远端响应,便于调用方诊断。
12
+ # @return [ApiError]
13
+ def initialize(message = nil, response = nil)
15
14
  super(message)
16
15
  @response = response
17
- set_error! if @response
18
16
  end
17
+ end
19
18
 
20
- private
19
+ # 表示资源不唯一、身份冲突或无法安全收敛。
20
+ class Conflict < ApiError; end
21
21
 
22
- # 从响应中提取 Zabbix API 错误信息
23
- def set_error!
24
- @error = @response["error"]
25
- @error_message = "#{@error["message"]}: #{@error["data"]}"
26
- rescue StandardError
27
- @error = nil
28
- @error_message = nil
29
- end
30
- end
22
+ # 表示 HTTP 状态或传输层失败。
23
+ class TransportError < StandardError; end
31
24
 
32
- # ZbxError 是 ZabbixManager 模块中处理 Zabbix API 异常的类
33
- class ZbxError < BaseError
34
- end
25
+ # 响应无法确认远端操作是否已经完成。
26
+ class ProtocolError < TransportError; end
35
27
 
36
- # HttpError 是 ZabbixManager 模块中处理 HTTP 异常的类
37
- class HttpError < BaseError
38
- end
28
+ # 表示远端可能已完成写入,调用方不得自动重放。
29
+ class ResultUnknown < TransportError; end
39
30
  end
@@ -1,13 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Events < Basic
5
- # 用于通过 Zabbix API 与 Events 交互的方法名称
4
+ # 原生事件查询入口;按当前客户端凭据可见范围返回服务端记录。
5
+ class Events < Resource
6
+ # 返回事件对象对应的 Zabbix API 方法前缀。
7
+ #
8
+ # @return [String]
6
9
  def method_name
7
10
  "event"
8
11
  end
9
12
 
10
- # 用于通过 Zabbix API 标识特定 Event 对象的 id 字段名称
13
+ # 返回事件对象用于业务识别的字段名。
14
+ #
15
+ # @return [String]
11
16
  def identify
12
17
  "name"
13
18
  end