Class: ZabbixManager::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/zabbix_manager/client.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Client

HTTP 客户端初始化方法,同时进行用户权限签证

Raises:



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/zabbix_manager/client.rb', line 45

def initialize(options = {})
  # 设置实例变量 @options 以便在整个类中访问
  @options = options

  # 检查必要的配置属性是否存在
  raise ZbxError, "必须正确提供 :url 属性" unless @options.key?(:url)
  raise ZbxError, "必须正确提供 :user 属性" unless @options.key?(:user)
  raise ZbxError, "必须正确提供 :password 属性" unless @options.key?(:password)

  # 配置代理信息
  if !ENV["http_proxy"].nil? && options[:no_proxy] != true
    @proxy_uri               = URI.parse(ENV["http_proxy"])
    @proxy_host              = @proxy_uri.host
    @proxy_port              = @proxy_uri.port
    @proxy_user, @proxy_pass = @proxy_uri.userinfo&.split(/:/) if @proxy_uri.userinfo
  end

  # 检查 Zabbix API 版本是否受支持
  unless api_version.match?(/^[4-7]\.\d+\.\d+$/)
    message = "Zabbix API版本:#{api_version} 不受此版本的 zabbix_manager 支持"
    if @options[:ignore_version]
      log "[WARNING] #{message}"
    else
      raise ZbxError, message
    end
  end

  # 进行用户鉴权,获取令牌
  @auth_hash = auth
  log "[DEBUG] Auth token: #{@auth_hash}"
end

Instance Attribute Details

#optionsObject (readonly)

用于读取配置选项



10
11
12
# File 'lib/zabbix_manager/client.rb', line 10

def options
  @options
end

Instance Method Details

#_request(body) ⇒ Object

对 API 响应结果进行解析的方法



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/zabbix_manager/client.rb', line 146

def _request(body)
  # 发起 HTTP 请求并解析 JSON 格式的响应
  result = JSON.parse(http_request(body))

  # 如果响应结果中包含错误信息,则抛出 ZbxError 异常
  if result["error"]
    # 构建错误消息,包括服务器返回的错误信息和请求的详细信息
    msg = <<~MOJO

      ---------------------------------------------------------------
      Server answer API error: #{JSON.pretty_unparse(result["error"])}
        on request: #{pretty_body(body)}
      ---------------------------------------------------------------

    MOJO

    # 抛出自定义异常 ZbxError,并传递错误消息和完整的响应结果
    raise ZbxError.new(msg, result)
  else
    # 如果没有错误信息,则返回响应结果中的 "result" 部分
    result["result"]
  end
end

#api_request(body) ⇒ Object

通用的 API 调用发起方法



185
186
187
188
# File 'lib/zabbix_manager/client.rb', line 185

def api_request(body)
  # 调用之前定义的 json_payload 方法,将请求信息转换为 JSON 字符串
  _request json_payload(body)
end

#api_versionObject

获取 Zabbix API 版本



18
19
20
# File 'lib/zabbix_manager/client.rb', line 18

def api_version
  api_request(method: "apiinfo.version", params: {})
end

#authObject

用户鉴权方法,登录成功即可获取令牌



33
34
35
36
37
38
39
40
41
42
# File 'lib/zabbix_manager/client.rb', line 33

def auth
  # 发起 "user.login" 方法的 API 请求, 并传递用户信息(用户名和密码)作为参数
  api_request(
    method: "user.login",
    params: {
      user:     @options[:user],
      password: @options[:password]
    }
  )
end

#debug?Boolean

是否启用 debug 模式

Returns:

  • (Boolean)


23
24
25
# File 'lib/zabbix_manager/client.rb', line 23

def debug?
  !@options || @options[:debug]
end

#http_request(body) ⇒ Object

实例化 Net::HTTP 对象,并发起 API 请求的方法

Raises:



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/zabbix_manager/client.rb', line 95

def http_request(body)
  uri = URI.parse(@options[:url])

  # 设置超时时间,默认为 60 秒
  timeout = @options[:timeout].nil? ? 60 : @options[:timeout]
  log "[DEBUG] Timeout for request set to #{timeout} seconds"

  # 创建 Net::HTTP 对象,支持代理设置
  http =
    if @proxy_uri
      Net::HTTP.Proxy(@proxy_host, @proxy_port, @proxy_user, @proxy_pass).new(uri.host, uri.port)
    else
      Net::HTTP.new(uri.host, uri.port)
    end

  # 配置 HTTPS 请求
  if uri.scheme == "https"
    http.use_ssl     = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  end

  # 配置请求超时时间
  http.open_timeout = timeout
  http.read_timeout = timeout

  # 创建 POST 请求
  request = Net::HTTP::Post.new(uri.request_uri)

  # 添加基本身份验证信息(如果提供了用户名和密码)
  request.basic_auth(@options[:http_user], @options[:http_password]) if @options[:http_user]

  # 设置请求头的 Content-Type 为 application/json-rpc
  request.add_field("Content-Type", "application/json-rpc")

  # 设置请求体为传入的 JSON 字符串
  request.body = body
  log "[DEBUG] HTTP request params: #{pretty_body(request.body)}"

  # 发起请求并获取响应
  response = http.request(request)

  # 检查响应状态码,如果不是 200,则抛出 HttpError 异常
  raise HttpError.new("HTTP Error: #{response.code} on #{@options[:url]}", response) unless response.code == "200"

  log "[DEBUG] HTTP response answer: #{pretty_body(response.body)}"

  # 返回响应体
  response.body
end

#idObject

生成一个随机的请求标识符



13
14
15
# File 'lib/zabbix_manager/client.rb', line 13

def id
  @id ||= rand 100_00
end

#json_payload(body) ⇒ Object

定义一个方法,用于将 Ruby 数据结构转换为 JSON 字符串,并根据条件添加令牌



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/zabbix_manager/client.rb', line 78

def json_payload(body)
  # 构建基本的 JSON 负载,包括方法名、参数、请求 ID 和 JSON-RPC 版本
  payload        = {
    method:  body[:method],
    params:  body[:params],
    id:      id,
    jsonrpc: "2.0"
  }

  # 检查请求方法是否是 "apiinfo.version" 或 "user.login",如果不是,则添加令牌信息
  payload[:auth] = @auth_hash unless body[:method] == "apiinfo.version" || body[:method] == "user.login"

  # 将构建好的负载转换为 JSON 字符串并返回
  JSON(payload)
end

#log(message) ⇒ Object

Debug 打印信息



28
29
30
# File 'lib/zabbix_manager/client.rb', line 28

def log(message)
  puts message if debug?
end

#pretty_body(body) ⇒ Object

将 Ruby 数据结构美化成 JSON 字符串后打印输出的方法



171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/zabbix_manager/client.rb', line 171

def pretty_body(body)
  # 解析 JSON 字符串
  data = JSON.parse(body)

  # 如果参数中包含密码字段,则将密码字段的值替换为 "***"
  if data["params"].is_a?(Hash) && data["params"].key?("password")
    data["params"]["password"] = "***"
  end

  # 将美化后的数据转换为 JSON 字符串并返回
  JSON.pretty_unparse(data)
end