mcproc 2016.2.20
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.
- checksums.yaml +7 -0
- data/Announce.txt +135 -0
- data/Gemfile +9 -0
- data/History.txt +469 -0
- data/LICENSE +22 -0
- data/README.md +37 -0
- data/Rakefile +185 -0
- data/TODO.md +37 -0
- data/bin/mcproc +134 -0
- data/doc/intro.asciidoc +20 -0
- data/doc/mcproc.asciidoc +1592 -0
- data/ext/god/.gitignore +5 -0
- data/ext/god/extconf.rb +56 -0
- data/ext/god/kqueue_handler.c +133 -0
- data/ext/god/netlink_handler.c +182 -0
- data/lib/god.rb +780 -0
- data/lib/god/behavior.rb +52 -0
- data/lib/god/behaviors/clean_pid_file.rb +21 -0
- data/lib/god/behaviors/clean_unix_socket.rb +21 -0
- data/lib/god/behaviors/notify_when_flapping.rb +51 -0
- data/lib/god/cli/command.rb +268 -0
- data/lib/god/cli/run.rb +170 -0
- data/lib/god/cli/version.rb +23 -0
- data/lib/god/compat19.rb +33 -0
- data/lib/god/condition.rb +96 -0
- data/lib/god/conditions/always.rb +36 -0
- data/lib/god/conditions/complex.rb +86 -0
- data/lib/god/conditions/cpu_usage.rb +80 -0
- data/lib/god/conditions/degrading_lambda.rb +52 -0
- data/lib/god/conditions/disk_usage.rb +32 -0
- data/lib/god/conditions/file_mtime.rb +28 -0
- data/lib/god/conditions/file_touched.rb +44 -0
- data/lib/god/conditions/flapping.rb +128 -0
- data/lib/god/conditions/http_response_code.rb +184 -0
- data/lib/god/conditions/lambda.rb +25 -0
- data/lib/god/conditions/memory_usage.rb +82 -0
- data/lib/god/conditions/process_exits.rb +66 -0
- data/lib/god/conditions/process_running.rb +63 -0
- data/lib/god/conditions/socket_responding.rb +142 -0
- data/lib/god/conditions/tries.rb +44 -0
- data/lib/god/configurable.rb +57 -0
- data/lib/god/contact.rb +114 -0
- data/lib/god/contacts/airbrake.rb +44 -0
- data/lib/god/contacts/campfire.rb +121 -0
- data/lib/god/contacts/email.rb +130 -0
- data/lib/god/contacts/hipchat.rb +117 -0
- data/lib/god/contacts/jabber.rb +75 -0
- data/lib/god/contacts/prowl.rb +57 -0
- data/lib/god/contacts/scout.rb +55 -0
- data/lib/god/contacts/sensu.rb +59 -0
- data/lib/god/contacts/slack.rb +98 -0
- data/lib/god/contacts/statsd.rb +46 -0
- data/lib/god/contacts/twitter.rb +51 -0
- data/lib/god/contacts/webhook.rb +74 -0
- data/lib/god/driver.rb +238 -0
- data/lib/god/errors.rb +24 -0
- data/lib/god/event_handler.rb +112 -0
- data/lib/god/event_handlers/dummy_handler.rb +13 -0
- data/lib/god/event_handlers/kqueue_handler.rb +17 -0
- data/lib/god/event_handlers/netlink_handler.rb +13 -0
- data/lib/god/logger.rb +109 -0
- data/lib/god/metric.rb +87 -0
- data/lib/god/process.rb +381 -0
- data/lib/god/registry.rb +32 -0
- data/lib/god/simple_logger.rb +59 -0
- data/lib/god/socket.rb +113 -0
- data/lib/god/sugar.rb +62 -0
- data/lib/god/sys_logger.rb +45 -0
- data/lib/god/system/portable_poller.rb +42 -0
- data/lib/god/system/process.rb +50 -0
- data/lib/god/system/slash_proc_poller.rb +92 -0
- data/lib/god/task.rb +552 -0
- data/lib/god/timeline.rb +25 -0
- data/lib/god/trigger.rb +43 -0
- data/lib/god/watch.rb +340 -0
- data/mcproc.gemspec +192 -0
- data/test/configs/child_events/child_events.god +44 -0
- data/test/configs/child_events/simple_server.rb +3 -0
- data/test/configs/child_polls/child_polls.god +37 -0
- data/test/configs/child_polls/simple_server.rb +12 -0
- data/test/configs/complex/complex.god +59 -0
- data/test/configs/complex/simple_server.rb +3 -0
- data/test/configs/contact/contact.god +118 -0
- data/test/configs/contact/simple_server.rb +3 -0
- data/test/configs/daemon_events/daemon_events.god +37 -0
- data/test/configs/daemon_events/simple_server.rb +8 -0
- data/test/configs/daemon_events/simple_server_stop.rb +11 -0
- data/test/configs/daemon_polls/daemon_polls.god +17 -0
- data/test/configs/daemon_polls/simple_server.rb +6 -0
- data/test/configs/degrading_lambda/degrading_lambda.god +31 -0
- data/test/configs/degrading_lambda/tcp_server.rb +15 -0
- data/test/configs/keepalive/keepalive.god +9 -0
- data/test/configs/keepalive/keepalive.rb +12 -0
- data/test/configs/lifecycle/lifecycle.god +25 -0
- data/test/configs/matias/matias.god +50 -0
- data/test/configs/real.rb +59 -0
- data/test/configs/running_load/running_load.god +16 -0
- data/test/configs/stop_options/simple_server.rb +12 -0
- data/test/configs/stop_options/stop_options.god +39 -0
- data/test/configs/stress/simple_server.rb +3 -0
- data/test/configs/stress/stress.god +15 -0
- data/test/configs/task/logs/.placeholder +0 -0
- data/test/configs/task/task.god +26 -0
- data/test/configs/test.rb +61 -0
- data/test/configs/usr1_trapper.rb +10 -0
- data/test/helper.rb +172 -0
- data/test/suite.rb +6 -0
- data/test/test_airbrake.rb +14 -0
- data/test/test_behavior.rb +18 -0
- data/test/test_campfire.rb +22 -0
- data/test/test_condition.rb +52 -0
- data/test/test_conditions_disk_usage.rb +50 -0
- data/test/test_conditions_http_response_code.rb +109 -0
- data/test/test_conditions_process_running.rb +40 -0
- data/test/test_conditions_socket_responding.rb +176 -0
- data/test/test_conditions_tries.rb +67 -0
- data/test/test_contact.rb +109 -0
- data/test/test_driver.rb +26 -0
- data/test/test_email.rb +34 -0
- data/test/test_event_handler.rb +82 -0
- data/test/test_god.rb +710 -0
- data/test/test_god_system.rb +201 -0
- data/test/test_handlers_kqueue_handler.rb +16 -0
- data/test/test_hipchat.rb +23 -0
- data/test/test_jabber.rb +29 -0
- data/test/test_logger.rb +55 -0
- data/test/test_metric.rb +74 -0
- data/test/test_process.rb +263 -0
- data/test/test_prowl.rb +15 -0
- data/test/test_registry.rb +15 -0
- data/test/test_sensu.rb +11 -0
- data/test/test_slack.rb +57 -0
- data/test/test_socket.rb +34 -0
- data/test/test_statsd.rb +22 -0
- data/test/test_sugar.rb +42 -0
- data/test/test_system_portable_poller.rb +17 -0
- data/test/test_system_process.rb +30 -0
- data/test/test_task.rb +246 -0
- data/test/test_timeline.rb +37 -0
- data/test/test_trigger.rb +63 -0
- data/test/test_watch.rb +286 -0
- data/test/test_webhook.rb +22 -0
- metadata +475 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
# Send a notice to Airbrake (http://airbrake.io/).
|
2
|
+
#
|
3
|
+
# apikey - The String API key.
|
4
|
+
|
5
|
+
CONTACT_DEPS[:airbrake] = ['airbrake']
|
6
|
+
CONTACT_DEPS[:airbrake].each do |d|
|
7
|
+
require d
|
8
|
+
end
|
9
|
+
|
10
|
+
module God
|
11
|
+
module Contacts
|
12
|
+
class Airbrake < Contact
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_accessor :apikey
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid?
|
19
|
+
valid = true
|
20
|
+
valid &= complain("Attribute 'apikey' must be specified", self) if self.apikey.nil?
|
21
|
+
valid
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_accessor :apikey
|
25
|
+
|
26
|
+
def notify(message, time, priority, category, host)
|
27
|
+
::Airbrake.configure {}
|
28
|
+
|
29
|
+
message = "God: #{message.to_s} at #{host}"
|
30
|
+
message << " | #{[category, priority].join(" ")}" unless category.to_s.empty? or priority.to_s.empty?
|
31
|
+
|
32
|
+
if ::Airbrake.notify nil, :error_message => message, :api_key => arg(:apikey)
|
33
|
+
self.info = "sent airbrake notification to #{self.name}"
|
34
|
+
else
|
35
|
+
self.info = "failed to send airbrake notification to #{self.name}"
|
36
|
+
end
|
37
|
+
rescue Object => e
|
38
|
+
applog(nil, :info, "failed to send airbrake notification: #{e.message}")
|
39
|
+
applog(nil, :debug, e.backtrace.join("\n"))
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# Send a notice to a Campfire room (http://campfirenow.com).
|
2
|
+
#
|
3
|
+
# subdomain - The String subdomain of the Campfire account. If your URL is
|
4
|
+
# "foo.campfirenow.com" then your subdomain is "foo".
|
5
|
+
# token - The String token used for authentication.
|
6
|
+
# room - The String room name to which the message should be sent.
|
7
|
+
# ssl - A Boolean determining whether or not to use SSL
|
8
|
+
# (default: false).
|
9
|
+
|
10
|
+
require 'net/http'
|
11
|
+
require 'net/https'
|
12
|
+
|
13
|
+
CONTACT_DEPS[:campfire] = ['json']
|
14
|
+
CONTACT_DEPS[:campfire].each do |d|
|
15
|
+
require d
|
16
|
+
end
|
17
|
+
|
18
|
+
module Marshmallow
|
19
|
+
class Connection
|
20
|
+
def initialize(options)
|
21
|
+
raise "Required option :subdomain not set." unless options[:subdomain]
|
22
|
+
raise "Required option :token not set." unless options[:token]
|
23
|
+
@options = options
|
24
|
+
end
|
25
|
+
|
26
|
+
def base_url
|
27
|
+
scheme = @options[:ssl] ? 'https' : 'http'
|
28
|
+
subdomain = @options[:subdomain]
|
29
|
+
"#{scheme}://#{subdomain}.campfirenow.com"
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_room_id_by_name(room)
|
33
|
+
url = URI.parse("#{base_url}/rooms.json")
|
34
|
+
|
35
|
+
http = Net::HTTP.new(url.host, url.port)
|
36
|
+
http.use_ssl = true if @options[:ssl]
|
37
|
+
|
38
|
+
req = Net::HTTP::Get.new(url.path)
|
39
|
+
req.basic_auth(@options[:token], 'X')
|
40
|
+
|
41
|
+
res = http.request(req)
|
42
|
+
case res
|
43
|
+
when Net::HTTPSuccess
|
44
|
+
rooms = JSON.parse(res.body)
|
45
|
+
room = rooms['rooms'].select { |x| x['name'] == room }
|
46
|
+
rooms.empty? ? nil : room.first['id']
|
47
|
+
else
|
48
|
+
raise res.error!
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def speak(room, message)
|
53
|
+
room_id = find_room_id_by_name(room)
|
54
|
+
raise "No such room: #{room}." unless room_id
|
55
|
+
|
56
|
+
url = URI.parse("#{base_url}/room/#{room_id}/speak.json")
|
57
|
+
|
58
|
+
http = Net::HTTP.new(url.host, url.port)
|
59
|
+
http.use_ssl = true if @options[:ssl]
|
60
|
+
|
61
|
+
req = Net::HTTP::Post.new(url.path)
|
62
|
+
req.basic_auth(@options[:token], 'X')
|
63
|
+
req.set_content_type('application/json')
|
64
|
+
req.body = { 'message' => { 'body' => message } }.to_json
|
65
|
+
|
66
|
+
res = http.request(req)
|
67
|
+
case res
|
68
|
+
when Net::HTTPSuccess
|
69
|
+
true
|
70
|
+
else
|
71
|
+
raise res.error!
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
module God
|
78
|
+
module Contacts
|
79
|
+
|
80
|
+
class Campfire < Contact
|
81
|
+
class << self
|
82
|
+
attr_accessor :subdomain, :token, :room, :ssl
|
83
|
+
attr_accessor :format
|
84
|
+
end
|
85
|
+
|
86
|
+
self.ssl = false
|
87
|
+
|
88
|
+
self.format = lambda do |message, time, priority, category, host|
|
89
|
+
"[#{time.strftime('%H:%M:%S')}] #{host} - #{message}"
|
90
|
+
end
|
91
|
+
|
92
|
+
attr_accessor :subdomain, :token, :room, :ssl
|
93
|
+
|
94
|
+
def valid?
|
95
|
+
valid = true
|
96
|
+
valid &= complain("Attribute 'subdomain' must be specified", self) unless arg(:subdomain)
|
97
|
+
valid &= complain("Attribute 'token' must be specified", self) unless arg(:token)
|
98
|
+
valid &= complain("Attribute 'room' must be specified", self) unless arg(:room)
|
99
|
+
valid
|
100
|
+
end
|
101
|
+
|
102
|
+
def notify(message, time, priority, category, host)
|
103
|
+
body = Campfire.format.call(message, time, priority, category, host)
|
104
|
+
|
105
|
+
conn = Marshmallow::Connection.new(
|
106
|
+
:subdomain => arg(:subdomain),
|
107
|
+
:token => arg(:token),
|
108
|
+
:ssl => arg(:ssl)
|
109
|
+
)
|
110
|
+
|
111
|
+
conn.speak(arg(:room), body)
|
112
|
+
|
113
|
+
self.info = "notified campfire: #{arg(:subdomain)}"
|
114
|
+
rescue Object => e
|
115
|
+
applog(nil, :info, "failed to notify campfire: #{e.message}")
|
116
|
+
applog(nil, :debug, e.backtrace.join("\n"))
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# Send a notice to an email address.
|
2
|
+
#
|
3
|
+
# to_email - The String email address to which the email will be sent.
|
4
|
+
# to_name - The String name corresponding to the recipient.
|
5
|
+
# from_email - The String email address from which the email will be sent.
|
6
|
+
# from_name - The String name corresponding to the sender.
|
7
|
+
# delivery_method - The Symbol delivery method. [ :smtp | :sendmail ]
|
8
|
+
# (default: :smtp).
|
9
|
+
#
|
10
|
+
# === SMTP Options (when delivery_method = :smtp) ===
|
11
|
+
# server_host - The String hostname of the SMTP server (default: localhost).
|
12
|
+
# server_port - The Integer port of the SMTP server (default: 25).
|
13
|
+
# server_auth - The Symbol authentication method. Possible values:
|
14
|
+
# [ nil | :plain | :login | :cram_md5 ]
|
15
|
+
# The default is nil, which means no authentication. To
|
16
|
+
# enable authentication, pass the appropriate symbol and
|
17
|
+
# then pass the appropriate SMTP Auth Options (below).
|
18
|
+
#
|
19
|
+
# === SMTP Auth Options (when server_auth != nil) ===
|
20
|
+
# server_domain - The String domain.
|
21
|
+
# server_user - The String username.
|
22
|
+
# server_password - The String password.
|
23
|
+
#
|
24
|
+
# === Sendmail Options (when delivery_method = :sendmail) ===
|
25
|
+
# sendmail_path - The String path to the sendmail executable
|
26
|
+
# (default: "/usr/sbin/sendmail").
|
27
|
+
# sendmail_args - The String args to send to sendmail (default "-i -t").
|
28
|
+
|
29
|
+
require 'time'
|
30
|
+
require 'net/smtp'
|
31
|
+
|
32
|
+
module God
|
33
|
+
module Contacts
|
34
|
+
|
35
|
+
class Email < Contact
|
36
|
+
class << self
|
37
|
+
attr_accessor :to_email, :to_name, :from_email, :from_name,
|
38
|
+
:delivery_method, :server_host, :server_port,
|
39
|
+
:server_auth, :server_domain, :server_user,
|
40
|
+
:server_password, :sendmail_path, :sendmail_args
|
41
|
+
attr_accessor :format
|
42
|
+
end
|
43
|
+
|
44
|
+
self.from_email = 'god@example.com'
|
45
|
+
self.from_name = 'God Process Monitoring'
|
46
|
+
self.delivery_method = :smtp
|
47
|
+
self.server_auth = nil
|
48
|
+
self.server_host = 'localhost'
|
49
|
+
self.server_port = 25
|
50
|
+
self.sendmail_path = '/usr/sbin/sendmail'
|
51
|
+
self.sendmail_args = '-i -t'
|
52
|
+
|
53
|
+
self.format = lambda do |name, from_email, from_name, to_email, to_name, message, time, priority, category, host|
|
54
|
+
<<-EOF
|
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)}.#{$$}.#{from_email}>
|
60
|
+
|
61
|
+
Message: #{message}
|
62
|
+
Host: #{host}
|
63
|
+
Priority: #{priority}
|
64
|
+
Category: #{category}
|
65
|
+
EOF
|
66
|
+
end
|
67
|
+
|
68
|
+
attr_accessor :to_email, :to_name, :from_email, :from_name,
|
69
|
+
:delivery_method, :server_host, :server_port,
|
70
|
+
:server_auth, :server_domain, :server_user,
|
71
|
+
:server_password, :sendmail_path, :sendmail_args
|
72
|
+
|
73
|
+
def valid?
|
74
|
+
valid = true
|
75
|
+
valid &= complain("Attribute 'to_email' must be specified", self) unless arg(:to_email)
|
76
|
+
valid &= complain("Attribute 'delivery_method' must be one of [ :smtp | :sendmail ]", self) unless [:smtp, :sendmail].include?(arg(:delivery_method))
|
77
|
+
if arg(:delivery_method) == :smtp
|
78
|
+
valid &= complain("Attribute 'server_host' must be specified", self) unless arg(:server_host)
|
79
|
+
valid &= complain("Attribute 'server_port' must be specified", self) unless arg(:server_port)
|
80
|
+
if arg(:server_auth)
|
81
|
+
valid &= complain("Attribute 'server_domain' must be specified", self) unless arg(:server_domain)
|
82
|
+
valid &= complain("Attribute 'server_user' must be specified", self) unless arg(:server_user)
|
83
|
+
valid &= complain("Attribute 'server_password' must be specified", self) unless arg(:server_password)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
valid
|
87
|
+
end
|
88
|
+
|
89
|
+
def notify(message, time, priority, category, host)
|
90
|
+
body = Email.format.call(self.name, arg(:from_email), arg(:from_name),
|
91
|
+
arg(:to_email), arg(:to_name), message, time,
|
92
|
+
priority, category, host)
|
93
|
+
|
94
|
+
case arg(:delivery_method)
|
95
|
+
when :smtp
|
96
|
+
notify_smtp(body)
|
97
|
+
when :sendmail
|
98
|
+
notify_sendmail(body)
|
99
|
+
end
|
100
|
+
|
101
|
+
self.info = "sent email to #{arg(:to_email)} via #{arg(:delivery_method).to_s}"
|
102
|
+
rescue Object => e
|
103
|
+
applog(nil, :info, "failed to send email to #{arg(:to_email)} via #{arg(:delivery_method).to_s}: #{e.message}")
|
104
|
+
applog(nil, :debug, e.backtrace.join("\n"))
|
105
|
+
end
|
106
|
+
|
107
|
+
def notify_smtp(mail)
|
108
|
+
args = [arg(:server_host), arg(:server_port)]
|
109
|
+
if arg(:server_auth)
|
110
|
+
args << arg(:server_domain)
|
111
|
+
args << arg(:server_user)
|
112
|
+
args << arg(:server_password)
|
113
|
+
args << arg(:server_auth)
|
114
|
+
end
|
115
|
+
|
116
|
+
Net::SMTP.start(*args) do |smtp|
|
117
|
+
smtp.send_message(mail, arg(:from_email), arg(:to_email))
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def notify_sendmail(mail)
|
122
|
+
IO.popen("#{arg(:sendmail_path)} #{arg(:sendmail_args)}","w+") do |sm|
|
123
|
+
sm.print(mail.gsub(/\r/, ''))
|
124
|
+
sm.flush
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# Send a notice to a Hipchat room (http://hipchat.com).
|
2
|
+
#
|
3
|
+
# token - The String token used for authentication.
|
4
|
+
# room - The String room name to which the message should be sent.
|
5
|
+
# ssl - A Boolean determining whether or not to use SSL
|
6
|
+
# (default: false).
|
7
|
+
# from - The String representing who the message should be sent as.
|
8
|
+
|
9
|
+
require 'net/http'
|
10
|
+
require 'net/https'
|
11
|
+
|
12
|
+
CONTACT_DEPS[:hipchat] = ['json']
|
13
|
+
CONTACT_DEPS[:hipchat].each do |d|
|
14
|
+
require d
|
15
|
+
end
|
16
|
+
|
17
|
+
module Marshmallow
|
18
|
+
class Connection
|
19
|
+
def initialize(options)
|
20
|
+
raise "Required option :token not set." unless options[:token]
|
21
|
+
@options = options
|
22
|
+
end
|
23
|
+
|
24
|
+
def base_url
|
25
|
+
scheme = @options[:ssl] ? 'https' : 'http'
|
26
|
+
"#{scheme}://api.hipchat.com/v1/rooms"
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_room_id_by_name(room_name)
|
30
|
+
url = URI.parse("#{base_url}/list?format=json&auth_token=#{@options[:token]}")
|
31
|
+
http = Net::HTTP.new(url.host, url.port)
|
32
|
+
http.use_ssl = true if @options[:ssl]
|
33
|
+
|
34
|
+
req = Net::HTTP::Get.new(url.request_uri)
|
35
|
+
req.set_content_type('application/json')
|
36
|
+
|
37
|
+
res = http.request(req)
|
38
|
+
case res
|
39
|
+
when Net::HTTPSuccess
|
40
|
+
rooms = JSON.parse(res.body)
|
41
|
+
room = rooms['rooms'].select { |x| x['name'] == room_name }
|
42
|
+
rooms.empty? ? nil : room.first['room_id'].to_i
|
43
|
+
else
|
44
|
+
raise res.error!
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def speak(room, message)
|
49
|
+
room_id = find_room_id_by_name(room)
|
50
|
+
puts "in spark: room_id = #{room_id}"
|
51
|
+
raise "No such room: #{room}." unless room_id
|
52
|
+
|
53
|
+
escaped_message = URI.escape(message)
|
54
|
+
|
55
|
+
url = URI.parse("#{base_url}/message?message_format=text&format=json&auth_token=#{@options[:token]}&from=#{@options[:from]}&room_id=#{room}&message=#{escaped_message}")
|
56
|
+
|
57
|
+
http = Net::HTTP.new(url.host, url.port)
|
58
|
+
http.use_ssl = true if @options[:ssl]
|
59
|
+
|
60
|
+
req = Net::HTTP::Post.new(url.request_uri)
|
61
|
+
req.set_content_type('application/json')
|
62
|
+
res = http.request(req)
|
63
|
+
case res
|
64
|
+
when Net::HTTPSuccess
|
65
|
+
true
|
66
|
+
else
|
67
|
+
raise res.error!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
module God
|
74
|
+
module Contacts
|
75
|
+
|
76
|
+
class Hipchat < Contact
|
77
|
+
class << self
|
78
|
+
attr_accessor :token, :room, :ssl, :from
|
79
|
+
attr_accessor :format
|
80
|
+
end
|
81
|
+
|
82
|
+
self.ssl = false
|
83
|
+
|
84
|
+
self.format = lambda do |message, time, priority, category, host|
|
85
|
+
"[#{time.strftime('%H:%M:%S')}] #{host} - #{message}"
|
86
|
+
end
|
87
|
+
|
88
|
+
attr_accessor :token, :room, :ssl, :from
|
89
|
+
|
90
|
+
def valid?
|
91
|
+
valid = true
|
92
|
+
valid &= complain("Attribute 'token' must be specified", self) unless arg(:token)
|
93
|
+
valid &= complain("Attribute 'room' must be specified", self) unless arg(:room)
|
94
|
+
valid &= complain("Attribute 'from' must be specified", self) unless arg(:from)
|
95
|
+
valid
|
96
|
+
end
|
97
|
+
|
98
|
+
def notify(message, time, priority, category, host)
|
99
|
+
body = Hipchat.format.call(message, time, priority, category, host)
|
100
|
+
|
101
|
+
conn = Marshmallow::Connection.new(
|
102
|
+
:token => arg(:token),
|
103
|
+
:ssl => arg(:ssl),
|
104
|
+
:from => arg(:from)
|
105
|
+
)
|
106
|
+
|
107
|
+
conn.speak(arg(:room), body)
|
108
|
+
|
109
|
+
self.info = "notified hipchat: #{arg(:room)}"
|
110
|
+
rescue Object => e
|
111
|
+
applog(nil, :info, "failed to notify hipchat: #{e.message}")
|
112
|
+
applog(nil, :debug, e.backtrace.join("\n"))
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Send a notice to a Jabber address.
|
2
|
+
#
|
3
|
+
# host - The String hostname of the Jabber server.
|
4
|
+
# port - The Integer port of the Jabber server (default: 5222).
|
5
|
+
# from_jid - The String Jabber ID of the sender.
|
6
|
+
# password - The String password of the sender.
|
7
|
+
# to_jid - The String Jabber ID of the recipient.
|
8
|
+
# subject - The String subject of the message (default: "God Notification").
|
9
|
+
|
10
|
+
CONTACT_DEPS[:jabber] = ['xmpp4r']
|
11
|
+
CONTACT_DEPS[:jabber].each do |d|
|
12
|
+
require d
|
13
|
+
end
|
14
|
+
|
15
|
+
module God
|
16
|
+
module Contacts
|
17
|
+
|
18
|
+
class Jabber < Contact
|
19
|
+
class << self
|
20
|
+
attr_accessor :host, :port, :from_jid, :password, :to_jid, :subject
|
21
|
+
attr_accessor :format
|
22
|
+
end
|
23
|
+
|
24
|
+
self.port = 5222
|
25
|
+
self.subject = 'God Notification'
|
26
|
+
|
27
|
+
self.format = lambda do |message, time, priority, category, host|
|
28
|
+
text = "Message: #{message}\n"
|
29
|
+
text += "Host: #{host}\n" if host
|
30
|
+
text += "Priority: #{priority}\n" if priority
|
31
|
+
text += "Category: #{category}\n" if category
|
32
|
+
text
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_accessor :host, :port, :from_jid, :password, :to_jid, :subject
|
36
|
+
|
37
|
+
def valid?
|
38
|
+
valid = true
|
39
|
+
valid &= complain("Attribute 'host' must be specified", self) unless arg(:host)
|
40
|
+
valid &= complain("Attribute 'port' must be specified", self) unless arg(:port)
|
41
|
+
valid &= complain("Attribute 'from_jid' must be specified", self) unless arg(:from_jid)
|
42
|
+
valid &= complain("Attribute 'to_jid' must be specified", self) unless arg(:to_jid)
|
43
|
+
valid &= complain("Attribute 'password' must be specified", self) unless arg(:password)
|
44
|
+
valid
|
45
|
+
end
|
46
|
+
|
47
|
+
def notify(message, time, priority, category, host)
|
48
|
+
body = Jabber.format.call(message, time, priority, category, host)
|
49
|
+
|
50
|
+
message = ::Jabber::Message.new(arg(:to_jid), body)
|
51
|
+
message.set_type(:normal)
|
52
|
+
message.set_id('1')
|
53
|
+
message.set_subject(arg(:subject))
|
54
|
+
|
55
|
+
jabber_id = ::Jabber::JID.new("#{arg(:from_jid)}/God")
|
56
|
+
|
57
|
+
client = ::Jabber::Client.new(jabber_id)
|
58
|
+
client.connect(arg(:host), arg(:port))
|
59
|
+
client.auth(arg(:password))
|
60
|
+
client.send(message)
|
61
|
+
client.close
|
62
|
+
|
63
|
+
self.info = "sent jabber message to #{self.to_jid}"
|
64
|
+
rescue Object => e
|
65
|
+
if e.respond_to?(:message)
|
66
|
+
applog(nil, :info, "failed to send jabber message to #{arg(:to_jid)}: #{e.message}")
|
67
|
+
else
|
68
|
+
applog(nil, :info, "failed to send jabber message to #{arg(:to_jid)}: #{e.class}")
|
69
|
+
end
|
70
|
+
applog(nil, :debug, e.backtrace.join("\n"))
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|