resurrected_god 0.14.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +559 -0
- data/README.md +9 -4
- data/bin/god +26 -28
- data/ext/god/extconf.rb +9 -9
- data/lib/god/behavior.rb +3 -5
- data/lib/god/behaviors/clean_pid_file.rb +4 -6
- data/lib/god/behaviors/clean_unix_socket.rb +4 -6
- data/lib/god/behaviors/notify_when_flapping.rb +13 -15
- data/lib/god/cli/command.rb +109 -89
- data/lib/god/cli/run.rb +51 -75
- data/lib/god/cli/version.rb +2 -4
- data/lib/god/condition.rb +12 -14
- data/lib/god/conditions/always.rb +3 -2
- data/lib/god/conditions/complex.rb +23 -24
- data/lib/god/conditions/cpu_usage.rb +12 -16
- data/lib/god/conditions/degrading_lambda.rb +15 -19
- data/lib/god/conditions/disk_usage.rb +7 -8
- data/lib/god/conditions/file_mtime.rb +3 -7
- data/lib/god/conditions/file_touched.rb +4 -5
- data/lib/god/conditions/flapping.rb +57 -62
- data/lib/god/conditions/http_response_code.rb +27 -32
- data/lib/god/conditions/lambda.rb +3 -5
- data/lib/god/conditions/memory_usage.rb +12 -16
- data/lib/god/conditions/process_exits.rb +12 -12
- data/lib/god/conditions/process_running.rb +8 -10
- data/lib/god/conditions/socket_responding.rb +23 -28
- data/lib/god/conditions/tries.rb +12 -14
- data/lib/god/configurable.rb +7 -10
- data/lib/god/contact.rb +41 -52
- data/lib/god/contacts/airbrake.rb +10 -12
- data/lib/god/contacts/campfire.rb +18 -20
- data/lib/god/contacts/email.rb +27 -28
- data/lib/god/contacts/prowl.rb +16 -17
- data/lib/god/contacts/scout.rb +2 -5
- data/lib/god/contacts/sensu.rb +15 -11
- data/lib/god/contacts/slack.rb +23 -33
- data/lib/god/contacts/statsd.rb +8 -8
- data/lib/god/contacts/twitter.rb +2 -2
- data/lib/god/contacts/webhook.rb +21 -24
- data/lib/god/driver.rb +12 -18
- data/lib/god/errors.rb +0 -2
- data/lib/god/event_handler.rb +40 -49
- data/lib/god/event_handlers/dummy_handler.rb +1 -1
- data/lib/god/event_handlers/kqueue_handler.rb +2 -2
- data/lib/god/event_handlers/netlink_handler.rb +1 -1
- data/lib/god/logger.rb +5 -13
- data/lib/god/metric.rb +13 -15
- data/lib/god/process.rb +93 -98
- data/lib/god/simple_logger.rb +13 -15
- data/lib/god/socket.rb +21 -23
- data/lib/god/sugar.rb +8 -8
- data/lib/god/sys_logger.rb +6 -8
- data/lib/god/system/portable_poller.rb +1 -9
- data/lib/god/system/process.rb +4 -6
- data/lib/god/system/slash_proc_poller.rb +17 -19
- data/lib/god/task.rb +110 -136
- data/lib/god/timeline.rb +2 -4
- data/lib/god/trigger.rb +7 -11
- data/lib/god/version.rb +1 -1
- data/lib/god/watch.rb +51 -57
- data/lib/god.rb +122 -148
- metadata +17 -370
- data/Announce.txt +0 -135
- data/Gemfile +0 -5
- data/Rakefile +0 -129
- data/doc/god.asciidoc +0 -1592
- data/doc/intro.asciidoc +0 -20
- data/ext/god/.gitignore +0 -5
- data/lib/god/compat19.rb +0 -33
- data/lib/god/contacts/hipchat.rb +0 -117
- data/lib/god/contacts/jabber.rb +0 -75
- data/test/configs/child_events/child_events.god +0 -44
- data/test/configs/child_events/simple_server.rb +0 -3
- data/test/configs/child_polls/child_polls.god +0 -37
- data/test/configs/child_polls/simple_server.rb +0 -12
- data/test/configs/complex/complex.god +0 -59
- data/test/configs/complex/simple_server.rb +0 -3
- data/test/configs/contact/contact.god +0 -118
- data/test/configs/contact/simple_server.rb +0 -3
- data/test/configs/daemon_events/daemon_events.god +0 -37
- data/test/configs/daemon_events/simple_server.rb +0 -8
- data/test/configs/daemon_events/simple_server_stop.rb +0 -11
- data/test/configs/daemon_polls/daemon_polls.god +0 -17
- data/test/configs/daemon_polls/simple_server.rb +0 -6
- data/test/configs/degrading_lambda/degrading_lambda.god +0 -31
- data/test/configs/degrading_lambda/tcp_server.rb +0 -15
- data/test/configs/keepalive/keepalive.god +0 -9
- data/test/configs/keepalive/keepalive.rb +0 -12
- data/test/configs/lifecycle/lifecycle.god +0 -25
- data/test/configs/matias/matias.god +0 -50
- data/test/configs/real.rb +0 -59
- data/test/configs/running_load/running_load.god +0 -16
- data/test/configs/stop_options/simple_server.rb +0 -12
- data/test/configs/stop_options/stop_options.god +0 -39
- data/test/configs/stress/simple_server.rb +0 -3
- data/test/configs/stress/stress.god +0 -15
- data/test/configs/task/logs/.placeholder +0 -0
- data/test/configs/task/task.god +0 -26
- data/test/configs/test.rb +0 -61
- data/test/configs/usr1_trapper.rb +0 -10
- data/test/helper.rb +0 -172
- data/test/suite.rb +0 -6
- data/test/test_airbrake.rb +0 -14
- data/test/test_behavior.rb +0 -18
- data/test/test_campfire.rb +0 -22
- data/test/test_condition.rb +0 -52
- data/test/test_conditions_disk_usage.rb +0 -50
- data/test/test_conditions_http_response_code.rb +0 -109
- data/test/test_conditions_process_running.rb +0 -40
- data/test/test_conditions_socket_responding.rb +0 -176
- data/test/test_conditions_tries.rb +0 -67
- data/test/test_contact.rb +0 -109
- data/test/test_driver.rb +0 -26
- data/test/test_email.rb +0 -34
- data/test/test_event_handler.rb +0 -82
- data/test/test_god.rb +0 -710
- data/test/test_god_system.rb +0 -201
- data/test/test_handlers_kqueue_handler.rb +0 -16
- data/test/test_hipchat.rb +0 -23
- data/test/test_jabber.rb +0 -29
- data/test/test_logger.rb +0 -55
- data/test/test_metric.rb +0 -74
- data/test/test_process.rb +0 -263
- data/test/test_prowl.rb +0 -15
- data/test/test_registry.rb +0 -15
- data/test/test_sensu.rb +0 -11
- data/test/test_slack.rb +0 -57
- data/test/test_socket.rb +0 -34
- data/test/test_statsd.rb +0 -22
- data/test/test_sugar.rb +0 -42
- data/test/test_system_portable_poller.rb +0 -17
- data/test/test_system_process.rb +0 -30
- data/test/test_task.rb +0 -246
- data/test/test_timeline.rb +0 -37
- data/test/test_trigger.rb +0 -63
- data/test/test_watch.rb +0 -286
- data/test/test_webhook.rb +0 -22
data/lib/god/configurable.rb
CHANGED
@@ -1,16 +1,13 @@
|
|
1
1
|
module God
|
2
|
-
|
3
2
|
module Configurable
|
4
3
|
# Override this method in your Configurable (optional)
|
5
4
|
#
|
6
5
|
# Called once after the Configurable has been sent to the block and attributes have been
|
7
6
|
# set. Do any post-processing on attributes here
|
8
7
|
def prepare
|
9
|
-
|
10
8
|
end
|
11
9
|
|
12
10
|
def reset
|
13
|
-
|
14
11
|
end
|
15
12
|
|
16
13
|
# Override this method in your Configurable (optional)
|
@@ -39,19 +36,19 @@ module God
|
|
39
36
|
base_name
|
40
37
|
end
|
41
38
|
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
# configurable - Should respond to :watch and :friendly_name
|
40
|
+
def self.complain(text, configurable = nil)
|
41
|
+
watch = configurable.watch rescue nil
|
42
|
+
msg = ''
|
45
43
|
msg += "#{watch.name}: " if watch
|
46
44
|
msg += text
|
47
|
-
msg += " for #{
|
45
|
+
msg += " for #{configurable.friendly_name}" if configurable
|
48
46
|
applog(watch, :error, msg)
|
49
47
|
false
|
50
48
|
end
|
51
49
|
|
52
|
-
def complain(text,
|
53
|
-
Configurable.complain(text,
|
50
|
+
def complain(text, configurable = nil)
|
51
|
+
Configurable.complain(text, configurable)
|
54
52
|
end
|
55
53
|
end
|
56
|
-
|
57
54
|
end
|
data/lib/god/contact.rb
CHANGED
@@ -1,21 +1,18 @@
|
|
1
1
|
module God
|
2
|
-
|
3
2
|
class Contact
|
4
3
|
include Configurable
|
5
4
|
|
6
5
|
attr_accessor :name, :group, :info
|
7
6
|
|
8
7
|
def self.generate(kind)
|
9
|
-
sym = kind.to_s.capitalize.gsub(/_(.)/){
|
8
|
+
sym = kind.to_s.capitalize.gsub(/_(.)/) { Regexp.last_match(1).upcase }.intern
|
10
9
|
c = God::Contacts.const_get(sym).new
|
11
10
|
|
12
|
-
unless c.
|
13
|
-
abort "Contact '#{c.class.name}' must subclass God::Contact"
|
14
|
-
end
|
11
|
+
abort "Contact '#{c.class.name}' must subclass God::Contact" unless c.is_a?(Contact)
|
15
12
|
|
16
13
|
c
|
17
14
|
rescue NameError
|
18
|
-
raise NoSuchContactError
|
15
|
+
raise NoSuchContactError, "No Contact found with the class name God::Contacts::#{sym}"
|
19
16
|
end
|
20
17
|
|
21
18
|
def self.valid?(contact)
|
@@ -29,7 +26,7 @@ module God
|
|
29
26
|
end
|
30
27
|
|
31
28
|
def arg(name)
|
32
|
-
|
29
|
+
instance_variable_get("@#{name}") || self.class.instance_variable_get("@#{name}")
|
33
30
|
end
|
34
31
|
|
35
32
|
# Normalize the given notify specification into canonical form.
|
@@ -45,50 +42,43 @@ module God
|
|
45
42
|
# Raises ArgumentError on invalid spec (message contains details)
|
46
43
|
def self.normalize(spec)
|
47
44
|
case spec
|
45
|
+
when String
|
46
|
+
{ contacts: Array(spec) }
|
47
|
+
when Array
|
48
|
+
raise ArgumentError, 'contains non-String elements' unless spec.all? { |x| x.instance_of?(String) }
|
49
|
+
|
50
|
+
{ contacts: spec }
|
51
|
+
when Hash
|
52
|
+
copy = spec.dup
|
53
|
+
|
54
|
+
# check :contacts
|
55
|
+
raise ArgumentError, 'must have a :contacts key' unless (contacts = copy.delete(:contacts))
|
56
|
+
|
57
|
+
case contacts
|
48
58
|
when String
|
49
|
-
|
59
|
+
# valid
|
50
60
|
when Array
|
51
|
-
unless
|
52
|
-
|
53
|
-
end
|
54
|
-
{:contacts => spec}
|
55
|
-
when Hash
|
56
|
-
copy = spec.dup
|
57
|
-
|
58
|
-
# check :contacts
|
59
|
-
if contacts = copy.delete(:contacts)
|
60
|
-
case contacts
|
61
|
-
when String
|
62
|
-
# valid
|
63
|
-
when Array
|
64
|
-
unless contacts.select { |x| !x.instance_of?(String) }.empty?
|
65
|
-
raise ArgumentError.new("has a :contacts key containing non-String elements")
|
66
|
-
end
|
67
|
-
# valid
|
68
|
-
else
|
69
|
-
raise ArgumentError.new("must have a :contacts key pointing to a String or Array of Strings")
|
70
|
-
end
|
71
|
-
else
|
72
|
-
raise ArgumentError.new("must have a :contacts key")
|
73
|
-
end
|
74
|
-
|
75
|
-
# remove priority and category
|
76
|
-
copy.delete(:priority)
|
77
|
-
copy.delete(:category)
|
78
|
-
|
79
|
-
# check for invalid keys
|
80
|
-
unless copy.empty?
|
81
|
-
raise ArgumentError.new("contains extra elements: #{copy.inspect}")
|
82
|
-
end
|
83
|
-
|
84
|
-
# normalize
|
85
|
-
spec[:contacts] &&= Array(spec[:contacts])
|
86
|
-
spec[:priority] &&= spec[:priority].to_s
|
87
|
-
spec[:category] &&= spec[:category].to_s
|
88
|
-
|
89
|
-
spec
|
61
|
+
raise ArgumentError, 'has a :contacts key containing non-String elements' unless contacts.all? { |x| x.instance_of?(String) }
|
62
|
+
# valid
|
90
63
|
else
|
91
|
-
raise ArgumentError
|
64
|
+
raise ArgumentError, 'must have a :contacts key pointing to a String or Array of Strings'
|
65
|
+
end
|
66
|
+
|
67
|
+
# remove priority and category
|
68
|
+
copy.delete(:priority)
|
69
|
+
copy.delete(:category)
|
70
|
+
|
71
|
+
# check for invalid keys
|
72
|
+
raise ArgumentError, "contains extra elements: #{copy.inspect}" unless copy.empty?
|
73
|
+
|
74
|
+
# normalize
|
75
|
+
spec[:contacts] &&= Array(spec[:contacts])
|
76
|
+
spec[:priority] &&= spec[:priority].to_s
|
77
|
+
spec[:category] &&= spec[:category].to_s
|
78
|
+
|
79
|
+
spec
|
80
|
+
else
|
81
|
+
raise ArgumentError, 'must be a String (contact name), Array (of contact names), or Hash (contact specification)'
|
92
82
|
end
|
93
83
|
end
|
94
84
|
|
@@ -99,16 +89,15 @@ module God
|
|
99
89
|
# +priority+ is the arbitrary priority String
|
100
90
|
# +category+ is the arbitrary category String
|
101
91
|
# +host+ is the hostname of the server
|
102
|
-
def notify(message, time, priority, category, host)
|
103
|
-
raise AbstractMethodNotOverriddenError
|
92
|
+
def notify(message, time, priority, category, host) # rubocop:disable Lint/UnusedMethodArgument
|
93
|
+
raise AbstractMethodNotOverriddenError, 'Contact#notify must be overridden in subclasses'
|
104
94
|
end
|
105
95
|
|
106
96
|
# Construct the friendly name of this Contact, looks like:
|
107
97
|
#
|
108
98
|
# Contact FooBar
|
109
99
|
def friendly_name
|
110
|
-
super + " Contact '#{
|
100
|
+
super + " Contact '#{name}'"
|
111
101
|
end
|
112
102
|
end
|
113
|
-
|
114
103
|
end
|
@@ -10,35 +10,33 @@ end
|
|
10
10
|
module God
|
11
11
|
module Contacts
|
12
12
|
class Airbrake < Contact
|
13
|
-
|
14
13
|
class << self
|
15
14
|
attr_accessor :apikey
|
16
15
|
end
|
17
16
|
|
18
17
|
def valid?
|
19
18
|
valid = true
|
20
|
-
valid &= complain("Attribute 'apikey' must be specified", self) if
|
19
|
+
valid &= complain("Attribute 'apikey' must be specified", self) if apikey.nil?
|
21
20
|
valid
|
22
21
|
end
|
23
22
|
|
24
23
|
attr_accessor :apikey
|
25
24
|
|
26
|
-
def notify(message,
|
27
|
-
::Airbrake.configure {}
|
25
|
+
def notify(message, _time, priority, category, host)
|
26
|
+
::Airbrake.configure {} # block must be passed
|
28
27
|
|
29
|
-
message = "God: #{message
|
30
|
-
message << " | #{[category, priority].join(
|
28
|
+
message = +"God: #{message} at #{host}"
|
29
|
+
message << " | #{[category, priority].join(' ')}" unless category.to_s.empty? || priority.to_s.empty?
|
31
30
|
|
32
|
-
if ::Airbrake.notify nil, :
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
self.info = if ::Airbrake.notify nil, error_message: message, api_key: arg(:apikey)
|
32
|
+
"sent airbrake notification to #{name}"
|
33
|
+
else
|
34
|
+
"failed to send airbrake notification to #{name}"
|
35
|
+
end
|
37
36
|
rescue Object => e
|
38
37
|
applog(nil, :info, "failed to send airbrake notification: #{e.message}")
|
39
38
|
applog(nil, :debug, e.backtrace.join("\n"))
|
40
39
|
end
|
41
|
-
|
42
40
|
end
|
43
41
|
end
|
44
42
|
end
|
@@ -18,8 +18,9 @@ end
|
|
18
18
|
module Marshmallow
|
19
19
|
class Connection
|
20
20
|
def initialize(options)
|
21
|
-
raise
|
22
|
-
raise
|
21
|
+
raise 'Required option :subdomain not set.' unless options[:subdomain]
|
22
|
+
raise 'Required option :token not set.' unless options[:token]
|
23
|
+
|
23
24
|
@options = options
|
24
25
|
end
|
25
26
|
|
@@ -40,12 +41,12 @@ module Marshmallow
|
|
40
41
|
|
41
42
|
res = http.request(req)
|
42
43
|
case res
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
when Net::HTTPSuccess
|
45
|
+
rooms = JSON.parse(res.body)
|
46
|
+
room = rooms['rooms'].select { |x| x['name'] == room }
|
47
|
+
rooms.empty? ? nil : room.first['id']
|
48
|
+
else
|
49
|
+
raise res.error!
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
@@ -65,10 +66,10 @@ module Marshmallow
|
|
65
66
|
|
66
67
|
res = http.request(req)
|
67
68
|
case res
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
when Net::HTTPSuccess
|
70
|
+
true
|
71
|
+
else
|
72
|
+
raise res.error!
|
72
73
|
end
|
73
74
|
end
|
74
75
|
end
|
@@ -76,16 +77,14 @@ end
|
|
76
77
|
|
77
78
|
module God
|
78
79
|
module Contacts
|
79
|
-
|
80
80
|
class Campfire < Contact
|
81
81
|
class << self
|
82
|
-
attr_accessor :subdomain, :token, :room, :ssl
|
83
|
-
attr_accessor :format
|
82
|
+
attr_accessor :subdomain, :token, :room, :ssl, :format
|
84
83
|
end
|
85
84
|
|
86
85
|
self.ssl = false
|
87
86
|
|
88
|
-
self.format = lambda do |message, time,
|
87
|
+
self.format = lambda do |message, time, _priority, _category, host|
|
89
88
|
"[#{time.strftime('%H:%M:%S')}] #{host} - #{message}"
|
90
89
|
end
|
91
90
|
|
@@ -103,9 +102,9 @@ module God
|
|
103
102
|
body = Campfire.format.call(message, time, priority, category, host)
|
104
103
|
|
105
104
|
conn = Marshmallow::Connection.new(
|
106
|
-
:
|
107
|
-
:
|
108
|
-
:
|
105
|
+
subdomain: arg(:subdomain),
|
106
|
+
token: arg(:token),
|
107
|
+
ssl: arg(:ssl)
|
109
108
|
)
|
110
109
|
|
111
110
|
conn.speak(arg(:room), body)
|
@@ -116,6 +115,5 @@ module God
|
|
116
115
|
applog(nil, :debug, e.backtrace.join("\n"))
|
117
116
|
end
|
118
117
|
end
|
119
|
-
|
120
118
|
end
|
121
119
|
end
|
data/lib/god/contacts/email.rb
CHANGED
@@ -26,19 +26,17 @@
|
|
26
26
|
# (default: "/usr/sbin/sendmail").
|
27
27
|
# sendmail_args - The String args to send to sendmail (default "-i -t").
|
28
28
|
|
29
|
+
require 'English'
|
29
30
|
require 'time'
|
30
31
|
require 'net/smtp'
|
31
32
|
|
32
33
|
module God
|
33
34
|
module Contacts
|
34
|
-
|
35
35
|
class Email < Contact
|
36
36
|
class << self
|
37
|
-
attr_accessor :to_email, :to_name, :from_email, :from_name,
|
38
|
-
:
|
39
|
-
:
|
40
|
-
:server_password, :sendmail_path, :sendmail_args
|
41
|
-
attr_accessor :format
|
37
|
+
attr_accessor :to_email, :to_name, :from_email, :from_name, :delivery_method, :server_host, :server_port,
|
38
|
+
:server_auth, :server_domain, :server_user, :server_password, :sendmail_path, :sendmail_args,
|
39
|
+
:format
|
42
40
|
end
|
43
41
|
|
44
42
|
self.from_email = 'god@example.com'
|
@@ -51,18 +49,18 @@ module God
|
|
51
49
|
self.sendmail_args = '-i -t'
|
52
50
|
|
53
51
|
self.format = lambda do |name, from_email, from_name, to_email, to_name, message, time, priority, category, host|
|
54
|
-
|
55
|
-
From: #{from_name} <#{from_email}>
|
56
|
-
To: #{to_name || name} <#{to_email}>
|
57
|
-
Subject: [god] #{message}
|
58
|
-
Date: #{time.httpdate}
|
59
|
-
Message-Id: <#{rand(1000000000).to_s(36)}.#{
|
52
|
+
<<~FORMAT
|
53
|
+
From: #{from_name} <#{from_email}>
|
54
|
+
To: #{to_name || name} <#{to_email}>
|
55
|
+
Subject: [god] #{message}
|
56
|
+
Date: #{time.httpdate}
|
57
|
+
Message-Id: <#{rand(1000000000).to_s(36)}.#{$PROCESS_ID}.#{from_email}>
|
60
58
|
|
61
|
-
Message: #{message}
|
62
|
-
Host: #{host}
|
63
|
-
Priority: #{priority}
|
64
|
-
Category: #{category}
|
65
|
-
|
59
|
+
Message: #{message}
|
60
|
+
Host: #{host}
|
61
|
+
Priority: #{priority}
|
62
|
+
Category: #{category}
|
63
|
+
FORMAT
|
66
64
|
end
|
67
65
|
|
68
66
|
attr_accessor :to_email, :to_name, :from_email, :from_name,
|
@@ -73,7 +71,9 @@ Category: #{category}
|
|
73
71
|
def valid?
|
74
72
|
valid = true
|
75
73
|
valid &= complain("Attribute 'to_email' must be specified", self) unless arg(:to_email)
|
76
|
-
|
74
|
+
unless [:smtp, :sendmail].include?(arg(:delivery_method))
|
75
|
+
valid &= complain("Attribute 'delivery_method' must be one of [ :smtp | :sendmail ]", self)
|
76
|
+
end
|
77
77
|
if arg(:delivery_method) == :smtp
|
78
78
|
valid &= complain("Attribute 'server_host' must be specified", self) unless arg(:server_host)
|
79
79
|
valid &= complain("Attribute 'server_port' must be specified", self) unless arg(:server_port)
|
@@ -87,20 +87,20 @@ Category: #{category}
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def notify(message, time, priority, category, host)
|
90
|
-
body = Email.format.call(
|
90
|
+
body = Email.format.call(name, arg(:from_email), arg(:from_name),
|
91
91
|
arg(:to_email), arg(:to_name), message, time,
|
92
92
|
priority, category, host)
|
93
93
|
|
94
94
|
case arg(:delivery_method)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
95
|
+
when :smtp
|
96
|
+
notify_smtp(body)
|
97
|
+
when :sendmail
|
98
|
+
notify_sendmail(body)
|
99
99
|
end
|
100
100
|
|
101
|
-
self.info = "sent email to #{arg(:to_email)} via #{arg(:delivery_method)
|
101
|
+
self.info = "sent email to #{arg(:to_email)} via #{arg(:delivery_method)}"
|
102
102
|
rescue Object => e
|
103
|
-
applog(nil, :info, "failed to send email to #{arg(:to_email)} via #{arg(:delivery_method)
|
103
|
+
applog(nil, :info, "failed to send email to #{arg(:to_email)} via #{arg(:delivery_method)}: #{e.message}")
|
104
104
|
applog(nil, :debug, e.backtrace.join("\n"))
|
105
105
|
end
|
106
106
|
|
@@ -119,12 +119,11 @@ Category: #{category}
|
|
119
119
|
end
|
120
120
|
|
121
121
|
def notify_sendmail(mail)
|
122
|
-
IO.popen("#{arg(:sendmail_path)} #{arg(:sendmail_args)}",
|
123
|
-
sm.print(mail.
|
122
|
+
IO.popen("#{arg(:sendmail_path)} #{arg(:sendmail_args)}", 'w+') do |sm|
|
123
|
+
sm.print(mail.delete("\r"))
|
124
124
|
sm.flush
|
125
125
|
end
|
126
126
|
end
|
127
127
|
end
|
128
|
-
|
129
128
|
end
|
130
129
|
end
|
data/lib/god/contacts/prowl.rb
CHANGED
@@ -10,14 +10,13 @@ end
|
|
10
10
|
module God
|
11
11
|
module Contacts
|
12
12
|
class Prowl < Contact
|
13
|
-
|
14
13
|
class << self
|
15
14
|
attr_accessor :apikey
|
16
15
|
end
|
17
16
|
|
18
17
|
def valid?
|
19
18
|
valid = true
|
20
|
-
valid &= complain("Attribute 'apikey' must be specified", self) if
|
19
|
+
valid &= complain("Attribute 'apikey' must be specified", self) if apikey.nil?
|
21
20
|
valid
|
22
21
|
end
|
23
22
|
|
@@ -27,29 +26,29 @@ module God
|
|
27
26
|
result = Prowly.notify do |n|
|
28
27
|
n.apikey = arg(:apikey)
|
29
28
|
n.priority = map_priority(priority.to_i)
|
30
|
-
n.application = category ||
|
31
|
-
n.event = "on "
|
32
|
-
n.description = message
|
29
|
+
n.application = category || 'God'
|
30
|
+
n.event = "on #{host}"
|
31
|
+
n.description = "#{message} at #{time}"
|
33
32
|
end
|
34
33
|
|
35
|
-
if result.succeeded?
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
self.info = if result.succeeded?
|
35
|
+
"sent prowl notification to #{name}"
|
36
|
+
else
|
37
|
+
"failed to send prowl notification to #{name}: #{result.message}"
|
38
|
+
end
|
40
39
|
rescue Object => e
|
41
|
-
applog(nil, :info, "failed to send prowl notification to #{
|
40
|
+
applog(nil, :info, "failed to send prowl notification to #{name}: #{e.message}")
|
42
41
|
applog(nil, :debug, e.backtrace.join("\n"))
|
43
42
|
end
|
44
43
|
|
45
44
|
def map_priority(priority)
|
46
45
|
case priority
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
46
|
+
when 1 then Prowly::Notification::Priority::EMERGENCY
|
47
|
+
when 2 then Prowly::Notification::Priority::HIGH
|
48
|
+
when 3 then Prowly::Notification::Priority::NORMAL
|
49
|
+
when 4 then Prowly::Notification::Priority::MODERATE
|
50
|
+
when 5 then Prowly::Notification::Priority::VERY_LOW
|
51
|
+
else Prowly::Notification::Priority::NORMAL
|
53
52
|
end
|
54
53
|
end
|
55
54
|
end
|
data/lib/god/contacts/scout.rb
CHANGED
@@ -8,11 +8,9 @@ require 'uri'
|
|
8
8
|
|
9
9
|
module God
|
10
10
|
module Contacts
|
11
|
-
|
12
11
|
class Scout < Contact
|
13
12
|
class << self
|
14
|
-
attr_accessor :client_key, :plugin_id
|
15
|
-
attr_accessor :format
|
13
|
+
attr_accessor :client_key, :plugin_id, :format
|
16
14
|
end
|
17
15
|
|
18
16
|
self.format = lambda do |message, priority, category, host|
|
@@ -32,7 +30,7 @@ module God
|
|
32
30
|
valid
|
33
31
|
end
|
34
32
|
|
35
|
-
def notify(message,
|
33
|
+
def notify(message, _time, priority, category, host)
|
36
34
|
data = {
|
37
35
|
:client_key => arg(:client_key),
|
38
36
|
:plugin_id => arg(:plugin_id),
|
@@ -50,6 +48,5 @@ module God
|
|
50
48
|
applog(nil, :debug, e.backtrace.join("\n"))
|
51
49
|
end
|
52
50
|
end
|
53
|
-
|
54
51
|
end
|
55
52
|
end
|
data/lib/god/contacts/sensu.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
2
2
|
# Send a notice to a SENSU client socket, port 3030 on 'localhost' only.
|
3
|
-
#
|
3
|
+
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
4
4
|
# [mandatory]
|
5
5
|
# check_name - a unique check name
|
6
6
|
#
|
@@ -16,7 +16,6 @@ end
|
|
16
16
|
|
17
17
|
module God
|
18
18
|
module Contacts
|
19
|
-
|
20
19
|
class Sensu < Contact
|
21
20
|
class << self
|
22
21
|
attr_accessor :check_name, :status_code, :handler, :host, :port
|
@@ -37,23 +36,28 @@ module God
|
|
37
36
|
|
38
37
|
def sensu_client_socket(msg)
|
39
38
|
u = UDPSocket.new
|
40
|
-
u.send(msg
|
39
|
+
u.send("#{msg}\n", 0, arg(:host).nil? ? host : arg(:host), arg(:port).nil? ? port : arg(:port))
|
41
40
|
u.close
|
42
41
|
end
|
43
42
|
|
44
43
|
def notify(message, time, priority, category, host)
|
45
44
|
data = {
|
46
|
-
:
|
47
|
-
:
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
45
|
+
category: category,
|
46
|
+
message: message,
|
47
|
+
priority: priority,
|
48
|
+
host: host,
|
49
|
+
time: time
|
50
|
+
}
|
51
|
+
parcel = {
|
52
|
+
'name' => arg(:check_name),
|
53
|
+
'status' => arg(:status_code).nil? ? status_code : arg(:status_code),
|
54
|
+
'output' => data.to_json,
|
55
|
+
'handler' => arg(:handler).empty? ? handler : arg(:handler),
|
56
|
+
'executed' => Time.now.to_i
|
51
57
|
}
|
52
|
-
parcel = { 'name' => arg(:check_name), 'status' => arg(:status_code).nil? ? self.status_code : arg(:status_code), 'output' => data.to_json, 'handler' => arg(:handler).empty? ? self.handler : arg(:handler), 'executed' => Time.now.to_i }
|
53
58
|
sensu_client_socket parcel.to_json
|
54
59
|
self.info = "notified sensu: #{arg(:check_name)}"
|
55
60
|
end
|
56
61
|
end
|
57
62
|
end
|
58
63
|
end
|
59
|
-
|
data/lib/god/contacts/slack.rb
CHANGED
@@ -16,15 +16,14 @@ end
|
|
16
16
|
|
17
17
|
module God
|
18
18
|
module Contacts
|
19
|
-
|
20
19
|
class Slack < Contact
|
21
20
|
class << self
|
22
21
|
attr_accessor :url, :channel, :notify_channel, :format, :username, :emoji
|
23
22
|
end
|
24
23
|
|
25
|
-
self.channel =
|
24
|
+
self.channel = '#general'
|
26
25
|
self.notify_channel = false
|
27
|
-
self.format =
|
26
|
+
self.format = '%{priority} alert on %{host}: %{message} (%{category}, %{time})'
|
28
27
|
|
29
28
|
def valid?
|
30
29
|
valid = true
|
@@ -35,28 +34,21 @@ module God
|
|
35
34
|
attr_accessor :url, :channel, :notify_channel, :format, :username, :emoji
|
36
35
|
|
37
36
|
def text(data)
|
38
|
-
text =
|
39
|
-
text <<
|
40
|
-
|
41
|
-
if RUBY_VERSION =~ /^1\.8/
|
42
|
-
text << arg(:format).gsub(/%\{(\w+)\}/) do |match|
|
43
|
-
data[$1.to_sym]
|
44
|
-
end
|
45
|
-
else
|
46
|
-
text << arg(:format) % data
|
47
|
-
end
|
37
|
+
text = +''
|
38
|
+
text << '<!channel> ' if arg(:notify_channel)
|
39
|
+
text << (arg(:format) % data)
|
48
40
|
|
49
41
|
text
|
50
42
|
end
|
51
43
|
|
52
44
|
def notify(message, time, priority, category, host)
|
53
45
|
text = text({
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
46
|
+
message: message,
|
47
|
+
time: time,
|
48
|
+
priority: priority,
|
49
|
+
category: category,
|
50
|
+
host: host
|
51
|
+
})
|
60
52
|
|
61
53
|
request(text)
|
62
54
|
end
|
@@ -71,28 +63,26 @@ module God
|
|
71
63
|
|
72
64
|
req = Net::HTTP::Post.new(api_url.request_uri)
|
73
65
|
req.body = {
|
74
|
-
:
|
75
|
-
:
|
76
|
-
:
|
77
|
-
}.tap
|
66
|
+
link_names: 1,
|
67
|
+
text: text,
|
68
|
+
channel: arg(:channel)
|
69
|
+
}.tap do |payload|
|
78
70
|
payload[:username] = arg(:username) if arg(:username)
|
79
71
|
payload[:icon_emoji] = arg(:emoji) if arg(:emoji)
|
80
|
-
|
72
|
+
end.to_json
|
81
73
|
|
82
74
|
res = http.request(req)
|
83
75
|
|
84
|
-
case res
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
76
|
+
self.info = case res
|
77
|
+
when Net::HTTPSuccess
|
78
|
+
"successfully notified slack on channel #{arg(:channel)}"
|
79
|
+
else
|
80
|
+
"failed to send webhook to #{arg(:url)}: #{res.error!}"
|
81
|
+
end
|
90
82
|
rescue Object => e
|
91
83
|
applog(nil, :info, "failed to send webhook to #{arg(:url)}: #{e.message}")
|
92
84
|
applog(nil, :debug, e.backtrace.join("\n"))
|
93
85
|
end
|
94
|
-
|
95
86
|
end
|
96
|
-
|
97
87
|
end
|
98
|
-
end
|
88
|
+
end
|