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.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/Announce.txt +135 -0
  3. data/Gemfile +9 -0
  4. data/History.txt +469 -0
  5. data/LICENSE +22 -0
  6. data/README.md +37 -0
  7. data/Rakefile +185 -0
  8. data/TODO.md +37 -0
  9. data/bin/mcproc +134 -0
  10. data/doc/intro.asciidoc +20 -0
  11. data/doc/mcproc.asciidoc +1592 -0
  12. data/ext/god/.gitignore +5 -0
  13. data/ext/god/extconf.rb +56 -0
  14. data/ext/god/kqueue_handler.c +133 -0
  15. data/ext/god/netlink_handler.c +182 -0
  16. data/lib/god.rb +780 -0
  17. data/lib/god/behavior.rb +52 -0
  18. data/lib/god/behaviors/clean_pid_file.rb +21 -0
  19. data/lib/god/behaviors/clean_unix_socket.rb +21 -0
  20. data/lib/god/behaviors/notify_when_flapping.rb +51 -0
  21. data/lib/god/cli/command.rb +268 -0
  22. data/lib/god/cli/run.rb +170 -0
  23. data/lib/god/cli/version.rb +23 -0
  24. data/lib/god/compat19.rb +33 -0
  25. data/lib/god/condition.rb +96 -0
  26. data/lib/god/conditions/always.rb +36 -0
  27. data/lib/god/conditions/complex.rb +86 -0
  28. data/lib/god/conditions/cpu_usage.rb +80 -0
  29. data/lib/god/conditions/degrading_lambda.rb +52 -0
  30. data/lib/god/conditions/disk_usage.rb +32 -0
  31. data/lib/god/conditions/file_mtime.rb +28 -0
  32. data/lib/god/conditions/file_touched.rb +44 -0
  33. data/lib/god/conditions/flapping.rb +128 -0
  34. data/lib/god/conditions/http_response_code.rb +184 -0
  35. data/lib/god/conditions/lambda.rb +25 -0
  36. data/lib/god/conditions/memory_usage.rb +82 -0
  37. data/lib/god/conditions/process_exits.rb +66 -0
  38. data/lib/god/conditions/process_running.rb +63 -0
  39. data/lib/god/conditions/socket_responding.rb +142 -0
  40. data/lib/god/conditions/tries.rb +44 -0
  41. data/lib/god/configurable.rb +57 -0
  42. data/lib/god/contact.rb +114 -0
  43. data/lib/god/contacts/airbrake.rb +44 -0
  44. data/lib/god/contacts/campfire.rb +121 -0
  45. data/lib/god/contacts/email.rb +130 -0
  46. data/lib/god/contacts/hipchat.rb +117 -0
  47. data/lib/god/contacts/jabber.rb +75 -0
  48. data/lib/god/contacts/prowl.rb +57 -0
  49. data/lib/god/contacts/scout.rb +55 -0
  50. data/lib/god/contacts/sensu.rb +59 -0
  51. data/lib/god/contacts/slack.rb +98 -0
  52. data/lib/god/contacts/statsd.rb +46 -0
  53. data/lib/god/contacts/twitter.rb +51 -0
  54. data/lib/god/contacts/webhook.rb +74 -0
  55. data/lib/god/driver.rb +238 -0
  56. data/lib/god/errors.rb +24 -0
  57. data/lib/god/event_handler.rb +112 -0
  58. data/lib/god/event_handlers/dummy_handler.rb +13 -0
  59. data/lib/god/event_handlers/kqueue_handler.rb +17 -0
  60. data/lib/god/event_handlers/netlink_handler.rb +13 -0
  61. data/lib/god/logger.rb +109 -0
  62. data/lib/god/metric.rb +87 -0
  63. data/lib/god/process.rb +381 -0
  64. data/lib/god/registry.rb +32 -0
  65. data/lib/god/simple_logger.rb +59 -0
  66. data/lib/god/socket.rb +113 -0
  67. data/lib/god/sugar.rb +62 -0
  68. data/lib/god/sys_logger.rb +45 -0
  69. data/lib/god/system/portable_poller.rb +42 -0
  70. data/lib/god/system/process.rb +50 -0
  71. data/lib/god/system/slash_proc_poller.rb +92 -0
  72. data/lib/god/task.rb +552 -0
  73. data/lib/god/timeline.rb +25 -0
  74. data/lib/god/trigger.rb +43 -0
  75. data/lib/god/watch.rb +340 -0
  76. data/mcproc.gemspec +192 -0
  77. data/test/configs/child_events/child_events.god +44 -0
  78. data/test/configs/child_events/simple_server.rb +3 -0
  79. data/test/configs/child_polls/child_polls.god +37 -0
  80. data/test/configs/child_polls/simple_server.rb +12 -0
  81. data/test/configs/complex/complex.god +59 -0
  82. data/test/configs/complex/simple_server.rb +3 -0
  83. data/test/configs/contact/contact.god +118 -0
  84. data/test/configs/contact/simple_server.rb +3 -0
  85. data/test/configs/daemon_events/daemon_events.god +37 -0
  86. data/test/configs/daemon_events/simple_server.rb +8 -0
  87. data/test/configs/daemon_events/simple_server_stop.rb +11 -0
  88. data/test/configs/daemon_polls/daemon_polls.god +17 -0
  89. data/test/configs/daemon_polls/simple_server.rb +6 -0
  90. data/test/configs/degrading_lambda/degrading_lambda.god +31 -0
  91. data/test/configs/degrading_lambda/tcp_server.rb +15 -0
  92. data/test/configs/keepalive/keepalive.god +9 -0
  93. data/test/configs/keepalive/keepalive.rb +12 -0
  94. data/test/configs/lifecycle/lifecycle.god +25 -0
  95. data/test/configs/matias/matias.god +50 -0
  96. data/test/configs/real.rb +59 -0
  97. data/test/configs/running_load/running_load.god +16 -0
  98. data/test/configs/stop_options/simple_server.rb +12 -0
  99. data/test/configs/stop_options/stop_options.god +39 -0
  100. data/test/configs/stress/simple_server.rb +3 -0
  101. data/test/configs/stress/stress.god +15 -0
  102. data/test/configs/task/logs/.placeholder +0 -0
  103. data/test/configs/task/task.god +26 -0
  104. data/test/configs/test.rb +61 -0
  105. data/test/configs/usr1_trapper.rb +10 -0
  106. data/test/helper.rb +172 -0
  107. data/test/suite.rb +6 -0
  108. data/test/test_airbrake.rb +14 -0
  109. data/test/test_behavior.rb +18 -0
  110. data/test/test_campfire.rb +22 -0
  111. data/test/test_condition.rb +52 -0
  112. data/test/test_conditions_disk_usage.rb +50 -0
  113. data/test/test_conditions_http_response_code.rb +109 -0
  114. data/test/test_conditions_process_running.rb +40 -0
  115. data/test/test_conditions_socket_responding.rb +176 -0
  116. data/test/test_conditions_tries.rb +67 -0
  117. data/test/test_contact.rb +109 -0
  118. data/test/test_driver.rb +26 -0
  119. data/test/test_email.rb +34 -0
  120. data/test/test_event_handler.rb +82 -0
  121. data/test/test_god.rb +710 -0
  122. data/test/test_god_system.rb +201 -0
  123. data/test/test_handlers_kqueue_handler.rb +16 -0
  124. data/test/test_hipchat.rb +23 -0
  125. data/test/test_jabber.rb +29 -0
  126. data/test/test_logger.rb +55 -0
  127. data/test/test_metric.rb +74 -0
  128. data/test/test_process.rb +263 -0
  129. data/test/test_prowl.rb +15 -0
  130. data/test/test_registry.rb +15 -0
  131. data/test/test_sensu.rb +11 -0
  132. data/test/test_slack.rb +57 -0
  133. data/test/test_socket.rb +34 -0
  134. data/test/test_statsd.rb +22 -0
  135. data/test/test_sugar.rb +42 -0
  136. data/test/test_system_portable_poller.rb +17 -0
  137. data/test/test_system_process.rb +30 -0
  138. data/test/test_task.rb +246 -0
  139. data/test/test_timeline.rb +37 -0
  140. data/test/test_trigger.rb +63 -0
  141. data/test/test_watch.rb +286 -0
  142. data/test/test_webhook.rb +22 -0
  143. 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