rubix 0.0.8 → 0.0.9
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.
- data/README.rdoc +10 -10
- data/VERSION +1 -1
- data/lib/rubix.rb +40 -1
- data/lib/rubix/associations/belongs_to_host.rb +4 -3
- data/lib/rubix/connection.rb +114 -34
- data/lib/rubix/log.rb +45 -1
- data/lib/rubix/models/model.rb +143 -9
- data/lib/rubix/response.rb +85 -13
- data/lib/rubix/sender.rb +122 -18
- data/spec/requests/application_request_spec.rb +36 -38
- data/spec/requests/host_group_request_spec.rb +40 -22
- data/spec/requests/host_request_spec.rb +55 -49
- data/spec/requests/item_request_spec.rb +49 -53
- data/spec/requests/template_request_spec.rb +34 -34
- data/spec/requests/user_macro_request_spec.rb +33 -27
- data/spec/spec_helper.rb +1 -13
- data/spec/support/integration_helper.rb +34 -1
- data/spec/test.yml +11 -3
- metadata +22 -8
data/lib/rubix/models/model.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
module Rubix
|
2
2
|
|
3
|
+
# A base class for all Zabbix models to subclass.
|
4
|
+
#
|
3
5
|
# It might be worth using ActiveModel -- but maybe not. The goal is
|
4
6
|
# to keep dependencies low while still retaining expressiveness.
|
5
7
|
class Model
|
6
8
|
|
7
|
-
|
9
|
+
# @return [Hash]] the properties this model was initialized with
|
10
|
+
attr_accessor :properties
|
11
|
+
|
12
|
+
# @return [Fixnum, nil] the ID of this model
|
13
|
+
attr_accessor :id
|
8
14
|
|
9
15
|
extend Logs
|
10
16
|
include Logs
|
@@ -15,28 +21,40 @@ module Rubix
|
|
15
21
|
|
16
22
|
# This is the name of the resource as used inside Rubix -- Host,
|
17
23
|
# HostGroup, UserMacro, &c.
|
24
|
+
#
|
25
|
+
# @return [String]
|
18
26
|
def self.resource_name
|
19
27
|
self.to_s.split('::').last
|
20
28
|
end
|
21
29
|
|
22
30
|
# This is the name of *this* resource instance, using this
|
23
31
|
# object's 'name' property if possible.
|
32
|
+
#
|
33
|
+
# @return [String]
|
24
34
|
def resource_name
|
25
35
|
"#{self.class.resource_name} #{respond_to?(:name) ? self.name : self.id}"
|
26
36
|
end
|
27
37
|
|
28
38
|
# This is the name of the resource as used by Zabbix -- host,
|
29
39
|
# hostgroup, usermacro, &c.
|
40
|
+
#
|
41
|
+
# @return [String]
|
30
42
|
def self.zabbix_name
|
31
43
|
resource_name.downcase
|
32
44
|
end
|
33
45
|
|
34
46
|
# This is the name of the id field returned in Zabbix responses --
|
35
|
-
# hostid
|
47
|
+
# +hostid+, +groupid+, +hostmacroid+, &c.
|
48
|
+
#
|
49
|
+
# @return [String]
|
36
50
|
def self.id_field
|
37
51
|
"#{zabbix_name}id"
|
38
52
|
end
|
39
53
|
|
54
|
+
# This is the name of the id field returned in Zabbix responses --
|
55
|
+
# +hostid+, +groupid+, +hostmacroid+, &c.
|
56
|
+
#
|
57
|
+
# @return [String]
|
40
58
|
def id_field
|
41
59
|
self.class.id_field
|
42
60
|
end
|
@@ -45,43 +63,83 @@ module Rubix
|
|
45
63
|
# == Initialization ==
|
46
64
|
#
|
47
65
|
|
66
|
+
# Create a new model instance. This may represent a new or
|
67
|
+
# existing Zabbix resource.
|
68
|
+
#
|
69
|
+
# @param [Hash] properties
|
70
|
+
# @option properties [Fixnum] id the ID of the resource in Zabbix (typically blank for a new resource)
|
48
71
|
def initialize properties={}
|
49
72
|
@properties = properties
|
50
73
|
@id = properties[:id]
|
51
74
|
end
|
52
75
|
|
76
|
+
# Send a request to the Zabbix API. This is just a convenience
|
77
|
+
# method for <tt>Rubix::Connection#request</tt>.
|
78
|
+
#
|
79
|
+
# @param [String] method
|
80
|
+
# @param [Hash,Array] params
|
81
|
+
# @return [Rubix::Response]
|
53
82
|
def request method, params
|
54
83
|
self.class.request(method, params)
|
55
84
|
end
|
56
85
|
|
86
|
+
# Send a request to the Zabbix API. This is just a convenience
|
87
|
+
# method for <tt>Rubix::Connection#request</tt>.
|
88
|
+
#
|
89
|
+
# @param [String] method
|
90
|
+
# @param [Hash,Array] params
|
91
|
+
# @return [Rubix::Response]
|
57
92
|
def self.request method, params
|
58
93
|
Rubix.connection && Rubix.connection.request(method, params)
|
59
94
|
end
|
60
95
|
|
96
|
+
# Is this a new record? We can tell because the ID must be blank.
|
61
97
|
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
|
98
|
+
# @return [true, false]
|
65
99
|
def new_record?
|
66
100
|
@id.nil?
|
67
101
|
end
|
68
102
|
|
103
|
+
# Save this record.
|
104
|
+
#
|
105
|
+
# Will create new records and update old ones.
|
106
|
+
#
|
107
|
+
# @return [true, false]
|
69
108
|
def save
|
70
109
|
new_record? ? create : update
|
71
110
|
end
|
72
|
-
|
111
|
+
|
112
|
+
# Validate this record.
|
113
|
+
#
|
114
|
+
# Override this method in a subclass and have it raise a
|
115
|
+
# <tt>Rubix::ValidationError</tt> if validation fails.
|
116
|
+
#
|
117
|
+
# @return [true, false]
|
73
118
|
def validate
|
74
119
|
true
|
75
120
|
end
|
76
121
|
|
122
|
+
#
|
123
|
+
# == Create ==
|
124
|
+
#
|
125
|
+
|
126
|
+
# Parameters for creating a new resource of this type.
|
127
|
+
#
|
128
|
+
# @return [Hash]
|
77
129
|
def create_params
|
78
130
|
{}
|
79
131
|
end
|
80
132
|
|
133
|
+
# Send a request to create this resource.
|
134
|
+
#
|
135
|
+
# @return [Rubix::Response]
|
81
136
|
def create_request
|
82
137
|
request("#{self.class.zabbix_name}.create", create_params)
|
83
138
|
end
|
84
139
|
|
140
|
+
# Create this resource.
|
141
|
+
#
|
142
|
+
# @return [true, false]
|
85
143
|
def create
|
86
144
|
return false unless validate
|
87
145
|
response = create_request
|
@@ -95,14 +153,27 @@ module Rubix
|
|
95
153
|
end
|
96
154
|
end
|
97
155
|
|
156
|
+
#
|
157
|
+
# == Update ==
|
158
|
+
#
|
159
|
+
|
160
|
+
# Parameters for updating a resource of this type.
|
161
|
+
#
|
162
|
+
# @return [Hash]
|
98
163
|
def update_params
|
99
164
|
create_params.merge({id_field => id})
|
100
165
|
end
|
101
166
|
|
167
|
+
# Send a request to update this resource.
|
168
|
+
#
|
169
|
+
# @return [Rubix::Response]
|
102
170
|
def update_request
|
103
171
|
request("#{self.class.zabbix_name}.update", update_params)
|
104
172
|
end
|
105
173
|
|
174
|
+
# Update this resource.
|
175
|
+
#
|
176
|
+
# @return [true, false]
|
106
177
|
def update
|
107
178
|
return false unless validate
|
108
179
|
return create if new_record?
|
@@ -121,18 +192,37 @@ module Rubix
|
|
121
192
|
end
|
122
193
|
end
|
123
194
|
|
195
|
+
# A hook that will be run before this resource is updated.
|
196
|
+
#
|
197
|
+
# Override this in a subclass to implement any desired
|
198
|
+
# before-update functionality. Must return +true+ or +false+.
|
199
|
+
#
|
200
|
+
# @return [true, false]
|
124
201
|
def before_update
|
125
202
|
true
|
126
203
|
end
|
127
204
|
|
205
|
+
#
|
206
|
+
# == Destroy ==
|
207
|
+
#
|
208
|
+
|
209
|
+
# Parameters for destroying this resource.
|
210
|
+
#
|
211
|
+
# @return [Array<Fixnum>]
|
128
212
|
def destroy_params
|
129
213
|
[id]
|
130
214
|
end
|
131
215
|
|
216
|
+
# Send a request to destroy this resource.
|
217
|
+
#
|
218
|
+
# @return [Rubix::Response]
|
132
219
|
def destroy_request
|
133
220
|
request("#{self.class.zabbix_name}.delete", destroy_params)
|
134
221
|
end
|
135
|
-
|
222
|
+
|
223
|
+
# Destroy this resource.
|
224
|
+
#
|
225
|
+
# @return [true, false]
|
136
226
|
def destroy
|
137
227
|
return true if new_record?
|
138
228
|
return false unless before_destroy
|
@@ -150,6 +240,12 @@ module Rubix
|
|
150
240
|
end
|
151
241
|
end
|
152
242
|
|
243
|
+
# A hook that will be run before this resource is destroyed.
|
244
|
+
#
|
245
|
+
# Override this in a subclass to implement any desired
|
246
|
+
# before-destroy functionality. Must return +true+ or +false+.
|
247
|
+
#
|
248
|
+
# @return [true, false]
|
153
249
|
def before_destroy
|
154
250
|
true
|
155
251
|
end
|
@@ -158,18 +254,33 @@ module Rubix
|
|
158
254
|
# == Index ==
|
159
255
|
#
|
160
256
|
|
257
|
+
# Parameters for 'get'-type requests for this resource's type.
|
258
|
+
#
|
259
|
+
# @return [Hash]
|
161
260
|
def self.get_params
|
162
261
|
{ :output => :extend }
|
163
262
|
end
|
164
263
|
|
264
|
+
# Parameters to list all the objects of this resource's type.
|
265
|
+
#
|
266
|
+
# @param [Hash] options options for filtering the list of all resources.
|
267
|
+
# @return [Hash]
|
165
268
|
def self.all_params options={}
|
166
269
|
get_params.merge(options)
|
167
270
|
end
|
168
271
|
|
272
|
+
# Send a request to list all objects of this resource's type.
|
273
|
+
#
|
274
|
+
# @param [Hash] options options for filtering the list of all resources.
|
275
|
+
# @return [Rubix::Response]
|
169
276
|
def self.all_request options={}
|
170
277
|
request("#{zabbix_name}.get", all_params(options))
|
171
278
|
end
|
172
279
|
|
280
|
+
# List all objects of this resource's type.
|
281
|
+
#
|
282
|
+
# @param [Hash] options options for filtering the list of all resources.
|
283
|
+
# @return [Array<Rubix::Model>]
|
173
284
|
def self.all options={}
|
174
285
|
response = all_request(options)
|
175
286
|
if response.has_data?
|
@@ -180,22 +291,39 @@ module Rubix
|
|
180
291
|
end
|
181
292
|
end
|
182
293
|
|
183
|
-
|
184
|
-
|
294
|
+
# Execute block once for each element of the result set.
|
295
|
+
#
|
296
|
+
# @param [Hash] options options for filtering the list of all resources.
|
297
|
+
# @return [Array<Rubix::Model>]
|
298
|
+
def self.each options={}, &block
|
299
|
+
all(options).each(&block)
|
185
300
|
end
|
186
301
|
|
187
302
|
#
|
188
303
|
# == Show ==
|
189
304
|
#
|
190
305
|
|
306
|
+
# Parameters for finding a specific resource.
|
307
|
+
#
|
308
|
+
# @param [Hash] options specify properties about the object to find
|
309
|
+
# @return [Hash]
|
191
310
|
def self.find_params options={}
|
192
311
|
get_params.merge(options)
|
193
312
|
end
|
194
313
|
|
314
|
+
# Send a find request for a specific resource.
|
315
|
+
#
|
316
|
+
# @param [Hash] options specify properties about the object to find
|
317
|
+
# @return [Rubix::Response]
|
195
318
|
def self.find_request options={}
|
196
319
|
request("#{zabbix_name}.get", find_params(options))
|
197
320
|
end
|
198
321
|
|
322
|
+
# Find a resource using the given +options+ or return +nil+ if
|
323
|
+
# none is found.
|
324
|
+
#
|
325
|
+
# @param [Hash] options specify properties about the object to find
|
326
|
+
# @return [Rubix::Model, nil]
|
199
327
|
def self.find options={}
|
200
328
|
response = find_request(options)
|
201
329
|
case
|
@@ -209,6 +337,12 @@ module Rubix
|
|
209
337
|
end
|
210
338
|
end
|
211
339
|
|
340
|
+
# Find a resource using the given +options+ or create one if none
|
341
|
+
# can be found. Will return +false+ if the object cannot be found
|
342
|
+
# and cannot be created.
|
343
|
+
#
|
344
|
+
# @param [Hash] options specify properties about the object to find
|
345
|
+
# @return [Rubix::Model, false]
|
212
346
|
def self.find_or_create options={}
|
213
347
|
response = find_request(options)
|
214
348
|
case
|
data/lib/rubix/response.rb
CHANGED
@@ -2,10 +2,22 @@ require 'json'
|
|
2
2
|
|
3
3
|
module Rubix
|
4
4
|
|
5
|
+
# A class used to wrap Net::HTTP::Response objects to make it easier
|
6
|
+
# to inspect them for various cases.
|
5
7
|
class Response
|
6
8
|
|
7
|
-
|
9
|
+
# @return [Net::HTTP::Response] the raw HTTP response from the Zabbix API
|
10
|
+
attr_reader :http_response
|
8
11
|
|
12
|
+
# @return [Fixnum] the raw HTTP response code
|
13
|
+
attr_reader :code
|
14
|
+
|
15
|
+
# @return [String] the raw HTTP response body
|
16
|
+
attr_reader :body
|
17
|
+
|
18
|
+
# Wrap a <tt>Net::HTTP::Response</tt>.
|
19
|
+
#
|
20
|
+
# @param [Net::HTTP::Response] http_response
|
9
21
|
def initialize(http_response)
|
10
22
|
@http_response = http_response
|
11
23
|
@body = http_response.body
|
@@ -13,9 +25,12 @@ module Rubix
|
|
13
25
|
end
|
14
26
|
|
15
27
|
#
|
16
|
-
# Parsing
|
28
|
+
# == Parsing ==
|
17
29
|
#
|
18
|
-
|
30
|
+
|
31
|
+
# The parsed JSON body.
|
32
|
+
#
|
33
|
+
# @return [Hash]
|
19
34
|
def parsed
|
20
35
|
return @parsed if @parsed
|
21
36
|
if non_200?
|
@@ -30,31 +45,64 @@ module Rubix
|
|
30
45
|
end
|
31
46
|
|
32
47
|
#
|
33
|
-
# Error Handling
|
48
|
+
# == Error Handling ==
|
34
49
|
#
|
35
50
|
|
51
|
+
# Was the response *not* a 200?
|
52
|
+
#
|
53
|
+
# @return [true,false]
|
36
54
|
def non_200?
|
37
55
|
code != 200
|
38
56
|
end
|
39
|
-
|
57
|
+
|
58
|
+
# Was the response an error? This will return +true+ if
|
59
|
+
#
|
60
|
+
# - the response was not a 200
|
61
|
+
# - the response was a 200 and contains an +error+ key
|
62
|
+
#
|
63
|
+
# @return [true, false]
|
40
64
|
def error?
|
41
65
|
non_200? || (parsed.is_a?(Hash) && parsed['error'])
|
42
66
|
end
|
43
67
|
|
68
|
+
# Was this response successful? Successful responses must
|
69
|
+
#
|
70
|
+
# - have a 200 response code
|
71
|
+
# - *not* have an +error+ key in the response
|
72
|
+
#
|
73
|
+
# @return [true, false]
|
74
|
+
def success?
|
75
|
+
!error?
|
76
|
+
end
|
77
|
+
|
78
|
+
# Was the response a *Zabbix* error, implying a 200 with an
|
79
|
+
# +error+ key.
|
80
|
+
#
|
81
|
+
# @return [true, false]
|
44
82
|
def zabbix_error?
|
45
83
|
code == 200 && error?
|
46
84
|
end
|
47
85
|
|
86
|
+
# Returns the error code of a Zabbix error or +nil+ if this wasn't
|
87
|
+
# an error.
|
88
|
+
#
|
89
|
+
# @return [nil, Fixnum]
|
48
90
|
def error_code
|
49
91
|
return unless error?
|
50
92
|
(non_200? ? code : parsed['error']['code'].to_i) rescue 0
|
51
93
|
end
|
52
|
-
|
94
|
+
|
95
|
+
# Returns the Zabbix type of the error or +nil+ if this wasn't an error.
|
96
|
+
#
|
97
|
+
# @return [nil, String]
|
53
98
|
def error_type
|
54
99
|
return unless error?
|
55
100
|
(non_200? ? "Non-200 Error" : parsed['error']['message']) rescue 'Unknown Error'
|
56
101
|
end
|
57
102
|
|
103
|
+
# Return an error message or +nil+ if this wasn't an error.
|
104
|
+
#
|
105
|
+
# @return [String, nil]
|
58
106
|
def error_message
|
59
107
|
return unless error?
|
60
108
|
begin
|
@@ -70,51 +118,75 @@ module Rubix
|
|
70
118
|
end
|
71
119
|
end
|
72
120
|
|
73
|
-
def success?
|
74
|
-
!error?
|
75
|
-
end
|
76
|
-
|
77
121
|
#
|
78
|
-
# Inspecting contents
|
122
|
+
# == Inspecting contents ==
|
79
123
|
#
|
80
124
|
|
125
|
+
# The contents of the +result+ key. Returns +nil+ if an error.
|
81
126
|
def result
|
127
|
+
return if error?
|
82
128
|
parsed['result']
|
83
129
|
end
|
84
|
-
|
130
|
+
|
131
|
+
# Return the contents of +key+ *within* the +result+ key or +nil+
|
132
|
+
# if an error.
|
85
133
|
def [] key
|
86
134
|
return if error?
|
87
135
|
result[key]
|
88
136
|
end
|
89
137
|
|
138
|
+
# Return the +first+ element of the +result+ key or +nil+ if an
|
139
|
+
# error.
|
90
140
|
def first
|
91
141
|
return if error?
|
92
142
|
result.first
|
93
143
|
end
|
94
144
|
|
145
|
+
# Is the +result+ key empty?
|
146
|
+
#
|
147
|
+
# @return [true, false]
|
95
148
|
def empty?
|
149
|
+
return true unless result
|
96
150
|
result.empty?
|
97
151
|
end
|
98
152
|
|
153
|
+
# Does this response "have data" in the sense that
|
154
|
+
#
|
155
|
+
# - it is a successful response (see <tt>Rubix::Response#success?</tt>)
|
156
|
+
# - it has a +result+ key which is not empty
|
99
157
|
def has_data?
|
100
158
|
success? && (!empty?)
|
101
159
|
end
|
102
|
-
|
160
|
+
|
161
|
+
# Is the contents of the *first* element of the +result+ key a
|
162
|
+
# Hash?
|
163
|
+
#
|
164
|
+
# @return [true, false]
|
103
165
|
def hash?
|
104
166
|
return false if error?
|
105
167
|
result.is_a?(Hash) && result.size > 0 && result.first.last
|
106
168
|
end
|
107
169
|
|
170
|
+
# Is the contents of the *first* element of the +result+ key an
|
171
|
+
# Array?
|
172
|
+
#
|
173
|
+
# @return [true, false]
|
108
174
|
def array?
|
109
175
|
return false if error?
|
110
176
|
result.is_a?(Array) && result.size > 0 && result.first
|
111
177
|
end
|
112
178
|
|
179
|
+
# Is the contents of the +result+ key a String?
|
180
|
+
#
|
181
|
+
# @return [true, false]
|
113
182
|
def string?
|
114
183
|
return false if error?
|
115
184
|
result.is_a?(String) && result.size > 0
|
116
185
|
end
|
117
186
|
|
187
|
+
# Is the contents of the +result+ key either +true+ or +false+?
|
188
|
+
#
|
189
|
+
# @return [true, false]
|
118
190
|
def boolean?
|
119
191
|
return false if error?
|
120
192
|
result == true || result == false
|