rubix 0.4.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/bin/zabbix_api
CHANGED
@@ -16,41 +16,59 @@ Settings.define :password, :description => "Password for the Zabbix AP
|
|
16
16
|
Settings.define :server_error_sleep, :description => "Seconds to sleep after a 50x error from the server", :required => true, :type => Integer, :default => 1
|
17
17
|
|
18
18
|
def Settings.usage
|
19
|
-
%Q{usage: #{raw_script_name} [...--param=val...] METHOD PARAMS}
|
19
|
+
%Q{usage: #{raw_script_name} [...--param=val...] [--shell || METHOD PARAMS]}
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
rescue RuntimeError => e
|
25
|
-
puts e.message
|
26
|
-
Settings.dump_help
|
22
|
+
def bail msg=nil
|
23
|
+
$stderr.puts msg if msg
|
27
24
|
exit(1)
|
28
25
|
end
|
29
26
|
|
30
|
-
|
31
|
-
Settings
|
32
|
-
exit(1)
|
27
|
+
def connect
|
28
|
+
Rubix.connect(Settings[:url], Settings[:username], Settings[:password])
|
33
29
|
end
|
34
30
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
31
|
+
def perform_query
|
32
|
+
begin
|
33
|
+
method = Settings.rest[0]
|
34
|
+
params = JSON.parse(Settings.rest[1])
|
35
|
+
response = Rubix.connection.request(method, params)
|
36
|
+
|
37
|
+
if Settings[:pretty]
|
38
|
+
puts JSON.pretty_generate(response.parsed)
|
39
|
+
else
|
40
|
+
puts response.parsed.to_json
|
41
|
+
end
|
42
|
+
exit(0)
|
43
|
+
rescue JSON::ParserError => e
|
44
|
+
bail("Invalid JSON -- #{e.message}")
|
45
|
+
rescue Rubix::Error => e
|
46
|
+
bail($e.message)
|
48
47
|
end
|
48
|
+
end
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
def drop_into_a_shell
|
51
|
+
require 'irb'
|
52
|
+
ARGV.clear
|
53
|
+
include Rubix
|
54
|
+
IRB.start
|
55
|
+
end
|
56
|
+
|
57
|
+
begin
|
58
|
+
Settings.resolve!
|
59
|
+
rescue RuntimeError => e
|
60
|
+
Settings.dump_help
|
61
|
+
bail(e.message)
|
62
|
+
end
|
63
|
+
|
64
|
+
begin
|
65
|
+
connect
|
53
66
|
rescue Rubix::Error => e
|
54
|
-
|
55
|
-
|
67
|
+
bail("Could not connect to Zabbix API: #{e.message}")
|
68
|
+
end
|
69
|
+
|
70
|
+
if Settings.rest.size < 2
|
71
|
+
drop_into_a_shell
|
72
|
+
else
|
73
|
+
perform_query
|
56
74
|
end
|
data/lib/rubix.rb
CHANGED
@@ -42,6 +42,20 @@ module Rubix
|
|
42
42
|
@connection = connection
|
43
43
|
end
|
44
44
|
|
45
|
+
# Is Rubix presently connected to a Zabbix server?
|
46
|
+
#
|
47
|
+
# @return [true, false]
|
48
|
+
def self.connected?
|
49
|
+
(!! connection)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Is Rubix presently connected and authorized with a Zabbix server?
|
53
|
+
#
|
54
|
+
# @return [true, false]
|
55
|
+
def self.authorized?
|
56
|
+
connection && connection.authorized?
|
57
|
+
end
|
58
|
+
|
45
59
|
# Return the current connection to a Zabbix API. Useful for
|
46
60
|
# directly sending queries.
|
47
61
|
#
|
@@ -71,5 +85,8 @@ module Rubix
|
|
71
85
|
# from being saved by the Zabbix API (i.e. - no host group for a
|
72
86
|
# host).
|
73
87
|
ValidationError = Class.new(Error)
|
88
|
+
|
89
|
+
# Given an incorrect argument.
|
90
|
+
ArgumentError = Class.new(Error)
|
74
91
|
|
75
92
|
end
|
data/lib/rubix/associations.rb
CHANGED
@@ -7,11 +7,17 @@ module Rubix
|
|
7
7
|
autoload :HasManyUserMacros, 'rubix/associations/has_many_user_macros'
|
8
8
|
autoload :HasManyApplications, 'rubix/associations/has_many_applications'
|
9
9
|
autoload :HasManyItems, 'rubix/associations/has_many_items'
|
10
|
+
autoload :HasManyUsers, 'rubix/associations/has_many_users'
|
11
|
+
autoload :HasManyUserGroups, 'rubix/associations/has_many_user_groups'
|
12
|
+
autoload :HasManyConditions, 'rubix/associations/has_many_conditions'
|
10
13
|
|
11
14
|
autoload :BelongsToHost, 'rubix/associations/belongs_to_host'
|
12
15
|
autoload :BelongsToTemplate, 'rubix/associations/belongs_to_template'
|
13
16
|
autoload :BelongsToItem, 'rubix/associations/belongs_to_item'
|
14
|
-
|
17
|
+
autoload :BelongsToAction, 'rubix/associations/belongs_to_action'
|
18
|
+
autoload :BelongsToUser, 'rubix/associations/belongs_to_user'
|
19
|
+
autoload :BelongsToUserGroup, 'rubix/associations/belongs_to_user_group'
|
20
|
+
autoload :BelongsToMediaType, 'rubix/associations/belongs_to_media_type'
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Rubix
|
2
|
+
module Associations
|
3
|
+
|
4
|
+
module BelongsToAction
|
5
|
+
|
6
|
+
def action= a
|
7
|
+
return unless a
|
8
|
+
@action = a
|
9
|
+
@action_id = a.id
|
10
|
+
end
|
11
|
+
|
12
|
+
def action
|
13
|
+
@action
|
14
|
+
end
|
15
|
+
|
16
|
+
def action_id= aid
|
17
|
+
return unless aid
|
18
|
+
@action_id = aid
|
19
|
+
end
|
20
|
+
|
21
|
+
def action_id
|
22
|
+
return @action_id if @action_id
|
23
|
+
return unless @action
|
24
|
+
@action_id = @action.id
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Rubix
|
2
|
+
module Associations
|
3
|
+
|
4
|
+
module BelongsToMediaType
|
5
|
+
|
6
|
+
def media_type= mt
|
7
|
+
return unless mt
|
8
|
+
@media_type = mt
|
9
|
+
@media_type_id = mt.id
|
10
|
+
end
|
11
|
+
|
12
|
+
def media_type
|
13
|
+
return @media_type if @media_type
|
14
|
+
return unless @media_type_id
|
15
|
+
@media_type = MediaType.find(:id => @media_type_id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def media_type_id= mtid
|
19
|
+
return unless mtid
|
20
|
+
@media_type_id = mtid
|
21
|
+
end
|
22
|
+
|
23
|
+
def media_type_id
|
24
|
+
return @media_type_id if @media_type_id
|
25
|
+
return unless @media_type
|
26
|
+
@media_type_id = @media_type.id
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Rubix
|
2
|
+
module Associations
|
3
|
+
|
4
|
+
module BelongsToUser
|
5
|
+
|
6
|
+
def user= u
|
7
|
+
return unless u
|
8
|
+
@user = u
|
9
|
+
@user_id = u.id
|
10
|
+
end
|
11
|
+
|
12
|
+
def user
|
13
|
+
return @user if @user
|
14
|
+
return unless @user_id
|
15
|
+
@user = User.find(:id => @user_id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def user_id= uid
|
19
|
+
return unless uid
|
20
|
+
@user_id = uid
|
21
|
+
end
|
22
|
+
|
23
|
+
def user_id
|
24
|
+
return @user_id if @user_id
|
25
|
+
return unless @user
|
26
|
+
@user_id = @user.id
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Rubix
|
2
|
+
module Associations
|
3
|
+
module BelongsToUserGroup
|
4
|
+
|
5
|
+
def user_group= ug
|
6
|
+
return unless ug
|
7
|
+
@user_group = ug
|
8
|
+
@user_group_id = ug.id
|
9
|
+
end
|
10
|
+
|
11
|
+
def user_group
|
12
|
+
return @user_group if @user_group
|
13
|
+
return unless @user_group_id
|
14
|
+
@user_group = UserGroup.find(:id => @user_group_id)
|
15
|
+
end
|
16
|
+
|
17
|
+
def user_group_id= ugid
|
18
|
+
return unless ugid
|
19
|
+
@user_group_id = ugid
|
20
|
+
end
|
21
|
+
|
22
|
+
def user_group_id
|
23
|
+
return @user_group_id if @user_group_id
|
24
|
+
return unless @user_group
|
25
|
+
@user_group_id = @user_group.id
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Rubix
|
2
|
+
module Associations
|
3
|
+
module HasManyConditions
|
4
|
+
|
5
|
+
def self.included klass
|
6
|
+
klass.send(:zabbix_attr, :condition_operator, :default => :and_or, :required => true)
|
7
|
+
end
|
8
|
+
|
9
|
+
def conditions
|
10
|
+
@conditions ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def conditions= cs
|
14
|
+
@conditions = cs.map do |c|
|
15
|
+
c.kind_of?(Condition) ? c : Condition.new(c)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Rubix
|
2
|
+
module Associations
|
3
|
+
module HasManyUserGroups
|
4
|
+
|
5
|
+
def user_groups= ugs
|
6
|
+
return unless ugs
|
7
|
+
@user_groups = ugs
|
8
|
+
@user_group_ids = ugs.map(&:id)
|
9
|
+
end
|
10
|
+
|
11
|
+
def user_groups
|
12
|
+
return @user_groups if @user_groups
|
13
|
+
return unless @user_group_ids
|
14
|
+
@user_groups = @user_group_ids.map { |ugid| UserGroup.find(:id => ugid) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def user_group_ids= ugids
|
18
|
+
return unless ugids
|
19
|
+
@user_group_ids = ugids
|
20
|
+
end
|
21
|
+
|
22
|
+
def user_group_ids
|
23
|
+
return @user_group_ids if @user_group_ids
|
24
|
+
return unless @user_groups
|
25
|
+
@user_group_ids = @user_groups.map(&:id)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Rubix
|
2
|
+
module Associations
|
3
|
+
module HasManyUsers
|
4
|
+
|
5
|
+
def users= us
|
6
|
+
return unless us
|
7
|
+
@users = us
|
8
|
+
@user_ids = us.map(&:id)
|
9
|
+
end
|
10
|
+
|
11
|
+
def users
|
12
|
+
return @users if @users
|
13
|
+
return unless @user_ids
|
14
|
+
@users = @user_ids.map { |uid| User.find(:id => uid) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def user_ids= uids
|
18
|
+
return unless uids
|
19
|
+
@user_ids = uids
|
20
|
+
end
|
21
|
+
|
22
|
+
def user_ids
|
23
|
+
return @user_ids if @user_ids
|
24
|
+
return unless @users
|
25
|
+
@user_ids = @users.map(&:id)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
data/lib/rubix/models.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
module Rubix
|
2
|
-
autoload :Model,
|
3
|
-
autoload :HostGroup,
|
4
|
-
autoload :Template,
|
5
|
-
autoload :Host,
|
6
|
-
autoload :Item,
|
7
|
-
autoload :Application,
|
8
|
-
autoload :UserMacro,
|
9
|
-
autoload :Trigger,
|
10
|
-
autoload :TimeSeries,
|
11
|
-
autoload :MediaType,
|
2
|
+
autoload :Model, 'rubix/models/model'
|
3
|
+
autoload :HostGroup, 'rubix/models/host_group'
|
4
|
+
autoload :Template, 'rubix/models/template'
|
5
|
+
autoload :Host, 'rubix/models/host'
|
6
|
+
autoload :Item, 'rubix/models/item'
|
7
|
+
autoload :Application, 'rubix/models/application'
|
8
|
+
autoload :UserMacro, 'rubix/models/user_macro'
|
9
|
+
autoload :Trigger, 'rubix/models/trigger'
|
10
|
+
autoload :TimeSeries, 'rubix/models/time_series'
|
11
|
+
autoload :MediaType, 'rubix/models/media_type'
|
12
|
+
autoload :Script, 'rubix/models/script'
|
13
|
+
autoload :Action, 'rubix/models/action'
|
14
|
+
autoload :Condition, 'rubix/models/condition'
|
15
|
+
autoload :Operation, 'rubix/models/operation'
|
16
|
+
autoload :User, 'rubix/models/user'
|
17
|
+
autoload :UserGroup, 'rubix/models/user_group'
|
18
|
+
autoload :Medium, 'rubix/models/medium'
|
12
19
|
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module Rubix
|
2
|
+
|
3
|
+
class Action < Model
|
4
|
+
|
5
|
+
# Numeric codes for the event source. Default will be 'triggers'.
|
6
|
+
EVENT_SOURCE_CODES = {
|
7
|
+
:triggers => 0,
|
8
|
+
:discovery => 1,
|
9
|
+
:auto_registration => 2
|
10
|
+
}.freeze
|
11
|
+
EVENT_SOURCE_NAMES = EVENT_SOURCE_CODES.invert.freeze
|
12
|
+
|
13
|
+
# The default subject for messages.
|
14
|
+
MESSAGE_SUBJECT = "{TRIGGER.NAME}: {TRIGGER.STATUS}"
|
15
|
+
|
16
|
+
# The default body for messages.
|
17
|
+
MESSAGE_BODY = "{TRIGGER.NAME}: {TRIGGER.STATUS}\nLast value: {ITEM.LASTVALUE}\n\n{TRIGGER.URL}"
|
18
|
+
|
19
|
+
#
|
20
|
+
# == Properties & Finding ==
|
21
|
+
#
|
22
|
+
|
23
|
+
zabbix_attr :name, :required => true
|
24
|
+
zabbix_attr :event_source, :default => :triggers, :required => true
|
25
|
+
zabbix_attr :escalation_time, :default => 0
|
26
|
+
zabbix_attr :enabled, :default => true
|
27
|
+
zabbix_attr :message_subject, :default => MESSAGE_SUBJECT
|
28
|
+
zabbix_attr :message_body, :default => MESSAGE_BODY
|
29
|
+
zabbix_attr :send_recovery_message, :default => false
|
30
|
+
zabbix_attr :recovery_message_subject, :default => MESSAGE_SUBJECT
|
31
|
+
zabbix_attr :recovery_message_body, :default => MESSAGE_BODY
|
32
|
+
|
33
|
+
def initialize properties={}
|
34
|
+
super(properties)
|
35
|
+
|
36
|
+
self.operations = (properties[:operations] || [])
|
37
|
+
self.conditions = (properties[:conditions] || [])
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# == Associations ==
|
42
|
+
#
|
43
|
+
|
44
|
+
include Associations::HasManyConditions
|
45
|
+
|
46
|
+
def operations
|
47
|
+
@operations ||= []
|
48
|
+
end
|
49
|
+
|
50
|
+
def operations= os
|
51
|
+
@operations = os.map do |o|
|
52
|
+
o.kind_of?(Operation) ? o : Operation.new(o)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# == Validations ==
|
58
|
+
#
|
59
|
+
def validate
|
60
|
+
super()
|
61
|
+
raise ValidationError.new("An action must have at least one operation defined.") if operations.empty?
|
62
|
+
operations.each do |operation|
|
63
|
+
return false unless operation.validate
|
64
|
+
end
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# == Requests ==
|
70
|
+
#
|
71
|
+
|
72
|
+
def create_params
|
73
|
+
{
|
74
|
+
:name => name,
|
75
|
+
:eventsource => self.class::EVENT_SOURCE_CODES[event_source],
|
76
|
+
:evaltype => Condition::JOIN_CODES[condition_operator],
|
77
|
+
:status => (enabled ? 0 : 1),
|
78
|
+
:esc_period => escalation_time,
|
79
|
+
:def_shortdata => message_subject,
|
80
|
+
:def_longdata => message_body,
|
81
|
+
:recovery_msg => (send_recovery_message ? 1 : 0),
|
82
|
+
:r_shortdata => recovery_message_subject,
|
83
|
+
:r_longdata => recovery_message_body
|
84
|
+
}.tap do |cp|
|
85
|
+
cp[:conditions] = conditions.map(&:to_hash) unless conditions.empty?
|
86
|
+
cp[:operations] = operations.map(&:to_hash) unless operations.empty?
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.find_params options={}
|
91
|
+
get_params.merge(:filter => {id_field => options[:id], :name => options[:name]})
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.get_params
|
95
|
+
super().merge({:select_conditions => :refer, :select_operations => :refer})
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.build action
|
99
|
+
new({
|
100
|
+
:id => action[id_field].to_i,
|
101
|
+
:name => action['name'],
|
102
|
+
:event_source => self::EVENT_SOURCE_NAMES[action['eventsource'].to_i],
|
103
|
+
:condition_operator => Condition::JOIN_NAMES[action['evaltype'].to_i],
|
104
|
+
:enabled => (action['status'].to_i == 0),
|
105
|
+
:escalation_time => action['esc_period'].to_i,
|
106
|
+
:message_subject => action['def_shortdata'],
|
107
|
+
:message_body => action['def_longdata'],
|
108
|
+
:send_recovery_message => (action['recovery_msg'].to_i == 1),
|
109
|
+
:recovery_message_subject => action['r_shortdata'],
|
110
|
+
:recovery_message_body => action['r_longdata'],
|
111
|
+
:conditions => (action['conditions'] || []).map { |c| Condition.build(c) },
|
112
|
+
:operations => (action['operations'] || []).map { |o| Operation.build(o) }
|
113
|
+
})
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|