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
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Items < Basic
4
+ # 监控项查询与写入;通用 CRUD 使用名称,专用 upsert 使用 hostid + key_。
5
+ class Items < Resource
5
6
  DEFAULT_OPTIONS = {
6
7
  delay: "1m",
7
8
  history: "1h",
@@ -19,13 +20,6 @@ class ZabbixManager
19
20
  "item"
20
21
  end
21
22
 
22
- # 使用名称作为通用 CRUD 的业务标识。
23
- #
24
- # @return [String]
25
- def identify
26
- "name"
27
- end
28
-
29
23
  # 返回创建监控项时的克制默认值。
30
24
  #
31
25
  # @return [Hash]
@@ -35,10 +29,10 @@ class ZabbixManager
35
29
 
36
30
  # 使用主机和名称组成通用 CRUD 的查询边界。
37
31
  #
38
- # @param data [Hash] Needs to include name and hostid to properly identify Items via Zabbix API
39
- # @raise [ApiError] Error returned when there is a problem with the Zabbix API call.
40
- # @raise [TransportError] Error raised when HTTP status from Zabbix Server response is not a 200 OK.
41
- # @return [Integer] Zabbix object id
32
+ # @param data [Hash] 包含 name 和 hostid 的监控项属性
33
+ # @raise [ApiError] Zabbix API 明确返回业务错误
34
+ # @raise [TransportError] HTTP 或网络请求失败,可能无法确认远端结果
35
+ # @return [Hash] 名称和所属主机组成的精确过滤条件
42
36
  def identity_filter(data)
43
37
  attributes = data.deep_symbolize_keys
44
38
  { name: attributes.fetch(:name), hostid: attributes.fetch(:hostid) }
@@ -59,7 +53,7 @@ class ZabbixManager
59
53
  # 按主机和稳定 key 查询唯一监控项。
60
54
  # @return [Hash, nil]
61
55
  def find_by_key(hostid:, key:)
62
- result = for_host(hostid, keys: key, output: ["itemid", "key_", "name"])
56
+ result = for_host(hostid, keys: key, output: "extend", select_preprocessing: "extend")
63
57
  raise Conflict, "multiple items use key #{key} on host #{hostid}" if result.length > 1
64
58
 
65
59
  result.first
@@ -68,25 +62,11 @@ class ZabbixManager
68
62
  # 按 hostid + key_ 幂等创建或更新监控项。
69
63
  # @return [Integer]
70
64
  def upsert_by_key(data)
71
- attributes = validate_item!(data)
72
-
73
- current = find_by_key(hostid: attributes[:hostid], key: attributes[:key_])
74
- if current
75
- itemid = current.fetch("itemid")
76
- @client.api_request(
77
- method: "item.update",
78
- params: attributes.except(:hostid).merge(itemid: itemid)
79
- )
80
- itemid.to_i
81
- else
82
- create_attributes = default_options.merge(attributes)
83
- validate_create_item!(create_attributes)
84
- result = @client.api_request(method: "item.create", params: create_attributes)
85
- result.fetch("itemids").first.to_i
86
- end
65
+ apply_item(*plan_item(validate_item!(data)))
87
66
  end
88
67
 
89
68
  # 先校验整批数据,再按稳定 key 逐项幂等写入。
69
+ # @yieldparam effective [Array<Hash>] 合并已有配置或创建默认值后的有效属性;块失败时不写入
90
70
  # @return [Array<Integer>]
91
71
  def upsert_many(collection)
92
72
  items = Array(collection).map { |data| validate_item!(data) }
@@ -94,28 +74,40 @@ class ZabbixManager
94
74
  duplicate = identities.tally.find { |_identity, count| count > 1 }&.first
95
75
  raise Invalid, "duplicate hostid + key_ identity #{duplicate.join(":")}" if duplicate
96
76
 
97
- items.map { |item| upsert_by_key(item) }
77
+ plans = items.map { |item| plan_item(item) }
78
+ if block_given?
79
+ effective = plans.map do |attributes, current|
80
+ if current && !%w[type value_type].all? { |field| current.key?(field) }
81
+ raise ProtocolError, "item.get must include type and value_type for effective configuration validation"
82
+ end
83
+
84
+ current ? current.deep_symbolize_keys.merge(attributes).deep_dup : attributes.deep_dup
85
+ end
86
+ yield effective
87
+ end
88
+ plans.map { |attributes, current| apply_item(attributes, current) }
98
89
  end
99
90
 
100
91
  # 批量启用或停用监控项。
101
92
  # @return [Array<Integer>]
102
93
  def set_status(hostid:, itemids:, enabled:)
103
- ids = normalized_ids(itemids, "itemids")
94
+ validate_boolean!(enabled, "enabled")
95
+ ids = normalized_ids(itemids)
104
96
  verify_host_ownership!(hostid, ids)
105
97
  result = @client.api_request(
106
98
  method: "item.update",
107
99
  params: ids.map { |itemid| { itemid: itemid, status: enabled ? 0 : 1 } }
108
100
  )
109
- Array(result.fetch("itemids")).map(&:to_i)
101
+ response_ids(result, expected: ids)
110
102
  end
111
103
 
112
104
  # 批量删除明确指定的监控项。
113
105
  # @return [Array<Integer>]
114
106
  def delete_many(hostid:, itemids:)
115
- ids = normalized_ids(itemids, "itemids")
107
+ ids = normalized_ids(itemids)
116
108
  verify_host_ownership!(hostid, ids)
117
109
  result = @client.api_request(method: "item.delete", params: ids)
118
- Array(result.fetch("itemids")).map(&:to_i)
110
+ response_ids(result, expected: ids)
119
111
  end
120
112
 
121
113
  # 返回主机中可能表示接口流量的已启用监控项。
@@ -127,7 +119,7 @@ class ZabbixManager
127
119
  params: {
128
120
  hostids: [hostid],
129
121
  monitored: true,
130
- output: %w[itemid hostid name key_ snmp_oid value_type status units],
122
+ output: %w[itemid hostid name key_ type snmp_oid value_type status units],
131
123
  selectPreprocessing: "extend",
132
124
  sortfield: "name",
133
125
  sortorder: "ASC"
@@ -143,7 +135,7 @@ class ZabbixManager
143
135
  raise Invalid, "dns_name is required" if name.blank?
144
136
  raise Invalid, "dns_name contains unsupported item key delimiters" if name.match?(/[\[\],]/)
145
137
 
146
- itemid = upsert_by_key(
138
+ upsert_by_key(
147
139
  hostid: hostid,
148
140
  interfaceid: interfaceid,
149
141
  name: "【DNS域名解析监控】#{name}",
@@ -154,72 +146,84 @@ class ZabbixManager
154
146
  history: "90d",
155
147
  timeout: "3s"
156
148
  )
157
- log "Ensured DNS monitoring item for #{name}"
158
- itemid
159
- rescue StandardError => e
160
- log "Failed to ensure DNS monitoring item: #{e.class}"
161
- raise
162
149
  end
163
150
 
164
151
  private
165
152
 
166
- # 规范化并校验幂等写入所需字段。
167
- # @return [Hash]
168
- # @api private
169
- def validate_item!(data)
170
- attributes = data.deep_symbolize_keys
171
- raise Invalid, "hostid is required" if attributes[:hostid].blank?
172
- raise Invalid, "key_ is required" if attributes[:key_].blank?
173
- raise Invalid, "name is required" if attributes[:name].blank?
153
+ # 创建必填字段必须在整批写入开始前校验。
154
+ def plan_item(attributes)
155
+ current = find_by_key(hostid: attributes[:hostid], key: attributes[:key_])
156
+ validate_item_type!(attributes[:type]) if attributes.key?(:type)
157
+ response_identifier(current["itemid"]) if current
158
+ unless current
159
+ attributes = default_options.merge(attributes)
160
+ validate_create_item!(attributes)
161
+ end
162
+ [attributes, current]
163
+ end
174
164
 
175
- attributes
165
+ def apply_item(attributes, current)
166
+ if current
167
+ itemid = current.fetch("itemid")
168
+ result = @client.api_request(method: "item.update", params: attributes.except(:hostid).merge(itemid: itemid))
169
+ response_id(result, expected: [itemid])
170
+ else
171
+ result = @client.api_request(method: "item.create", params: attributes)
172
+ response_id(result)
176
173
  end
174
+ end
177
175
 
178
- # 校验 item.create 的通用必填字段和 SNMP 条件字段。
179
- def validate_create_item!(attributes)
180
- raise Invalid, "type is required when creating an item" if attributes[:type].blank?
181
- raise Invalid, "value_type is required when creating an item" if attributes[:value_type].blank?
176
+ # 规范化并校验幂等写入所需字段。
177
+ # @return [Hash]
178
+ # @api private
179
+ def validate_item!(data)
180
+ attributes = data.deep_symbolize_keys
181
+ raise Invalid, "hostid is required" if attributes[:hostid].blank?
182
+ raise Invalid, "key_ is required" if attributes[:key_].blank?
183
+ raise Invalid, "name is required" if attributes[:name].blank?
182
184
 
183
- type = Integer(attributes[:type])
184
- raise Invalid, "unsupported item type #{type}" unless ITEM_TYPES.include?(type)
185
+ attributes
186
+ end
185
187
 
186
- if REQUIRED_INTERFACE_TYPES.include?(type) && attributes[:interfaceid].blank?
187
- raise Invalid, "interfaceid is required for item type #{type}"
188
- end
189
- if REQUIRED_PARAMS_TYPES.include?(type) && attributes[:params].blank?
190
- raise Invalid, "params is required for item type #{type}"
191
- end
188
+ # 校验 item.create 的通用必填字段和 SNMP 条件字段。
189
+ def validate_create_item!(attributes)
190
+ raise Invalid, "type is required when creating an item" if attributes[:type].blank?
191
+ raise Invalid, "value_type is required when creating an item" if attributes[:value_type].blank?
192
192
 
193
- raise Invalid,
194
- "master_itemid is required for a dependent item" if type == 18 && attributes[:master_itemid].blank?
195
- raise Invalid, "url is required for an HTTP item" if type == 19 && attributes[:url].blank?
196
- return unless type == 20
193
+ type = validate_item_type!(attributes[:type])
197
194
 
198
- raise Invalid, "snmp_oid is required for an SNMP item" if attributes[:snmp_oid].blank?
199
- rescue ArgumentError, TypeError
200
- raise Invalid, "type must be a supported integer"
195
+ if REQUIRED_INTERFACE_TYPES.include?(type) && attributes[:interfaceid].blank?
196
+ raise Invalid, "interfaceid is required for item type #{type}"
197
+ end
198
+ if REQUIRED_PARAMS_TYPES.include?(type) && attributes[:params].blank?
199
+ raise Invalid, "params is required for item type #{type}"
201
200
  end
202
201
 
203
- # 回查监控项归属,阻止共享高权限令牌跨主机修改。
204
- def verify_host_ownership!(hostid, ids)
205
- raise Invalid, "hostid is required" if hostid.blank?
202
+ raise Invalid,
203
+ "master_itemid is required for a dependent item" if type == 18 && attributes[:master_itemid].blank?
204
+ raise Invalid, "url is required for an HTTP item" if type == 19 && attributes[:url].blank?
205
+ return unless type == 20
206
206
 
207
- result = @client.api_request(
208
- method: "item.get", params: { hostids: hostid, itemids: ids, output: ["itemid"] }
209
- )
210
- owned_ids = result.map { |item| item.fetch("itemid").to_s }
211
- foreign_ids = ids - owned_ids
212
- raise Conflict, "items do not belong to host #{hostid}: #{foreign_ids.join(", ")}" if foreign_ids.any?
213
- end
207
+ raise Invalid, "snmp_oid is required for an SNMP item" if attributes[:snmp_oid].blank?
208
+ end
214
209
 
215
- # 统一批量 ID 并拒绝空集合。
216
- # @return [Array<String>]
217
- # @api private
218
- def normalized_ids(values, name)
219
- ids = Array(values).filter_map { |value| value.to_s.strip.presence }.uniq
220
- raise Invalid, "#{name} are required" if ids.empty?
210
+ def validate_item_type!(value)
211
+ type = integer_attribute(value, "type")
212
+ raise Invalid, "unsupported item type #{type}" unless ITEM_TYPES.include?(type)
221
213
 
222
- ids
223
- end
214
+ type
215
+ end
216
+
217
+ # 回查监控项归属,阻止共享高权限令牌跨主机修改。
218
+ def verify_host_ownership!(hostid, ids)
219
+ raise Invalid, "hostid is required" if hostid.blank?
220
+
221
+ result = @client.api_request(
222
+ method: "item.get", params: { hostids: hostid, itemids: ids, output: ["itemid"] }
223
+ )
224
+ owned_ids = result.map { |item| item.fetch("itemid").to_s }
225
+ foreign_ids = ids - owned_ids
226
+ raise Conflict, "items do not belong to host #{hostid}: #{foreign_ids.join(", ")}" if foreign_ids.any?
227
+ end
224
228
  end
225
229
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Maintenance < Basic
4
+ # 原生维护期资源;时间段、目标主机和群组由调用方显式定义。
5
+ class Maintenance < Resource
5
6
  # 返回维护期对象对应的 Zabbix API 方法前缀。
6
7
  #
7
8
  # @return [String]
@@ -1,19 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Mediatypes < Basic
4
+ # 原生通知媒介资源;仅提供最小默认值,不推断端点、凭据或版本字段。
5
+ class MediaTypes < Resource
5
6
  # 返回媒介类型对象对应的 Zabbix API 方法前缀。
6
7
  # @return [String] API 方法前缀
7
8
  def method_name
8
9
  "mediatype"
9
10
  end
10
11
 
11
- # 返回媒介类型用于业务识别的字段名。
12
- # @return [String] 识别字段名
13
- def identify
14
- "name"
15
- end
16
-
17
12
  # 返回媒介类型的最小默认属性;端点和凭据等版本相关字段由调用方显式提供。
18
13
  # @return [Hash] 媒介类型默认属性
19
14
  def default_options
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Problems < Basic
4
+ # 原生问题查询与事件确认;问题身份使用 eventid,确认动作属于远端写入。
5
+ class Problems < Resource
5
6
  # 返回问题对象对应的 Zabbix API 方法前缀。
6
7
  #
7
8
  # @return [String]
@@ -9,45 +10,18 @@ class ZabbixManager
9
10
  "problem"
10
11
  end
11
12
 
12
- # 返回问题对象用于业务识别的字段名。
13
- #
14
- # @return [String]
15
- def identify
16
- "name"
17
- end
18
-
19
- # 返回问题对象的兼容 ID 字段名;问题对象本身没有独立的唯一标识。
13
+ # 使用触发问题的事件 ID 作为对象身份。
20
14
  #
21
15
  # @return [String]
22
16
  def key
23
- "problemid"
17
+ "eventid"
24
18
  end
25
19
 
26
- # 返回问题对象的复数兼容 ID 字段名。
20
+ # 返回事件 ID 集合字段名。
27
21
  #
28
22
  # @return [String]
29
23
  def keys
30
- "problemids"
31
- end
32
-
33
- # 按识别字段查询问题对象的完整数据。
34
- #
35
- # @param data [Hash] 包含问题识别字段及其值的查询条件
36
- # @raise [ApiError] Zabbix API 返回业务错误时抛出
37
- # @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
38
- # @return [Hash] 匹配的问题数据
39
- def dump_by_id(data)
40
- log "[DEBUG] Call dump_by_id with parameters: #{data.inspect}"
41
-
42
- @client.api_request(
43
- method: "problem.get",
44
- params: {
45
- filter: {
46
- identify.to_sym => data[identify.to_sym]
47
- },
48
- output: "extend"
49
- }
50
- )
24
+ "eventids"
51
25
  end
52
26
 
53
27
  # 获取问题及其确认、标签和抑制信息,并支持附加查询参数。
@@ -55,10 +29,8 @@ class ZabbixManager
55
29
  # @param data [Hash] 问题过滤条件及附加 API 参数
56
30
  # @raise [ApiError] Zabbix API 返回业务错误时抛出
57
31
  # @raise [TransportError] Zabbix 服务端返回非成功 HTTP 状态时抛出
58
- # @return [Hash] 匹配的问题完整数据
32
+ # @return [Array<Hash>] 匹配的问题完整数据
59
33
  def get_full_data(data)
60
- log "[DEBUG] Call get_full_data with parameters: #{data.inspect}"
61
-
62
34
  data = data.deep_symbolize_keys
63
35
  params = {
64
36
  recent: false,
@@ -92,15 +64,14 @@ class ZabbixManager
92
64
  # @param message [String, nil] 可选确认消息
93
65
  # @return [Hash] 事件确认结果
94
66
  def acknowledge_events(eventids, action: 2, message: nil)
95
- ids = Array(eventids).map(&:to_s).reject(&:blank?).uniq
96
- raise Invalid, "eventids are required" if ids.empty?
67
+ ids = normalized_ids(eventids)
97
68
 
98
- @client.api_request(
69
+ result = @client.api_request(
99
70
  method: "event.acknowledge",
100
71
  params: { eventids: ids, action: action, message: message }.compact
101
72
  )
73
+ response_ids(result, expected: ids)
74
+ result
102
75
  end
103
-
104
- alias ack_event acknowledge_events
105
76
  end
106
77
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Proxies < Basic
4
+ # 原生代理资源;按服务器版本选择 name 或 host 作为名称字段。
5
+ class Proxies < Resource
5
6
  # 返回 Zabbix API 中代理对象的方法名前缀。
6
7
  #
7
8
  # @return [String] 代理对象的方法名前缀
@@ -13,18 +14,7 @@ class ZabbixManager
13
14
  #
14
15
  # @return [String] 代理对象的标识字段名
15
16
  def identify
16
- "host"
17
- end
18
-
19
- # 通过 Zabbix API 删除指定代理,并返回首个已删除代理的 ID。
20
- #
21
- # @param data [Array] 要删除的 proxyid 数组
22
- # @raise [ApiError] Zabbix API 返回业务错误时抛出
23
- # @raise [TransportError] Zabbix 服务返回非成功 HTTP 状态时抛出
24
- # @return [Integer, nil] 已删除代理的 ID,无结果时返回 nil
25
- def delete(data)
26
- result = @client.api_request(method: "proxy.delete", params: data)
27
- result.empty? ? nil : result["proxyids"][0].to_i
17
+ Gem::Version.new(@client.api_version) >= Gem::Version.new("7.0") ? "name" : "host"
28
18
  end
29
19
 
30
20
  # 检查当前凭证是否可读取指定代理。
@@ -58,9 +48,9 @@ class ZabbixManager
58
48
  result = @client.api_request(
59
49
  method: "proxy.get",
60
50
  params: {
61
- output: %w[proxyid host],
51
+ output: ["proxyid", identify],
62
52
  filter: {
63
- host: proxy
53
+ identify.to_sym => proxy
64
54
  }
65
55
  }
66
56
  )
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ZabbixManager
4
+ # Zabbix 7.0 起提供的原生代理组资源。
5
+ class ProxyGroups < Resource
6
+ # @return [String] 原生 API 方法前缀
7
+ def method_name
8
+ "proxygroup"
9
+ end
10
+
11
+ # @return [String] 原生代理组 ID 字段
12
+ def key
13
+ "proxy_groupid"
14
+ end
15
+ end
16
+ end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Roles < Basic
4
+ # 角色查询与权限规则更新;权限内容由调用方定义,服务端负责权限校验。
5
+ class Roles < Resource
5
6
  # 返回 Zabbix API 中角色对象的方法名前缀。
6
7
  #
7
8
  # @return [String] 角色对象的方法名前缀
@@ -9,20 +10,6 @@ class ZabbixManager
9
10
  "role"
10
11
  end
11
12
 
12
- # 返回角色对象的主键字段名。
13
- #
14
- # @return [String] 角色对象的主键字段名
15
- def key
16
- "roleid"
17
- end
18
-
19
- # 返回用于唯一识别角色的业务字段名。
20
- #
21
- # @return [String] 角色对象的业务标识字段名
22
- def identify
23
- "name"
24
- end
25
-
26
13
  # 更新指定角色的权限规则。
27
14
  #
28
15
  # @param data [Hash] 包含 roleid 和 rules 的角色规则数据
@@ -34,6 +21,8 @@ class ZabbixManager
34
21
  raise Invalid, "roleid is required" if attributes[:roleid].blank?
35
22
  raise Invalid, "rules is required" if attributes[:rules].blank?
36
23
 
24
+ normalized_ids([attributes[:roleid]])
25
+
37
26
  result = @client.api_request(
38
27
  method: "role.update",
39
28
  params: {
@@ -41,24 +30,29 @@ class ZabbixManager
41
30
  rules: attributes[:rules]
42
31
  }
43
32
  )
44
- result.fetch("roleids").first.to_i
33
+ response_id(result, expected: [attributes[:roleid]])
45
34
  end
46
35
 
47
36
  # 按角色 ID 获取角色详情及完整规则。
48
37
  #
49
- # @param data [Hash] 包含 id 的查询参数
38
+ # @param data [Hash] 包含 roleid 的查询参数;旧 id 引用仍可使用,但不得矛盾
50
39
  # @raise [ApiError] Zabbix API 返回业务错误时抛出
51
40
  # @raise [TransportError] Zabbix 服务返回非成功 HTTP 状态时抛出
52
41
  # @return [Array<Hash>] 匹配的角色详情
53
42
  def dump_by_id(data)
54
- log "[DEBUG] Call dump_by_id with parameters: #{data.inspect}"
43
+ attributes = data.deep_symbolize_keys
44
+ if attributes.key?(:roleid) && attributes.key?(:id) &&
45
+ normalized_ids([attributes[:roleid]]) != normalized_ids([attributes[:id]])
46
+ raise Invalid, "roleid and id disagree"
47
+ end
55
48
 
49
+ id = normalized_ids([attributes.fetch(:roleid) { attributes[:id] }]).first
56
50
  @client.api_request(
57
51
  method: "role.get",
58
52
  params: {
59
53
  output: "extend",
60
54
  selectRules: "extend",
61
- roleids: data[:id]
55
+ roleids: id
62
56
  }
63
57
  )
64
58
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Screens < Basic
4
+ # 旧版聚合图形的网格创建入口;目标服务器须提供 screen API。
5
+ class Screens < Resource
5
6
  # 以下资源类型取自 frontends/php/include/defines.inc.php。
6
7
  # SCREEN_RESOURCE_GRAPH => 0,
7
8
  # SCREEN_RESOURCE_SIMPLE_GRAPH => 1,
@@ -28,24 +29,6 @@ class ZabbixManager
28
29
  "screen"
29
30
  end
30
31
 
31
- # 返回用于唯一识别聚合图形的业务字段名。
32
- #
33
- # @return [String] 聚合图形的业务标识字段名
34
- def identify
35
- "name"
36
- end
37
-
38
- # 删除指定聚合图形并返回首个已删除对象的 ID。
39
- #
40
- # @param data [String, Array] 要删除的聚合图形 ID
41
- # @raise [ApiError] Zabbix API 返回业务错误时抛出
42
- # @raise [TransportError] Zabbix 服务返回非成功 HTTP 状态时抛出
43
- # @return [Integer, nil] 已删除聚合图形的 ID,无结果时返回 nil
44
- def delete(data)
45
- result = @client.api_request(method: "screen.delete", params: [data])
46
- result.empty? ? nil : result["screenids"][0].to_i
47
- end
48
-
49
32
  # 按名称获取聚合图形,不存在时按图形 ID 网格化创建。
50
33
  #
51
34
  # @param data [Hash] 包含 screen_name、graphids 及可选布局参数
@@ -97,17 +80,15 @@ class ZabbixManager
97
80
 
98
81
  private
99
82
 
100
- # 将横向格数转换为正整数,非法值直接拒绝。
101
- #
102
- # @param value [Object] 待校验的横向格数
103
- # @return [Integer] 正整数横向格数
104
- def positive_hsize(value)
105
- size = Integer(value)
106
- raise Invalid unless size.positive?
83
+ # 将横向格数转换为正整数,非法值直接拒绝。
84
+ #
85
+ # @param value [Object] 待校验的横向格数
86
+ # @return [Integer] 正整数横向格数
87
+ def positive_hsize(value)
88
+ size = integer_attribute(value, "hsize")
89
+ raise Invalid, "hsize must be a positive integer" unless size.positive?
107
90
 
108
- size
109
- rescue ArgumentError, TypeError
110
- raise Invalid, "hsize must be a positive integer"
111
- end
91
+ size
92
+ end
112
93
  end
113
94
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
- class Scripts < Basic
4
+ # 远端脚本执行与可用脚本查询;执行请求可能产生 API 之外的设备副作用。
5
+ class Scripts < Resource
5
6
  # 返回 Zabbix API 中脚本对象的方法名前缀。
6
7
  #
7
8
  # @return [String] 脚本对象的方法名前缀
@@ -9,13 +10,6 @@ class ZabbixManager
9
10
  "script"
10
11
  end
11
12
 
12
- # 返回用于唯一识别脚本的业务字段名。
13
- #
14
- # @return [String] 脚本对象的业务标识字段名
15
- def identify
16
- "name"
17
- end
18
-
19
13
  # 在指定主机上执行 Zabbix 脚本。
20
14
  #
21
15
  # 示例:
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ZabbixManager
4
+ # 已连接服务器的版本快照;复用 Client 初始化结果,不发起额外版本查询。
4
5
  class Server
5
6
  # 返回连接对应的 Zabbix API 版本。
6
7
  #