god 0.10.1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,124 +1,73 @@
1
- # To add Jabber notifications you must have xmpp4r gem installed.
2
- # Configure your watches like this:
1
+ # Send a notice to a Jabber address.
3
2
  #
4
- # God::Contacts::Jabber.settings = { :jabber_id => 'sender@example.com',
5
- # :password => 'secret' }
6
- # God.contact(:jabber) do |c|
7
- # c.name = 'Tester'
8
- # c.jabber_id = 'receiver@example.com'
9
- # c.group = 'developers'
10
- # end
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").
11
9
 
12
- module XMPP4R
13
- require 'xmpp4r'
14
- include Jabber
10
+ CONTACT_DEPS[:jabber] = ['xmpp4r']
11
+ CONTACT_DEPS[:jabber].each do |d|
12
+ require d
15
13
  end
16
14
 
17
15
  module God
18
16
  module Contacts
19
- class Jabber < Contact
17
+
18
+ class Jabber < Contact
20
19
  class << self
21
- attr_accessor :settings, :format, :client
20
+ attr_accessor :host, :port, :from_jid, :password, :to_jid, :subject
21
+ attr_accessor :format
22
22
  end
23
-
24
- self.format = lambda do |message, priority, category, host|
23
+
24
+ self.port = 5222
25
+ self.subject = 'God Notification'
26
+
27
+ self.format = lambda do |message, time, priority, category, host|
25
28
  text = "Message: #{message}\n"
26
29
  text += "Host: #{host}\n" if host
27
30
  text += "Priority: #{priority}\n" if priority
28
31
  text += "Category: #{category}\n" if category
29
- return text
32
+ text
30
33
  end
31
-
32
- attr_accessor :jabber_id
33
-
34
+
35
+ attr_accessor :host, :port, :from_jid, :password, :to_jid, :subject
36
+
34
37
  def valid?
35
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
36
45
  end
37
-
46
+
38
47
  def notify(message, time, priority, category, host)
39
- connect
40
-
41
- body = Jabber.format.call message, priority, category, host
42
-
43
- message = XMPP4R::Message::new self.jabber_id, body
44
- message.set_type :normal
45
- message.set_id '1'
46
- message.set_subject 'God'
47
-
48
- self.send!(message)
49
-
50
- self.info = "sent jabber message to #{self.jabber_id}"
51
- rescue => e
52
- puts e.message
53
- puts e.backtrace.join("\n")
54
-
55
- self.info = "failed to send jabber message to #{self.jabber_id}: #{e.message}"
56
- end
57
-
58
- def send!(msg)
59
- attempts = 0
60
- begin
61
- attempts += 1
62
- client.send(msg)
63
- rescue Errno::EPIPE, IOError => e
64
- sleep 1
65
- disconnect!
66
- reconnect!
67
- retry unless attempts > 3
68
- raise e
69
- rescue Errno::ECONNRESET => e
70
- sleep (attempts^2) * 60 + 60
71
- disconnect!
72
- reconnect!
73
- retry unless attempts > 3
74
- raise e
75
- end
76
- end
77
-
78
- def connect
79
- connect! unless connected?
80
- end
81
-
82
- def connected?
83
- connected = client.respond_to?(:is_connected?) && client.is_connected?
84
- return connected
85
- end
86
-
87
- def connect!
88
- disconnect! if connected?
48
+ body = Jabber.format.call(message, time, priority, category, host)
89
49
 
90
- @connect_mutex ||= Mutex.new
91
- # don't try to connect if another thread is already connecting.
92
- return if @connect_mutex.locked?
93
- @connect_mutex.lock
94
-
95
- jabber_id = XMPP4R::JID::new "#{Jabber.settings[:jabber_id]}/God"
96
- jabber_client = XMPP4R::Client::new jabber_id
97
- jabber_client.connect Jabber.settings[:host]
98
- jabber_client.auth Jabber.settings[:password]
99
- self.client = jabber_client
100
-
101
- @connect_mutex.unlock
102
- end
103
-
104
- def disconnect!
105
- if client.respond_to?(:is_connected?) && client.is_connected?
106
- begin
107
- client.close
108
- rescue Errno::EPIPE, IOError => e
109
- self.info "Failed to disconnect: #{e}"
110
- nil
111
- end
112
- end
113
- client = nil
114
- end
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))
115
54
 
116
- def client
117
- Jabber.client
118
- end
55
+ jabber_id = ::Jabber::JID.new("#{arg(:from_jid)}/God")
119
56
 
120
- def client=(jc)
121
- Jabber.client = jc
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"))
122
71
  end
123
72
 
124
73
  end
@@ -1,38 +1,19 @@
1
- # For Prowl notifications you need the 'prowly' gem
2
- # (gem install prowly)
1
+ # Send a notice to Prowl (http://prowl.weks.net/).
3
2
  #
4
- # Configure your watches like this:
5
- #
6
- # God.contact(:prowl) do |c|
7
- # c.name = 'georgette'
8
- # c.apikey = 'ffffffffffffffffffffffffffffffffffffffff'
9
- # c.group = 'developers'
10
- # end
11
- #
12
- #
13
- # God.contact(:prowl) do |c|
14
- # c.name = 'johnny'
15
- # c.apikey = 'ffffffffffffffffffffffffffffffffffffffff'
16
- # c.group = 'developers'
17
- # end
18
- #
19
- #
20
- # Define a transition for the process running event
21
- #
22
- # w.transition(:up, :start) do |on|
23
- # on.condition(:process_running) do |c|
24
- # c.running = true
25
- # c.notify = 'developers'
26
- # end
27
- # end
3
+ # apikey - The String API key.
28
4
 
29
- require 'prowly'
5
+ CONTACT_DEPS[:prowl] = ['prowly']
6
+ CONTACT_DEPS[:prowl].each do |d|
7
+ require d
8
+ end
30
9
 
31
10
  module God
32
11
  module Contacts
33
12
  class Prowl < Contact
34
13
 
35
- attr_accessor :apikey
14
+ class << self
15
+ attr_accessor :apikey
16
+ end
36
17
 
37
18
  def valid?
38
19
  valid = true
@@ -40,28 +21,27 @@ module God
40
21
  valid
41
22
  end
42
23
 
24
+ attr_accessor :apikey
25
+
43
26
  def notify(message, time, priority, category, host)
44
- begin
45
- result = Prowly.notify do |n|
46
- n.apikey = self.apikey
47
- n.priority = map_priority(priority.to_i)
48
- n.application = category || "God"
49
- n.event = "on " + host.to_s
50
- n.description = message.to_s + " at " + time.to_s
51
- end
27
+ result = Prowly.notify do |n|
28
+ n.apikey = arg(:apikey)
29
+ n.priority = map_priority(priority.to_i)
30
+ n.application = category || "God"
31
+ n.event = "on " + host.to_s
32
+ n.description = message.to_s + " at " + time.to_s
33
+ end
52
34
 
53
- if result.succeeded?
54
- self.info = "sent prowl notification to #{self.name}"
55
- else
56
- self.info = "failed to send prowl notification to #{self.name}: #{result.message}"
57
- end
35
+ if result.succeeded?
36
+ self.info = "sent prowl notification to #{self.name}"
37
+ else
38
+ self.info = "failed to send prowl notification to #{self.name}: #{result.message}"
58
39
  end
59
40
  rescue Object => e
60
- self.info = "failed to send prowl notification to #{self.name}: #{e.message}"
41
+ applog(nil, :info, "failed to send prowl notification to #{self.name}: #{e.message}")
42
+ applog(nil, :debug, e.backtrace.join("\n"))
61
43
  end
62
44
 
63
- private
64
-
65
45
  def map_priority(priority)
66
46
  case priority
67
47
  when 1 then Prowly::Notification::Priority::EMERGENCY
@@ -74,4 +54,4 @@ module God
74
54
  end
75
55
  end
76
56
  end
77
- end
57
+ end
@@ -1,33 +1,19 @@
1
- # Configure your Scout client key:
1
+ # Send a notice to Scout (http://scoutapp.com/).
2
2
  #
3
- # God::Contacts::Scout.client_key = '1qpw29ie38ur37yt5
4
- #
5
- # A client key is configured per god process. Inside this God process,
6
- # you can create multiple Scout 'contacts' - which are actually Scout
7
- # plugins. This allows you to use Scout's UI to configure who gets
8
- # notifications for each plugin, and to disable notifications when you
9
- # go on vacation, etc.
10
- #
11
- # God.contact(:scout) do |c|
12
- # c.name = 'scout_delayed_job_plugin'
13
- # c.plugin_id = '12345
14
- # end
15
- #
16
- # God.contact(:scout) do |c|
17
- # c.name = 'scout_apache_plugin'
18
- # c.plugin_id = '54312
19
- # end
3
+ # client_key - The String client key.
4
+ # plugin_id - The String plugin id.
20
5
 
21
6
  require 'net/http'
22
7
  require 'uri'
23
8
 
24
9
  module God
25
10
  module Contacts
11
+
26
12
  class Scout < Contact
27
13
  class << self
28
- attr_accessor :client_key, :format
14
+ attr_accessor :client_key, :plugin_id
15
+ attr_accessor :format
29
16
  end
30
- attr_accessor :plugin_id
31
17
 
32
18
  self.format = lambda do |message, priority, category, host|
33
19
  text = "Message: #{message}\n"
@@ -37,28 +23,33 @@ module God
37
23
  return text
38
24
  end
39
25
 
26
+ attr_accessor :client_key, :plugin_id
27
+
40
28
  def valid?
41
29
  valid = true
30
+ valid &= complain("Attribute 'client_key' must be specified", self) unless arg(:client_key)
31
+ valid &= complain("Attribute 'plugin_id' must be specified", self) unless arg(:plugin_id)
32
+ valid
42
33
  end
43
34
 
44
35
  def notify(message, time, priority, category, host)
45
- begin
46
- data = {
47
- :client_key => Scout.client_key,
48
- :plugin_id => plugin_id,
49
- :format => 'xml',
50
- 'alert[subject]' => message,
51
- 'alert[body]' => Scout.format.call(message, priority, category, host)
52
- }
36
+ data = {
37
+ :client_key => arg(:client_key),
38
+ :plugin_id => arg(:plugin_id),
39
+ :format => 'xml',
40
+ 'alert[subject]' => message,
41
+ 'alert[body]' => Scout.format.call(message, priority, category, host)
42
+ }
53
43
 
54
- uri = URI.parse('http://scoutapp.com/alerts/create')
55
- Net::HTTP.post_form(uri, data)
44
+ uri = URI.parse('http://scoutapp.com/alerts/create')
45
+ Net::HTTP.post_form(uri, data)
56
46
 
57
- self.info = "sent scout alert to plugin ##{plugin_id}"
58
- rescue => e
59
- self.info = "failed to send scout alert to plugin ##{plugin_id}: #{e.message}"
60
- end
47
+ self.info = "sent scout alert to plugin ##{plugin_id}"
48
+ rescue => e
49
+ applog(nil, :info, "failed to send scout alert to plugin ##{plugin_id}: #{e.message}")
50
+ applog(nil, :debug, e.backtrace.join("\n"))
61
51
  end
62
52
  end
53
+
63
54
  end
64
55
  end
@@ -1,37 +1,50 @@
1
- # For Twitter updates you need the 'twitter' gem
2
- # (gem install twitter)
1
+ # Send a notice to a Twitter account (http://twitter.com/).
3
2
  #
4
- # Configure your watches like this:
5
- #
6
- # God::Contacts::Twitter.settings = { :username => 'sender@example.com',
7
- # :password => 'secret' }
8
- # God.contact(:twitter) do |c|
9
- # c.name = 'Tester'
10
- # c.group = 'developers'
11
- # end
3
+ # consumer_token - The String OAuth consumer token (defaults to God's
4
+ # existing consumer token).
5
+ # consumer_secret - The String OAuth consumer secret (defaults to God's
6
+ # existing consumer secret).
7
+ # access_token - The String OAuth access token.
8
+ # access_secret - The String OAuth access secret.
12
9
 
13
- require 'twitter'
10
+ CONTACT_DEPS[:twitter] = ['twitter']
11
+ CONTACT_DEPS[:twitter].each do |d|
12
+ require d
13
+ end
14
14
 
15
15
  module God
16
16
  module Contacts
17
17
  class Twitter < Contact
18
18
  class << self
19
- attr_accessor :settings
19
+ attr_accessor :consumer_token, :consumer_secret,
20
+ :access_token, :access_secret
20
21
  end
21
22
 
23
+ self.consumer_token = 'gOhjax6s0L3mLeaTtBWPw'
24
+ self.consumer_secret = 'yz4gpAVXJHKxvsGK85tEyzQJ7o2FEy27H1KEWL75jfA'
25
+
22
26
  def valid?
23
27
  valid = true
28
+ valid &= complain("Attribute 'consumer_token' must be specified", self) unless arg(:consumer_token)
29
+ valid &= complain("Attribute 'consumer_secret' must be specified", self) unless arg(:consumer_secret)
30
+ valid &= complain("Attribute 'access_token' must be specified", self) unless arg(:access_token)
31
+ valid &= complain("Attribute 'access_secret' must be specified", self) unless arg(:access_secret)
32
+ valid
24
33
  end
25
34
 
35
+ attr_accessor :consumer_token, :consumer_secret,
36
+ :access_token, :access_secret
37
+
26
38
  def notify(message, time, priority, category, host)
27
- begin
28
- ::Twitter::Base.new(Twitter.settings[:username],
29
- Twitter.settings[:password]).update(message)
30
-
31
- self.info = "sent twitter update as #{Twitter.settings[:username]}"
32
- rescue => e
33
- self.info = "failed to send twitter update from #{self.twitter_id}: #{e.message}"
34
- end
39
+ oauth = ::Twitter::OAuth.new(arg(:consumer_token), arg(:consumer_secret))
40
+ oauth.authorize_from_access(arg(:access_token), arg(:access_secret))
41
+
42
+ ::Twitter::Base.new(oauth).update(message)
43
+
44
+ self.info = "sent twitter update"
45
+ rescue => e
46
+ applog(nil, :info, "failed to send twitter update: #{e.message}")
47
+ applog(nil, :debug, e.backtrace.join("\n"))
35
48
  end
36
49
  end
37
50
  end
@@ -1,44 +1,70 @@
1
- # Configure your watches like this:
1
+ # Send a notice to a webhook.
2
2
  #
3
- # God.contact(:webhook) do |c|
4
- # c.name = 'Tester'
5
- # c.hook_url = 'http://hook/url'
6
- # end
3
+ # url - The String webhook URL.
4
+ # format - The Symbol format [ :form | :json ] (default: :form).
7
5
 
8
6
  require 'net/http'
9
7
  require 'uri'
10
8
 
9
+ CONTACT_DEPS[:webhook] = ['json']
10
+ CONTACT_DEPS[:webhook].each do |d|
11
+ require d
12
+ end
13
+
11
14
  module God
12
15
  module Contacts
13
16
 
14
17
  class Webhook < Contact
18
+ class << self
19
+ attr_accessor :url, :format
20
+ end
15
21
 
16
- attr_accessor :hook_url
22
+ self.format = :form
17
23
 
18
24
  def valid?
19
25
  valid = true
26
+ valid &= complain("Attribute 'url' must be specified", self) unless arg(:url)
27
+ valid &= complain("Attribute 'format' must be one of [ :form | :json ]", self) unless [:form, :json].include?(arg(:format))
28
+ valid
20
29
  end
21
30
 
31
+ attr_accessor :url, :format
32
+
22
33
  def notify(message, time, priority, category, host)
23
- begin
24
- data = {
25
- :message => message,
26
- :time => time,
27
- :priority => priority,
28
- :category => category,
29
- :host => host
30
- }
31
-
32
- uri = URI.parse(self.hook_url)
33
- Net::HTTP.post_form(uri, data)
34
-
35
- self.info = "sent webhook to #{self.hook_url}"
36
- rescue => e
37
- puts e.message
38
- puts e.backtrace.join("\n")
39
-
40
- self.info = "failed to send webhook to #{self.hook_url}: #{e.message}"
34
+ data = {
35
+ :message => message,
36
+ :time => time,
37
+ :priority => priority,
38
+ :category => category,
39
+ :host => host
40
+ }
41
+
42
+ uri = URI.parse(arg(:url))
43
+ http = Net::HTTP.new(uri.host, uri.port)
44
+
45
+ req = nil
46
+ res = nil
47
+
48
+ case arg(:format)
49
+ when :form
50
+ req = Net::HTTP::Post.new(uri.path)
51
+ req.set_form_data(data)
52
+ when :json
53
+ req = Net::HTTP::Post.new(uri.path)
54
+ req.body = data.to_json
55
+ end
56
+
57
+ res = http.request(req)
58
+
59
+ case res
60
+ when Net::HTTPSuccess
61
+ self.info = "sent webhook to #{arg(:url)}"
62
+ else
63
+ self.info = "failed to send webhook to #{arg(:url)}: #{res.error!}"
41
64
  end
65
+ rescue Object => e
66
+ applog(nil, :info, "failed to send email to #{arg(:url)}: #{e.message}")
67
+ applog(nil, :debug, e.backtrace.join("\n"))
42
68
  end
43
69
 
44
70
  end