Class: Rubix::Model

Inherits:
Object
  • Object
show all
Extended by:
Logs
Includes:
Logs
Defined in:
lib/rubix/models/model.rb

Overview

A base class for all Zabbix models to subclass.

It might be worth using ActiveModel – but maybe not. The goal is to keep dependencies low while still retaining expressiveness.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logs

debug, error, fatal, info, warn

Constructor Details

#initialize(properties = {}) ⇒ Model

Create a new model instance. This may represent a new or existing Zabbix resource.

Parameters:

  • properties (Hash) (defaults to: {})

Options Hash (properties):

  • id (Fixnum)

    the ID of the resource in Zabbix (typically blank for a new resource)



71
72
73
74
75
76
77
# File 'lib/rubix/models/model.rb', line 71

def initialize properties={}
  @properties = properties
  self.class.properties.keys.each do |property|
    self.send("#{property}=", properties[property])
  end
  @id         = properties[:id]
end

Instance Attribute Details

#idFixnum?

Returns the ID of this model.

Returns:

  • (Fixnum, nil)

    the ID of this model



13
14
15
# File 'lib/rubix/models/model.rb', line 13

def id
  @id
end

#propertiesHash

Returns ] the properties this model was initialized with.

Returns:

  • (Hash)

    ] the properties this model was initialized with



10
11
12
# File 'lib/rubix/models/model.rb', line 10

def properties
  @properties
end

Class Method Details

.all(options = {}) ⇒ Array<Rubix::Model>

List all objects of this resource’s type.

Parameters:

  • options (Hash) (defaults to: {})

    options for filtering the list of all resources.

Returns:



317
318
319
320
321
322
323
324
325
# File 'lib/rubix/models/model.rb', line 317

def self.all options={} 
  response = all_request(options)
  if response.has_data?
    response.result.map { |obj_data| build(obj_data) }
  else
    error("Error listing all Zabbix #{resource_name}s: #{response.error_message}") unless response.success?
    []
  end
end

.all_params(options = {}) ⇒ Hash

Parameters to list all the objects of this resource’s type.

Parameters:

  • options (Hash) (defaults to: {})

    options for filtering the list of all resources.

Returns:

  • (Hash)


301
302
303
# File 'lib/rubix/models/model.rb', line 301

def self.all_params options={}
  get_params.merge(options)
end

.all_request(options = {}) ⇒ Rubix::Response

Send a request to list all objects of this resource’s type.

Parameters:

  • options (Hash) (defaults to: {})

    options for filtering the list of all resources.

Returns:



309
310
311
# File 'lib/rubix/models/model.rb', line 309

def self.all_request options={}
  request("#{zabbix_name}.get", all_params(options))
end

.each(options = {}, &block) ⇒ Array<Rubix::Model>

Execute block once for each element of the result set.

Parameters:

  • options (Hash) (defaults to: {})

    options for filtering the list of all resources.

Returns:



331
332
333
# File 'lib/rubix/models/model.rb', line 331

def self.each options={}, &block
  all(options).each(&block)
end

.find(options = {}) ⇒ Rubix::Model?

Find a resource using the given options or return nil if none is found.

Parameters:

  • options (Hash) (defaults to: {})

    specify properties about the object to find

Returns:



360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/rubix/models/model.rb', line 360

def self.find options={}
  response = find_request(options)
  case
  when response.has_data?
    build(response.result.first)
  when response.success?
    # a successful but empty response means it wasn't found
  else
    error("Error finding Zabbix #{resource_name} using #{options.inspect}: #{response.error_message}")
    nil
  end
end

.find_or_create(options = {}) ⇒ Rubix::Model, false

Find a resource using the given options or create one if none can be found. Will return false if the object cannot be found and cannot be created.

Parameters:

  • options (Hash) (defaults to: {})

    specify properties about the object to find

Returns:



379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# File 'lib/rubix/models/model.rb', line 379

def self.find_or_create options={}
  response = find_request(options)
  case
  when response.has_data?
    build(response.result.first)
  when response.success?
    # doesn't exist
    obj = new(options)
    if obj.save
      obj
    else
      false
    end
  else
    error("Error creating Zabbix #{resource_name} using #{options.inspect}: #{response.error_message}")
    false
  end
end

.find_params(options = {}) ⇒ Hash

Parameters for finding a specific resource.

Parameters:

  • options (Hash) (defaults to: {})

    specify properties about the object to find

Returns:

  • (Hash)


343
344
345
# File 'lib/rubix/models/model.rb', line 343

def self.find_params options={}
  get_params.merge(options)
end

.find_request(options = {}) ⇒ Rubix::Response

Send a find request for a specific resource.

Parameters:

  • options (Hash) (defaults to: {})

    specify properties about the object to find

Returns:



351
352
353
# File 'lib/rubix/models/model.rb', line 351

def self.find_request options={}
  request("#{zabbix_name}.get", find_params(options))
end

.get_paramsHash

Parameters for ‘get’-type requests for this resource’s type.

Returns:

  • (Hash)


293
294
295
# File 'lib/rubix/models/model.rb', line 293

def self.get_params
  { :output => :extend }
end

.id_fieldString

This is the name of the id field returned in Zabbix responses – hostid, groupid, hostmacroid, &c.

Returns:

  • (String)


50
51
52
# File 'lib/rubix/models/model.rb', line 50

def self.id_field
  "#{zabbix_name}id"
end

.list(ids) ⇒ Object

List ==



402
403
404
405
406
407
408
409
410
411
412
413
414
415
# File 'lib/rubix/models/model.rb', line 402

def self.list ids
  return [] if ids.nil? || ids.empty?
  response = request("#{zabbix_name}.get", get_params.merge((id_field + 's') => ids))
  case
  when response.has_data?
    response.result.map do |obj|
      build(obj)
    end
  when response.success?
    []
  else
    error("Error listing Zabbix #{resource_name}s: #{response.error_message}")
  end
end

.propertiesObject

Helpers ==



421
422
423
# File 'lib/rubix/models/model.rb', line 421

def self.properties
  @properties ||= {}
end

.request(method, params) ⇒ Rubix::Response

Send a request to the Zabbix API. This is just a convenience method for Rubix::Connection#request.

Parameters:

  • method (String)
  • params (Hash, Array)

Returns:



95
96
97
# File 'lib/rubix/models/model.rb', line 95

def self.request method, params
  Rubix.connection && Rubix.connection.request(method, params)
end

.resource_nameString

This is the name of the resource as used inside Rubix – Host, HostGroup, UserMacro, &c.

Returns:

  • (String)


26
27
28
# File 'lib/rubix/models/model.rb', line 26

def self.resource_name
  self.to_s.split('::').last
end

.web_request(verb, path, data = {}) ⇒ Object

Send a web request to the Zabbix web application. This is just a convenience method for Rubix::Connection#web_request.

Parameters:

  • verb (String)

    one of “GET” or “POST”

  • path (String)

    the path to send the request to

  • data (Hash) (defaults to: {})

    the data to include with the request



105
106
107
# File 'lib/rubix/models/model.rb', line 105

def self.web_request verb, path, data={}
  Rubix.connection && Rubix.connection.web_request(verb, path, data)
end

.zabbix_attr(name, options = {}) ⇒ Object



425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
# File 'lib/rubix/models/model.rb', line 425

def self.zabbix_attr name, options={}
  name = name.to_s.to_sym
  @properties     ||= {}
  @properties[name] = options
  
  if options[:default].nil?
    attr_accessor name
  else
    attr_writer name
    define_method name do
      current_value = instance_variable_get("@#{name}")
      return current_value unless current_value.nil?
      instance_variable_set("@#{name}", options[:default])
    end
  end
end

.zabbix_define(defname, hash) ⇒ Object



442
443
444
445
446
447
448
449
450
451
# File 'lib/rubix/models/model.rb', line 442

def self.zabbix_define defname, hash
  codes = hash
  names = hash.invert.freeze
  codes.keys.each do |key|
    codes[key.to_s] = codes[key]
  end
  codes.freeze
  const_set "#{defname}_CODES", codes
  const_set "#{defname}_NAMES", names
end

.zabbix_nameString

This is the name of the resource as used by Zabbix – host, hostgroup, usermacro, &c.

Returns:

  • (String)


42
43
44
# File 'lib/rubix/models/model.rb', line 42

def self.zabbix_name
  resource_name.downcase
end

Instance Method Details

#after_createObject

Run this hook after creating a new resource.



181
182
183
# File 'lib/rubix/models/model.rb', line 181

def after_create
  true
end

#before_destroytrue, false

A hook that will be run before this resource is destroyed.

Override this in a subclass to implement any desired before-destroy functionality. Must return true or false.

Returns:

  • (true, false)


282
283
284
# File 'lib/rubix/models/model.rb', line 282

def before_destroy
  true
end

#before_updatetrue, false

A hook that will be run before this resource is updated.

Override this in a subclass to implement any desired before-update functionality. Must return true or false.

Returns:

  • (true, false)


234
235
236
# File 'lib/rubix/models/model.rb', line 234

def before_update
  true
end

#createtrue, false

Create this resource.

Returns:

  • (true, false)


166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/rubix/models/model.rb', line 166

def create
  return false unless validate
  response = create_request
  if response.has_data?
    @id = response.result[id_field + 's'].first.to_i
    info("Created Zabbix #{resource_name}")
    true
  else
    error("Error creating Zabbix #{resource_name}: #{response.error_message}")
    return false
  end
  after_create
end

#create_paramsHash

Parameters for creating a new resource of this type.

Returns:

  • (Hash)


152
153
154
# File 'lib/rubix/models/model.rb', line 152

def create_params
  {}
end

#create_requestRubix::Response

Send a request to create this resource.

Returns:



159
160
161
# File 'lib/rubix/models/model.rb', line 159

def create_request
  request("#{self.class.zabbix_name}.create", create_params)
end

#destroytrue, false

Destroy this resource.

Returns:

  • (true, false)


259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/rubix/models/model.rb', line 259

def destroy
  return true if new_record?
  return false unless before_destroy
  response = destroy_request
  case
  when response.has_data? && response.result.values.first.first.to_i == id
    info("Destroyed Zabbix #{resource_name}")
    true
  when response.zabbix_error? && response.error_message =~ /does not exist/i
    # was never there
    true
  else
    error("Could not destroy Zabbix #{resource_name}: #{response.error_message}")
    false
  end
end

#destroy_paramsArray<Fixnum>

Parameters for destroying this resource.

Returns:

  • (Array<Fixnum>)


245
246
247
# File 'lib/rubix/models/model.rb', line 245

def destroy_params
  [id]
end

#destroy_requestRubix::Response

Send a request to destroy this resource.

Returns:



252
253
254
# File 'lib/rubix/models/model.rb', line 252

def destroy_request
  request("#{self.class.zabbix_name}.delete", destroy_params)
end

#id_fieldString

This is the name of the id field returned in Zabbix responses – hostid, groupid, hostmacroid, &c.

Returns:

  • (String)


58
59
60
# File 'lib/rubix/models/model.rb', line 58

def id_field
  self.class.id_field
end

#new_record?true, false

Is this a new record? We can tell because the ID must be blank.

Returns:

  • (true, false)


112
113
114
# File 'lib/rubix/models/model.rb', line 112

def new_record?
  @id.nil?
end

#request(method, params) ⇒ Rubix::Response

Send a request to the Zabbix API. This is just a convenience method for Rubix::Connection#request.

Parameters:

  • method (String)
  • params (Hash, Array)

Returns:



85
86
87
# File 'lib/rubix/models/model.rb', line 85

def request method, params
  self.class.request(method, params)
end

#resource_nameString

This is the name of this resource instance, using this object’s ‘name’ property if possible.

Returns:

  • (String)


34
35
36
# File 'lib/rubix/models/model.rb', line 34

def resource_name
  "#{self.class.resource_name} #{respond_to?(:name) ? self.name : self.id}"
end

#savetrue, false

Save this record.

Will create new records and update old ones.

Returns:

  • (true, false)


121
122
123
# File 'lib/rubix/models/model.rb', line 121

def save
  new_record? ? create : update
end

#to_hashHash

Return this object as a Hash.

Returns:

  • (Hash)


141
142
143
# File 'lib/rubix/models/model.rb', line 141

def to_hash
  update_params
end

#updatetrue, false

Update this resource.

Returns:

  • (true, false)


210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/rubix/models/model.rb', line 210

def update
  return false unless validate
  return create if new_record?
  return false unless before_update
  response = update_request
  case
  when response.has_data? && (response.result.values.first == true || response.result.values.first.map(&:to_i).include?(id))
    info("Updated Zabbix #{resource_name}")
    true
  when response.has_data?
    error("No error, but failed to update Zabbix #{resource_name}")
    false
  else
    error("Error updating Zabbix #{resource_name}: #{response.error_message}")
    false
  end
end

#update_paramsHash

Parameters for updating a resource of this type.

Returns:

  • (Hash)


192
193
194
195
196
197
198
# File 'lib/rubix/models/model.rb', line 192

def update_params
  if id
    create_params.merge({id_field => id})
  else
    create_params
  end
end

#update_requestRubix::Response

Send a request to update this resource.

Returns:



203
204
205
# File 'lib/rubix/models/model.rb', line 203

def update_request
  request("#{self.class.zabbix_name}.update", update_params)
end

#validatetrue, false

Validate this record.

Override this method in a subclass and have it raise a Rubix::ValidationError if validation fails.

Returns:

  • (true, false)


131
132
133
134
135
136
# File 'lib/rubix/models/model.rb', line 131

def validate
  self.class.properties.each_pair do |property, options|
    raise ValidationError.new("A #{self.class.resource_name} must have a #{property}") if options[:required] && (self.send(property).nil? || self.send(property).empty?)
  end
  true
end