rubix 0.4.3 → 0.5.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 (37) hide show
  1. data/VERSION +1 -1
  2. data/bin/zabbix_api +45 -27
  3. data/lib/rubix.rb +17 -0
  4. data/lib/rubix/associations.rb +7 -1
  5. data/lib/rubix/associations/belongs_to_action.rb +31 -0
  6. data/lib/rubix/associations/belongs_to_media_type.rb +33 -0
  7. data/lib/rubix/associations/belongs_to_user.rb +33 -0
  8. data/lib/rubix/associations/belongs_to_user_group.rb +32 -0
  9. data/lib/rubix/associations/has_many_conditions.rb +23 -0
  10. data/lib/rubix/associations/has_many_user_groups.rb +32 -0
  11. data/lib/rubix/associations/has_many_users.rb +32 -0
  12. data/lib/rubix/models.rb +17 -10
  13. data/lib/rubix/models/action.rb +117 -0
  14. data/lib/rubix/models/application.rb +1 -3
  15. data/lib/rubix/models/condition.rb +99 -0
  16. data/lib/rubix/models/host.rb +9 -11
  17. data/lib/rubix/models/host_group.rb +1 -4
  18. data/lib/rubix/models/item.rb +12 -27
  19. data/lib/rubix/models/media_type.rb +19 -21
  20. data/lib/rubix/models/medium.rb +86 -0
  21. data/lib/rubix/models/model.rb +53 -1
  22. data/lib/rubix/models/operation.rb +134 -0
  23. data/lib/rubix/models/script.rb +49 -0
  24. data/lib/rubix/models/template.rb +2 -2
  25. data/lib/rubix/models/trigger.rb +8 -9
  26. data/lib/rubix/models/user.rb +145 -0
  27. data/lib/rubix/models/user_group.rb +94 -0
  28. data/lib/rubix/models/user_macro.rb +10 -20
  29. data/spec/requests/action_request_spec.rb +45 -0
  30. data/spec/requests/connection_request_spec.rb +3 -3
  31. data/spec/requests/media_type_request_spec.rb +8 -8
  32. data/spec/requests/script_request_spec.rb +54 -0
  33. data/spec/requests/user_group_request_spec.rb +97 -0
  34. data/spec/requests/user_request_spec.rb +84 -0
  35. data/spec/support/integration_helper.rb +105 -33
  36. data/spec/test.yml +0 -2
  37. metadata +22 -4
@@ -0,0 +1,134 @@
1
+ module Rubix
2
+
3
+ class Operation < Model
4
+
5
+ # Numeric codes for the action's type.
6
+ TYPE_CODES = {
7
+ :message => 0,
8
+ :command => 1,
9
+ :host_add => 2,
10
+ :host_remove => 3,
11
+ :host_group_add => 4,
12
+ :host_group_remove => 5,
13
+ :template_add => 6,
14
+ :template_remove => 7,
15
+ :host_enable => 8,
16
+ :host_disable => 9
17
+ }.freeze
18
+ TYPE_NAMES = TYPE_CODES.invert.freeze
19
+
20
+ # Numeric codes for the type of object that should be notified.
21
+ # Default will be 'group'.
22
+ NOTIFICATION_OBJECT_CODES = {
23
+ :user => 0,
24
+ :user_group => 1
25
+ }.freeze
26
+ NOTIFICATION_OBJECT_NAMES = NOTIFICATION_OBJECT_CODES.invert.freeze
27
+
28
+ #
29
+ # == Properties & Finding ==
30
+ #
31
+
32
+ zabbix_attr :type, :default => :message, :required => true
33
+ zabbix_attr :message_subject, :default => Action::MESSAGE_SUBJECT
34
+ zabbix_attr :message_body, :default => Action::MESSAGE_BODY
35
+ zabbix_attr :use_default_message, :default => true
36
+ zabbix_attr :escalation_time, :default => 0
37
+ zabbix_attr :start, :default => 1
38
+ zabbix_attr :stop, :default => 1
39
+
40
+ def step= s
41
+ self.start = s
42
+ self.stop = s
43
+ end
44
+
45
+ def initialize properties={}
46
+ super(properties)
47
+ self.step = properties[:step] if properties[:step]
48
+
49
+ self.user_id = properties[:user_id]
50
+ self.user = properties[:user]
51
+
52
+ self.user_group_id = properties[:user_group_id]
53
+ self.user_group = properties[:user_group]
54
+
55
+ self.conditions = (properties[:conditions] || [])
56
+
57
+ self.media_type = properties[:media_type]
58
+ self.media_type_id = properties[:media_type_id]
59
+ end
60
+
61
+ def notification_object_name
62
+ case
63
+ when user_id then :user
64
+ when user_group_id then :user_group
65
+ else
66
+ raise Error.new("An #{resource_name} must have either a user or a user group.")
67
+ end
68
+ end
69
+
70
+ def notification_object_id
71
+ if user_id || user_group_id
72
+ return user_id || user_group_id
73
+ else
74
+ raise Error.new("An #{resource_name} must have either a user or a user group.")
75
+ end
76
+ end
77
+
78
+ #
79
+ # == Associations ==
80
+ #
81
+
82
+ include Associations::HasManyConditions
83
+ include Associations::BelongsToUser
84
+ include Associations::BelongsToUserGroup
85
+ include Associations::BelongsToMediaType
86
+
87
+ #
88
+ # == Requests ==
89
+ #
90
+
91
+ def create_params
92
+ {
93
+ :operationtype => self.class::TYPE_CODES[type],
94
+ :object => self.class::NOTIFICATION_OBJECT_CODES[notification_object_name],
95
+ :objectid => notification_object_id,
96
+ :shortdata => message_subject,
97
+ :longdata => message_body,
98
+ :default_msg => (use_default_message ? 1 : 0),
99
+ :evaltype => Condition::JOIN_CODES[condition_operator],
100
+ :esc_period => escalation_time,
101
+ :esc_step_from => start,
102
+ :esc_step_to => stop
103
+ }.tap do |cp|
104
+ cp[:opconditions] = conditions.map(&:to_hash) unless conditions.empty?
105
+ cp[:opmediatypes] = [{ :mediatypeid => media_type_id }] if media_type_id
106
+ end
107
+ end
108
+
109
+ def self.build operation
110
+ new({
111
+ :id => operation[id_field].to_i,
112
+ :type => self::TYPE_NAMES[operation['operationtype'].to_i],
113
+ :message_subject => operation['shortdata'],
114
+ :message_body => operation['longdata'],
115
+ :escalation_period => operation['esc_period'].to_i,
116
+ :use_default_message => (operation['default_msg'].to_i == 1),
117
+ :condition_operator => Condition::JOIN_NAMES[operation['evaltype'].to_i],
118
+ :conditions => (operation['opconditions'] || []).map { |c| Condition.build(c) },
119
+ :start => operation['esc_step_from'].to_i,
120
+ :stop => operation['esc_step_to'].to_i
121
+ }).tap do |o|
122
+ if self::NOTIFICATION_OBJECT_NAMES[operation['object'].to_i] == :user
123
+ o.user_id = operation['objectid']
124
+ else
125
+ o.user_group_id = operation['objectid']
126
+ end
127
+ if (operation['opmediatypes'] || []).first
128
+ o.media_type_id = (operation['opmediatypes'] || []).first['mediatypeid'].to_i
129
+ end
130
+ end
131
+ end
132
+
133
+ end
134
+ end
@@ -0,0 +1,49 @@
1
+ module Rubix
2
+
3
+ class Script < Model
4
+
5
+ # Numeric codes of the access types a script can require to run on
6
+ # a host.
7
+ #
8
+ # Default is 'read'.
9
+ ACCESS_CODES = {
10
+ :read => 2,
11
+ :write => 3
12
+ }.freeze
13
+ ACCESS_NAMES = ACCESS_CODES.invert.freeze
14
+
15
+ #
16
+ # == Properties & Finding ==
17
+ #
18
+
19
+ zabbix_attr :name, :required => true
20
+ zabbix_attr :command, :required => true
21
+ zabbix_attr :access, :default => :read
22
+
23
+ #
24
+ # == Requests ==
25
+ #
26
+
27
+ def create_params
28
+ {
29
+ :name => name,
30
+ :command => command,
31
+ :host_access => self.class::ACCESS_CODES[access]
32
+ }
33
+ end
34
+
35
+ def self.find_params options={}
36
+ get_params.merge(:filter => {id_field => options[:id], :name => options[:name]})
37
+ end
38
+
39
+ def self.build script
40
+ new({
41
+ :id => script[id_field].to_i,
42
+ :name => script['name'],
43
+ :command => script['command'],
44
+ :access => self::ACCESS_NAMES[script['host_access'].to_i]
45
+ })
46
+ end
47
+
48
+ end
49
+ end
@@ -6,11 +6,10 @@ module Rubix
6
6
  # == Properties & Finding ==
7
7
  #
8
8
 
9
- attr_accessor :name
9
+ zabbix_attr :name, :required => true
10
10
 
11
11
  def initialize properties={}
12
12
  super(properties)
13
- @name = properties[:name]
14
13
 
15
14
  self.host_ids = properties[:host_ids]
16
15
  self.hosts = properties[:hosts]
@@ -24,6 +23,7 @@ module Rubix
24
23
  #
25
24
 
26
25
  def validate
26
+ super()
27
27
  raise ValidationError.new("A template must have at least one host group.") if host_group_ids.nil? || host_group_ids.empty?
28
28
  true
29
29
  end
@@ -22,18 +22,15 @@ module Rubix
22
22
  }.freeze
23
23
  STATUS_CODES = STATUS_NAMES.invert.freeze
24
24
 
25
- attr_accessor :description, :url, :status, :priority, :comments
26
- attr_reader :expression
25
+ zabbix_attr :description
26
+ zabbix_attr :url
27
+ zabbix_attr :status
28
+ zabbix_attr :priority
29
+ zabbix_attr :comments
27
30
 
28
31
  def initialize properties={}
29
32
  super(properties)
30
- @description = properties[:description]
31
- @url = properties[:url]
32
- @status = properties[:status]
33
- @priority = properties[:priority]
34
- @comments = properties[:comments]
35
-
36
- self.expression = properties[:expression]
33
+ self.expression = properties[:expression]
37
34
 
38
35
  self.host = properties[:host]
39
36
  self.template = properties[:template]
@@ -45,7 +42,9 @@ module Rubix
45
42
  self.item_ids = properties[:item_ids]
46
43
  end
47
44
 
45
+ attr_reader :expression
48
46
  def expression= e
47
+ return unless e
49
48
  if e =~ %r!^\{(.*)\}!
50
49
  trigger_condition = $1
51
50
  if trigger_condition && trigger_condition =~ /:/
@@ -0,0 +1,145 @@
1
+ require 'digest/md5'
2
+
3
+ module Rubix
4
+
5
+ class User < Model
6
+
7
+ # Numeric codes for the various user types.
8
+ TYPE_CODES = {
9
+ :normal => 1,
10
+ :admin => 2,
11
+ :super_admin => 3
12
+ }.freeze
13
+ TYPE_NAMES = TYPE_CODES.invert.freeze
14
+
15
+ #
16
+ # == Properties & Finding ==
17
+ #
18
+
19
+ zabbix_attr :username, :required => true
20
+ zabbix_attr :first_name, :required => true
21
+ zabbix_attr :last_name, :required => true
22
+ zabbix_attr :url
23
+ zabbix_attr :auto_login
24
+ zabbix_attr :type
25
+ zabbix_attr :lang
26
+ zabbix_attr :theme
27
+ zabbix_attr :auto_logout_period
28
+ zabbix_attr :refresh_period
29
+ zabbix_attr :rows_per_page
30
+ zabbix_attr :password
31
+
32
+ attr_accessor :password_md5
33
+
34
+ def initialize properties={}
35
+ super(properties)
36
+ self.password_md5 = properties[:password_md5]
37
+
38
+ self.user_group_ids = properties[:user_group_ids]
39
+ self.user_groups = properties[:user_groups]
40
+
41
+ self.media = properties[:media]
42
+ end
43
+
44
+ #
45
+ # == Validations ==
46
+ #
47
+ def validate
48
+ super()
49
+ raise ValidationError.new("A new user must have a password") if new_record? && (password.nil? || password.empty?)
50
+ true
51
+ end
52
+
53
+ #
54
+ # == Associations ==
55
+ #
56
+
57
+ include Associations::HasManyUserGroups
58
+
59
+ attr_reader :media
60
+
61
+ def media= ms
62
+ return if ms.nil?
63
+ @media = ms.map do |m|
64
+ m = Medium.new(m) unless m.kind_of?(Medium)
65
+ m.user = self
66
+ m
67
+ end
68
+ end
69
+
70
+ #
71
+ # == Requests ==
72
+ #
73
+
74
+ def create_params
75
+ {
76
+ :alias => username,
77
+ :name => first_name,
78
+ :surname => last_name,
79
+ :url => url,
80
+ :lang => lang,
81
+ :refresh => refresh_period,
82
+ :type => self.class::TYPE_CODES[type],
83
+ :theme => theme,
84
+ :rows_per_page => rows_per_page
85
+ }.tap do |cp|
86
+ cp[:passwd] = password if password && (!password.empty?)
87
+
88
+ case
89
+ when auto_login
90
+ cp[:autologin] = 1
91
+ when (!auto_logout_period.nil?)
92
+ cp[:autologout] = auto_logout_period
93
+ end
94
+
95
+ end
96
+ end
97
+
98
+ def after_create
99
+ update_media
100
+ end
101
+
102
+ def before_update
103
+ update_media
104
+ end
105
+
106
+ def update_media
107
+ return true if media.nil?
108
+ response = request("user.updateMedia", { :users => [{:userid => id}], :medias => media.map(&:to_hash) })
109
+ if response.has_data?
110
+ true
111
+ else
112
+ error("Could not update media for #{resource_name}: #{response.error_message}")
113
+ false
114
+ end
115
+ end
116
+
117
+ def self.build user
118
+ new({
119
+ :id => user[id_field].to_i,
120
+ :username => user['alias'],
121
+ :first_name => user['name'],
122
+ :last_name => user['surname'],
123
+ :password_md5 => user['passwd'],
124
+ :url => user['url'],
125
+ :auto_login => (user['autologin'].to_i == 1),
126
+ :auto_logout_period => user['autologout'],
127
+ :lang => user['lang'],
128
+ :refresh_period => user['refresh'].to_i,
129
+ :type => self::TYPE_NAMES[user['type'].to_i],
130
+ :theme => user['theme'],
131
+ :rows_per_page => user['rows_per_page'].to_i
132
+ })
133
+ end
134
+
135
+ def self.get_params
136
+ # FIXME -- select_medias doesn't seem to work here...
137
+ super().merge({})
138
+ end
139
+
140
+ def self.find_params options={}
141
+ get_params.merge(:filter => {:alias => options[:username], id_field => options[:id]})
142
+ end
143
+
144
+ end
145
+ end
@@ -0,0 +1,94 @@
1
+ module Rubix
2
+
3
+ class UserGroup < Model
4
+
5
+ # Numeric codes for the types of access allowed to the GUI for
6
+ # users in the group. Default is, well, 'default'.
7
+ GUI_ACCESS_CODES = {
8
+ :default => 0,
9
+ :internal => 1,
10
+ :disabled => 2
11
+ }.freeze
12
+ GUI_ACCESS_NAMES = GUI_ACCESS_CODES.invert.freeze
13
+
14
+ #
15
+ # == Properties & Finding ==
16
+ #
17
+
18
+ zabbix_attr :name
19
+ zabbix_attr :api_access, :default => false
20
+ zabbix_attr :debug_mode, :default => false
21
+ zabbix_attr :banned, :default => false
22
+ zabbix_attr :gui_access, :default => :default
23
+
24
+ def initialize properties={}
25
+ super(properties)
26
+ self.user_ids = properties[:user_ids]
27
+ self.users = properties[:users]
28
+ end
29
+
30
+ def self.id_field
31
+ 'usrgrpid'
32
+ end
33
+
34
+ #
35
+ # == Associations ==
36
+ #
37
+
38
+ include Associations::HasManyUsers
39
+
40
+ #
41
+ # == Requests ==
42
+ #
43
+
44
+ def create_params
45
+ {
46
+ :name => name,
47
+ :gui_access => self.class::GUI_ACCESS_CODES[gui_access],
48
+ :users_status => (banned ? 1 : 0),
49
+ :api_access => (api_access ? 1 : 0),
50
+ :debug_mode => (debug_mode ? 1 : 0)
51
+ }
52
+ end
53
+
54
+ def after_create
55
+ update_users
56
+ end
57
+
58
+ def before_update
59
+ update_users
60
+ end
61
+
62
+ def update_users
63
+ return true unless self.user_ids
64
+ response = request("usergroup.massUpdate", { :usrgrpids => [id], :userids => self.user_ids })
65
+ if response.has_data?
66
+ true
67
+ else
68
+ error("Could not update users for #{resource_name}: #{response.error_message}")
69
+ false
70
+ end
71
+ end
72
+
73
+ def self.get_params
74
+ super().merge(:select_users => :refer)
75
+ end
76
+
77
+ def self.find_params options={}
78
+ get_params.merge(:filter => {id_field => options[:id], :name => options[:name]})
79
+ end
80
+
81
+ def self.build user_group
82
+ new({
83
+ :id => user_group[id_field].to_i,
84
+ :name => user_group['name'],
85
+ :gui_access => self::GUI_ACCESS_NAMES[user_group['gui_access'].to_i],
86
+ :banned => (user_group['users_status'].to_i == 1),
87
+ :api_access => (user_group['api_access'].to_i == 1),
88
+ :debug_mode => (user_group['debug_mode'].to_i == 1),
89
+ :user_ids => user_group['users'].map { |user_info| user_info['userid'].to_i }
90
+ })
91
+ end
92
+
93
+ end
94
+ end