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,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ZabbixManager
4
- class Basic
5
- # 按标识字段从 Zabbix API 获取对象完整数据。
6
- #
7
- # @param data [Hash] 包含对象标识字段及其值
8
- # @raise [ApiError] Zabbix API 调用失败时抛出
9
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
10
- # @return [Hash] 对象完整数据
11
- def get(data)
12
- get_full_data(data)
13
- end
14
-
15
- # 通过 Zabbix API 创建对象。
16
- #
17
- # @param data [Hash] 待创建的对象属性
18
- # @raise [ApiError] Zabbix API 调用失败时抛出
19
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
20
- # @return [Integer] 创建单个对象时返回对象 ID
21
- # @return [Boolean] 创建多个对象时返回操作结果
22
- def add(data)
23
- create(data)
24
- end
25
-
26
- # 通过 Zabbix API 删除对象。
27
- #
28
- # @param data [Hash] 包含对象标识字段及其值
29
- # @raise [ApiError] Zabbix API 调用失败时抛出
30
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
31
- # @return [Integer] 删除单个对象时返回对象 ID
32
- # @return [Boolean] 删除多个对象时返回操作结果
33
- def destroy(data)
34
- delete(data)
35
- end
36
-
37
- # 返回子类对应的 Zabbix API 方法名;由具体资源类实现。
38
- #
39
- # @return [String, nil] API 方法名
40
- def method_name; end
41
- end
42
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ZabbixManager
4
- class Basic
5
- # 将调试信息交给客户端结构化日志,并移除可能包含请求参数的片段。
6
- #
7
- # @param message [String] 待记录的调试信息
8
- # @return [void]
9
- def log(message)
10
- return unless @client.options[:debug]
11
-
12
- raw_message = message.to_s
13
- safe_message = if raw_message.start_with?("[DEBUG]")
14
- raw_message[/\A\[DEBUG\]\s+Call\s+[a-z_]+/i] || "[DEBUG] domain operation"
15
- else
16
- raw_message
17
- end
18
- @client.log(:debug, "domain.operation", message: safe_message)
19
- end
20
-
21
- # 比较实际哈希是否包含期望哈希中的全部键值。
22
- #
23
- # @param first_hash [Hash] 实际数据
24
- # @param second_hash [Hash] 期望数据
25
- # @return [Boolean] 是否匹配
26
- def hash_equals?(first_hash, second_hash)
27
- actual = normalize_hash(first_hash)
28
- expected = normalize_hash(second_hash)
29
- actual.slice(*expected.keys) == expected
30
- end
31
-
32
- # 将哈希值递归规范为字符串,并忽略 hostid。
33
- #
34
- # @param hash [Hash] 待规范化的哈希
35
- # @return [Hash] 规范化后的副本
36
- def normalize_hash(hash)
37
- hash.deep_symbolize_keys.except(:hostid).deep_transform_values(&:to_s)
38
- end
39
-
40
- # 从 API 结果中解析单个对象 ID,或透传布尔结果。
41
- #
42
- # @param data [Hash, Boolean] API 返回结果
43
- # @return [Integer, Boolean, nil] 对象 ID、布尔结果或空值
44
- def parse_keys(data)
45
- case data
46
- when Hash
47
- data.empty? ? nil : data[keys][0].to_i
48
- when TrueClass
49
- true
50
- when FalseClass
51
- false
52
- end
53
- end
54
- end
55
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ZabbixManager
4
- class Basic
5
- # 使用 ZabbixManager 客户端初始化基础资源对象。
6
- #
7
- # @param client [ZabbixManager::Client] API 客户端
8
- # @return [ZabbixManager::Basic] 基础资源对象
9
- def initialize(client)
10
- @client = client
11
- end
12
-
13
- # 定义资源对应的 API 方法名占位,要求子类覆盖。
14
- #
15
- # @raise [ApiError] 基础类不能直接提供方法名时抛出
16
- # @return [String] API 方法名
17
- def method_name
18
- raise Invalid, "Can't call method_name here"
19
- end
20
-
21
- # 返回资源创建时使用的默认选项,子类可按需覆盖。
22
- #
23
- # @return [Hash] 默认选项
24
- def default_options
25
- {}
26
- end
27
-
28
- # 根据单数 ID 字段名生成 API 返回结果中的复数字段名。
29
- #
30
- # @return [String] 复数 ID 字段名
31
- def keys
32
- "#{key}s"
33
- end
34
-
35
- # 根据 API 方法名生成对象 ID 字段名。
36
- #
37
- # @return [String] 对象 ID 字段名
38
- def key
39
- "#{method_name}id"
40
- end
41
-
42
- # 定义资源业务标识字段占位,要求子类覆盖。
43
- #
44
- # @raise [ApiError] 基础类不能直接提供标识字段时抛出
45
- # @return [String] 业务标识字段名
46
- def identify
47
- raise Invalid, "Can't call identify here"
48
- end
49
- end
50
- end
@@ -1,239 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ZabbixManager
4
- class Basic
5
- # 合并默认选项后通过 Zabbix API 创建对象。
6
- #
7
- # @param data [Hash] 待创建的对象属性
8
- # @raise [ApiError] Zabbix API 调用失败时抛出
9
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
10
- # @return [Integer] 创建单个对象时返回对象 ID
11
- # @return [Boolean] 创建多个对象时返回操作结果
12
- def create(data)
13
- log "[DEBUG] Call create with parameters: #{data.inspect}"
14
-
15
- # 判断是否绑定默认选项并重新生成配置
16
- data_with_default = default_options.empty? ? data : default_options.merge(data)
17
- data_create = [data_with_default]
18
-
19
- # 调用实例方法
20
- result = @client.api_request(method: "#{method_name}.create", params: data_create)
21
- # 判断是否执行成功并返回结果
22
- parse_keys result
23
- end
24
-
25
- # 通过 Zabbix API 删除对象。
26
- #
27
- # @param data [Hash] 包含待删除对象的 ID 字段和值
28
- # @raise [ApiError] Zabbix API 调用失败时抛出
29
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
30
- # @return [Integer] 删除单个对象时返回对象 ID
31
- # @return [Boolean] 删除多个对象时返回操作结果
32
- def delete(data)
33
- log "[DEBUG] Call delete with parameters: #{data.inspect}"
34
-
35
- data_delete = [data]
36
- result = @client.api_request(method: "#{method_name}.delete", params: data_delete)
37
- parse_keys result
38
- end
39
-
40
- # 按业务标识查找对象,存在则更新,否则创建。
41
- #
42
- # @param data [Hash] 包含对象业务标识及待写入属性
43
- # @raise [ApiError] Zabbix API 调用失败时抛出
44
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
45
- # @return [Integer] 创建或更新后的对象 ID
46
- # @return [Boolean] 批量操作时返回操作结果
47
- def create_or_update(data)
48
- log "[DEBUG] Call create_or_update with parameters: #{data.inspect}"
49
-
50
- id = get_id(**identity_filter(data))
51
- id ? update(data.merge(key.to_sym => id)) : create(data)
52
- end
53
-
54
- # 在属性发生变化或强制更新时通过 Zabbix API 更新对象。
55
- #
56
- # @param data [Hash] 包含对象 ID 及待更新属性
57
- # @param force [Boolean] 属性一致时是否仍强制更新
58
- # @raise [ApiError] Zabbix API 调用失败时抛出
59
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
60
- # @return [Integer] 更新后的对象 ID
61
- # @return [Boolean] 批量操作时返回操作结果
62
- def update(data, force = false)
63
- log "[DEBUG] Call update with parameters: #{data.inspect}"
64
- dump = {}
65
- dump_by_id(key.to_sym => data[key.to_sym]).each do |item|
66
- dump = item.deep_symbolize_keys if item[key].to_i == data[key.to_sym].to_i
67
- end
68
- if hash_equals?(dump, data) && !force
69
- log "[DEBUG] Equal keys #{dump} and #{data}, skip update"
70
- data[key.to_sym].to_i
71
- else
72
- data_update = [data]
73
- result = @client.api_request(method: "#{method_name}.update", params: data_update)
74
- parse_keys result
75
- end
76
- end
77
-
78
- # 按业务标识从 Zabbix API 获取对象扩展数据。
79
- #
80
- # @param data [Hash] 包含对象业务标识字段及其值
81
- # @raise [ApiError] Zabbix API 调用失败时抛出
82
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
83
- # @return [Hash] 对象扩展数据
84
- def get_full_data(data)
85
- log "[DEBUG] Call get_full_data with parameters: #{data.inspect}"
86
-
87
- @client.api_request(
88
- method: "#{method_name}.get",
89
- params: {
90
- filter: {
91
- identify.to_sym => data[identify.to_sym]
92
- },
93
- output: "extend"
94
- }
95
- )
96
- end
97
-
98
- # 将调用方参数直接传给对应的 Zabbix get 方法。
99
- #
100
- # @param data [Hash] 原始查询参数
101
- # @raise [ApiError] Zabbix API 调用失败时抛出
102
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
103
- # @return [Hash] API 返回数据
104
- def get_raw(data)
105
- log "[DEBUG] Call get_raw with parameters: #{data.inspect}"
106
-
107
- @client.api_request(
108
- method: "#{method_name}.get",
109
- params: data
110
- )
111
- end
112
-
113
- # 按对象 ID 字段从 Zabbix API 获取扩展数据。
114
- #
115
- # @param data [Hash] 包含对象 ID 字段及其值
116
- # @raise [ApiError] Zabbix API 调用失败时抛出
117
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
118
- # @return [Hash] 对象扩展数据
119
- def dump_by_id(data)
120
- log "[DEBUG] Call dump_by_id with parameters: #{data.inspect}"
121
-
122
- @client.api_request(
123
- method: "#{method_name}.get",
124
- params: {
125
- filter: {
126
- key.to_sym => data[key.to_sym]
127
- },
128
- output: "extend"
129
- }
130
- )
131
- end
132
-
133
- # 获取当前资源的全部对象,并返回业务标识到 ID 的映射。
134
- #
135
- # @raise [ApiError] Zabbix API 调用失败时抛出
136
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
137
- # @return [Hash] 业务标识到对象 ID 的映射
138
- def all
139
- result = {}
140
- @client.api_request(
141
- method: "#{method_name}.get",
142
- params: { output: "extend" }
143
- ).each do |item|
144
- result[item[identify]] = item[key]
145
- end
146
- result
147
- end
148
-
149
- # 按业务标识精确查询对象 ID,并拒绝歧义结果。
150
- #
151
- # @param data [Hash] 业务标识过滤条件
152
- # @raise [ApiError] API 调用失败、缺少标识字段或结果不唯一时抛出
153
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
154
- # @return [Integer, nil] Zabbix 对象 ID,未找到时返回空值
155
- def get_id(data)
156
- log "[DEBUG] Call get_id with parameters: #{data.inspect}"
157
-
158
- data = data.deep_symbolize_keys
159
- # 缺少业务标识字段时立即终止查询
160
- name = data[identify.to_sym]
161
- raise Invalid, "#{identify} not supplied in call to get_id" if name.nil?
162
-
163
- result = @client.api_request(
164
- method: "#{method_name}.get",
165
- params: {
166
- filter: data,
167
- output: [key, identify]
168
- }
169
- )
170
- matches = result.select { |item| item[identify].to_s == name.to_s }
171
- raise Conflict, "multiple #{method_name} objects match #{identify}=#{name}" if matches.length > 1
172
-
173
- matches.first&.fetch(key, nil)&.to_i
174
- end
175
-
176
- # 按业务标识获取对象,不存在时创建。
177
- #
178
- # @param data [Hash] 包含对象业务标识及待创建属性
179
- # @raise [ApiError] Zabbix API 调用失败时抛出
180
- # @raise [TransportError] Zabbix 服务端返回非 200 状态时抛出
181
- # @return [Integer] Zabbix 对象 ID
182
- def get_or_create(data)
183
- log "[DEBUG] Call get_or_create with parameters: #{data.inspect}"
184
-
185
- unless (id = get_id(**identity_filter(data)))
186
- id = create(data)
187
- end
188
- id
189
- end
190
-
191
- # 提取通用获取或写入操作使用的远端业务标识。
192
- #
193
- # @param data [Hash] 对象属性
194
- # @return [Hash] 业务标识过滤条件
195
- def identity_filter(data)
196
- attributes = data.deep_symbolize_keys
197
- { identify.to_sym => attributes.fetch(identify.to_sym) }
198
- end
199
-
200
- # 使用原始参数直接创建 Zabbix 对象。
201
- #
202
- # @param data [Hash, Array] 原始创建参数
203
- # @return [Object] API 返回结果
204
- def create_raw(data)
205
- log "[DEBUG] Call create_raw with parameters: #{data.inspect}"
206
- # 请求创建数据
207
- @client.api_request(
208
- method: "#{method_name}.create",
209
- params: data
210
- )
211
- end
212
-
213
- # 使用原始参数直接更新 Zabbix 对象。
214
- #
215
- # @param data [Hash, Array] 原始更新参数
216
- # @return [Object] API 返回结果
217
- def update_raw(data)
218
- log "[DEBUG] Call update_raw with parameters: #{data.inspect}"
219
- # 请求创建数据
220
- @client.api_request(
221
- method: "#{method_name}.update",
222
- params: data
223
- )
224
- end
225
-
226
- # 使用原始参数直接删除 Zabbix 对象。
227
- #
228
- # @param data [Hash, Array] 原始删除参数
229
- # @return [Object] API 返回结果
230
- def delete_raw(data)
231
- log "[DEBUG] Call delete_raw with parameters: #{data.inspect}"
232
- # 请求创建数据
233
- @client.api_request(
234
- method: "#{method_name}.delete",
235
- params: data
236
- )
237
- end
238
- end
239
- end
@@ -1,189 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ZabbixManager
4
- # 封装高频使用的 Zabbix 主机接口查询与幂等更新。
5
- class HostInterfaces < Basic
6
- # 返回对应的 Zabbix API 模块名。
7
- # @return [String]
8
- def method_name
9
- "hostinterface"
10
- end
11
-
12
- # 返回接口对象的主键字段。
13
- # @return [String]
14
- def key
15
- "interfaceid"
16
- end
17
-
18
- # 使用接口 ID 作为通用查询标识。
19
- # @return [String]
20
- def identify
21
- "interfaceid"
22
- end
23
-
24
- # 查询指定主机的全部接口,可选择同时返回关联监控项。
25
- # @return [Array<Hash>]
26
- def for_host(hostid, select_items: nil)
27
- raise Invalid, "hostid is required" if hostid.blank?
28
-
29
- params = { hostids: hostid, output: "extend" }
30
- params[:selectItems] = select_items if select_items
31
- @client.api_request(method: "hostinterface.get", params: params)
32
- end
33
-
34
- # 规范化并校验接口定义,不执行远端查询或写入。
35
- # @return [Array<Hash>]
36
- def validate(interfaces)
37
- desired = Array.wrap(interfaces).map { |interface| normalize_definition(interface) }
38
- validate_definitions!(desired)
39
- desired
40
- end
41
-
42
- # 校验 host.create 中全部接口的创建必填合同。
43
- # @return [Array<Hash>]
44
- def validate_for_create(interfaces)
45
- validate(interfaces).each { |attributes| validate_create_definition!(attributes) }
46
- end
47
-
48
- # 幂等创建或更新一个主机的接口集合。
49
- # @return [Array<Integer>]
50
- def reconcile_for_host(hostid:, interfaces:)
51
- @client.with_upsert_lock("host-interfaces:#{hostid}") do
52
- plan = plan_for_host(hostid: hostid, interfaces: interfaces)
53
- apply_plan(hostid: hostid, plan: plan)
54
- end
55
- end
56
-
57
- # 删除明确指定的主机接口;关联监控项由 Zabbix 按官方规则处理。
58
- # @return [Array<Integer>]
59
- def delete_many(hostid:, interfaceids:)
60
- ids = Array(interfaceids).filter_map { |value| value.to_s.strip.presence }.uniq
61
- raise Invalid, "interfaceids are required" if ids.empty?
62
-
63
- owned_ids = for_host(hostid).map { |interface| interface.fetch("interfaceid").to_s }
64
- foreign_ids = ids - owned_ids
65
- raise Conflict, "interfaces do not belong to host #{hostid}: #{foreign_ids.join(", ")}" if foreign_ids.any?
66
-
67
- result = @client.api_request(method: "hostinterface.delete", params: ids)
68
- Array(result.fetch("interfaceids")).map(&:to_i)
69
- end
70
-
71
- private
72
-
73
- # 预先校验并生成仅供当前对象执行的接口变更计划。
74
- def plan_for_host(hostid:, interfaces:)
75
- desired = validate(interfaces)
76
- existing = for_host(hostid)
77
- desired.map { |attributes| [attributes, matching_interface(existing, attributes)] }
78
- end
79
-
80
- # 执行内部生成的接口变更计划,避免调用方伪造跨主机接口 ID。
81
- def apply_plan(hostid:, plan:)
82
- plan.map do |attributes, current|
83
- current ? update_interface(attributes, current) : create_interface(hostid, attributes)
84
- end
85
- end
86
-
87
- # 把接口字段递归转换为统一符号键。
88
- def normalize_definition(interface)
89
- interface.deep_symbolize_keys
90
- end
91
-
92
- # 校验新接口的通用字段及 SNMP 条件字段。
93
- def validate_create_definition!(attributes)
94
- attributes[:ip] = "" unless attributes.key?(:ip)
95
- attributes[:dns] = "" unless attributes.key?(:dns)
96
- interface_identity(attributes)
97
- validate_snmp_details!(attributes) if attributes[:type].to_i == 2
98
- end
99
-
100
- # 校验 SNMP 版本和 v1/v2c community 必填合同。
101
- def validate_snmp_details!(attributes)
102
- details = attributes[:details]&.deep_symbolize_keys
103
- raise Invalid, "SNMP interface details are required" unless details
104
-
105
- version = Integer(details[:version])
106
- raise Invalid, "SNMP interface version must be 1, 2, or 3" unless [1, 2, 3].include?(version)
107
- if [1, 2].include?(version) && details[:community].blank?
108
- raise Invalid, "SNMP v1/v2 interface community is required"
109
- end
110
-
111
- attributes[:details] = details
112
- rescue ArgumentError, TypeError
113
- raise Invalid, "SNMP interface version must be 1, 2, or 3"
114
- end
115
-
116
- # 校验期望接口是否包含重复身份。
117
- # @return [void]
118
- # @api private
119
- def validate_definitions!(interfaces)
120
- identities = interfaces.map { |interface| interface_identity(interface) }
121
- duplicate = identities.tally.find { |_identity, count| count > 1 }&.first
122
- raise Invalid, "duplicate desired interface identity #{duplicate}" if duplicate
123
- end
124
-
125
- # 按显式 ID 或稳定端点身份匹配已有接口。
126
- # @return [Hash, nil]
127
- # @api private
128
- def matching_interface(existing, attributes)
129
- if attributes[:interfaceid]
130
- match = existing.find { |item| item["interfaceid"].to_s == attributes[:interfaceid].to_s }
131
- raise Invalid, "interfaceid #{attributes[:interfaceid]} does not belong to this host" unless match
132
-
133
- return match
134
- end
135
-
136
- candidates = existing.select { |item| endpoint_identity(item) == endpoint_identity(attributes) }
137
- raise Conflict, "interface identity is ambiguous; provide interfaceid" if candidates.length > 1
138
-
139
- candidates.first
140
- end
141
-
142
- # 生成不依赖数组顺序的接口身份。
143
- # @return [String]
144
- # @api private
145
- def interface_identity(attributes)
146
- values = attributes.with_indifferent_access
147
- return "id:#{values[:interfaceid]}" if values[:interfaceid].present?
148
-
149
- endpoint_identity(values)
150
- end
151
-
152
- # 使用类型、端点和端口匹配接口,不把可变的 main 或远端 ID 作为端点身份。
153
- def endpoint_identity(attributes)
154
- values = attributes.with_indifferent_access
155
-
156
- %i[type main useip port].each do |field|
157
- raise Invalid, "interface #{field} is required" if values[field].blank?
158
- end
159
- endpoint_field = values[:useip].to_i == 1 ? :ip : :dns
160
- raise Invalid, "interface #{endpoint_field} is required" if values[endpoint_field].blank?
161
-
162
- "endpoint:#{values[:type]}:#{values[:useip]}:#{values[endpoint_field]}:#{values[:port]}"
163
- end
164
-
165
- # 更新已属于目标主机的接口。
166
- # @return [Integer]
167
- # @api private
168
- def update_interface(attributes, current)
169
- interfaceid = current.fetch("interfaceid")
170
- @client.api_request(
171
- method: "hostinterface.update",
172
- params: attributes.except(:hostid).merge(interfaceid: interfaceid)
173
- )
174
- interfaceid.to_i
175
- end
176
-
177
- # 为目标主机创建缺失接口。
178
- # @return [Integer]
179
- # @api private
180
- def create_interface(hostid, attributes)
181
- validate_create_definition!(attributes)
182
- result = @client.api_request(
183
- method: "hostinterface.create",
184
- params: attributes.except(:interfaceid).merge(hostid: hostid)
185
- )
186
- result.fetch("interfaceids").first.to_i
187
- end
188
- end
189
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ZabbixManager
4
- class Usergroups < Basic
5
- # 返回 Zabbix API 中用户组对象的方法名前缀。
6
- #
7
- # @return [String] 用户组对象的方法名前缀
8
- def method_name
9
- "usergroup"
10
- end
11
-
12
- # 返回用户组对象的主键字段名。
13
- #
14
- # @return [String] 用户组对象的主键字段名
15
- def key
16
- "usrgrpid"
17
- end
18
-
19
- # 返回用于唯一识别用户组的业务字段名。
20
- #
21
- # @return [String] 用户组对象的业务标识字段名
22
- def identify
23
- "name"
24
- end
25
-
26
- # 更新用户组对主机组的访问权限。
27
- #
28
- # @param data [Hash] 包含 usrgrpid、hostgroupids 及可选 permission
29
- # @raise [ApiError] Zabbix API 返回业务错误时抛出
30
- # @raise [TransportError] Zabbix 服务返回非成功 HTTP 状态时抛出
31
- # @return [Integer, nil] 已更新用户组的 ID
32
- def permissions(data)
33
- permission = data[:permission] || 2
34
- result = @client.api_request(
35
- method: "usergroup.update",
36
- params: {
37
- usrgrpid: data[:usrgrpid],
38
- rights: data[:hostgroupids].map { |t| { permission: permission, id: t } }
39
- }
40
- )
41
- result ? result["usrgrpids"][0].to_i : nil
42
- end
43
-
44
- # 将用户加入用户组;兼容旧调用并委托给 update_users。
45
- #
46
- # @deprecated Zabbix 已移除 massAdd,请使用 update_users。
47
- # @param data [Hash] 包含 userids 和 usrgrpids
48
- # @raise [ApiError] Zabbix API 返回业务错误时抛出
49
- # @raise [TransportError] Zabbix 服务返回非成功 HTTP 状态时抛出
50
- # @return [Integer, nil] 已更新用户组的 ID
51
- def add_user(data)
52
- update_users(data)
53
- end
54
-
55
- # 批量替换指定用户组中的用户列表。
56
- #
57
- # @param data [Hash] 包含 userids 和 usrgrpids
58
- # @raise [ApiError] Zabbix API 返回业务错误时抛出
59
- # @raise [TransportError] Zabbix 服务返回非成功 HTTP 状态时抛出
60
- # @return [Integer, nil] 首个已更新用户组的 ID
61
- def update_users(data)
62
- user_groups = data[:usrgrpids].map do |t|
63
- {
64
- usrgrpid: t,
65
- userids: data[:userids]
66
- }
67
- end
68
- result = @client.api_request(
69
- method: "usergroup.update",
70
- params: user_groups
71
- )
72
- result ? result["usrgrpids"][0].to_i : nil
73
- end
74
- end
75
- end