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.
- data/VERSION +1 -1
- data/bin/zabbix_api +45 -27
- data/lib/rubix.rb +17 -0
- data/lib/rubix/associations.rb +7 -1
- data/lib/rubix/associations/belongs_to_action.rb +31 -0
- data/lib/rubix/associations/belongs_to_media_type.rb +33 -0
- data/lib/rubix/associations/belongs_to_user.rb +33 -0
- data/lib/rubix/associations/belongs_to_user_group.rb +32 -0
- data/lib/rubix/associations/has_many_conditions.rb +23 -0
- data/lib/rubix/associations/has_many_user_groups.rb +32 -0
- data/lib/rubix/associations/has_many_users.rb +32 -0
- data/lib/rubix/models.rb +17 -10
- data/lib/rubix/models/action.rb +117 -0
- data/lib/rubix/models/application.rb +1 -3
- data/lib/rubix/models/condition.rb +99 -0
- data/lib/rubix/models/host.rb +9 -11
- data/lib/rubix/models/host_group.rb +1 -4
- data/lib/rubix/models/item.rb +12 -27
- data/lib/rubix/models/media_type.rb +19 -21
- data/lib/rubix/models/medium.rb +86 -0
- data/lib/rubix/models/model.rb +53 -1
- data/lib/rubix/models/operation.rb +134 -0
- data/lib/rubix/models/script.rb +49 -0
- data/lib/rubix/models/template.rb +2 -2
- data/lib/rubix/models/trigger.rb +8 -9
- data/lib/rubix/models/user.rb +145 -0
- data/lib/rubix/models/user_group.rb +94 -0
- data/lib/rubix/models/user_macro.rb +10 -20
- data/spec/requests/action_request_spec.rb +45 -0
- data/spec/requests/connection_request_spec.rb +3 -3
- data/spec/requests/media_type_request_spec.rb +8 -8
- data/spec/requests/script_request_spec.rb +54 -0
- data/spec/requests/user_group_request_spec.rb +97 -0
- data/spec/requests/user_request_spec.rb +84 -0
- data/spec/support/integration_helper.rb +105 -33
- data/spec/test.yml +0 -2
- 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
|
-
|
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
|
data/lib/rubix/models/trigger.rb
CHANGED
@@ -22,18 +22,15 @@ module Rubix
|
|
22
22
|
}.freeze
|
23
23
|
STATUS_CODES = STATUS_NAMES.invert.freeze
|
24
24
|
|
25
|
-
|
26
|
-
|
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
|
-
|
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
|