flapjack 0.6.46 → 0.6.47

Sign up to get free protection for your applications and to get access to all the features.
@@ -35,7 +35,6 @@ config = Flapjack::Configuration.new
35
35
  config.load(options.config)
36
36
  @config_env = config.all
37
37
  @redis_options = config.for_redis
38
- puts @redis_options.inspect
39
38
 
40
39
  if @config_env.nil? || @config_env.empty?
41
40
  puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
@@ -95,7 +94,7 @@ def process_input(redis)
95
94
  end
96
95
 
97
96
  def main
98
- redis = Redis.new(@redis_options.merge(:driver => 'ruby'))
97
+ redis = Redis.new(@redis_options)
99
98
 
100
99
  while true
101
100
  process_input(redis)
@@ -64,14 +64,12 @@ when "import-contacts"
64
64
 
65
65
  if contacts && contacts.is_a?(Enumerable) && contacts.any? {|e| !e['id'].nil?}
66
66
  @persistence = Redis.new(redis_options)
67
- @persistence.multi do
68
- contacts.each do |contact|
69
- unless contact['id']
70
- puts "Contact not imported as it has no id: " + contact.inspect
71
- next
72
- end
73
- Flapjack::Data::Contact.add(contact, :redis => @persistence)
67
+ contacts.each do |contact|
68
+ unless contact['id']
69
+ puts "Contact not imported as it has no id: " + contact.inspect
70
+ next
74
71
  end
72
+ Flapjack::Data::Contact.add(contact, :redis => @persistence)
75
73
  end
76
74
  @persistence.quit
77
75
  end
@@ -81,7 +79,6 @@ when "import-entities"
81
79
 
82
80
  if entities && entities.is_a?(Enumerable) && entities.any? {|e| !e['id'].nil?}
83
81
  @persistence = Redis.new(redis_options)
84
- @persistence.multi
85
82
  entities.each do |entity|
86
83
  unless entity['id']
87
84
  puts "Entity not imported as it has no id: " + entity.inspect
@@ -89,7 +86,6 @@ when "import-entities"
89
86
  end
90
87
  Flapjack::Data::Entity.add(entity, :redis => @persistence)
91
88
  end
92
- @persistence.exec
93
89
  @persistence.quit
94
90
  end
95
91
 
@@ -44,13 +44,11 @@ Feature: notifications
44
44
  When the SMS notification handler fails to send an SMS
45
45
  Then the user should not receive an SMS notification
46
46
 
47
- @email
48
47
  Scenario: Send a queued email notification
49
48
  Given a user email notification has been queued for entity 'example.com'
50
49
  When the email notification handler runs successfully
51
50
  Then the user should receive an email notification
52
51
 
53
- @email
54
52
  Scenario: Handle a failure to send a queued email notification
55
53
  Given a user email notification has been queued for entity 'example.com'
56
54
  When the email notification handler fails to send an email
@@ -1,6 +1,4 @@
1
1
 
2
- include Mail::Matchers
3
-
4
2
  # copied from flapjack-populator
5
3
  # TODO use Flapjack::Data::Contact.add
6
4
  def add_contact(contact = {})
@@ -125,57 +123,72 @@ end
125
123
 
126
124
  # TODO may need to get more complex, depending which SMS provider is used
127
125
  When /^the SMS notification handler runs successfully$/ do
128
- # returns success by default - currently matches all addresses, maybe load from config?
129
- stub_request(:get, /.*/)
130
- # TODO load config from cfg file instead?
131
- Flapjack::Gateways::Sms.instance_variable_set('@config', {'username' => 'abcd', 'password' => 'efgh'})
126
+ @request = stub_request(:get, /^#{Regexp.escape(Flapjack::Gateways::SmsMessagenet::MESSAGENET_URL)}/)
132
127
 
133
- lambda {
134
- Flapjack::Gateways::Sms.dispatch(@sms_notification, :logger => @logger, :redis => @redis)
135
- }.should_not raise_error
136
- @sms_sent = true
128
+ Flapjack::Gateways::SmsMessagenet.instance_variable_set('@config', {'username' => 'abcd', 'password' => 'efgh'})
129
+ Flapjack::Gateways::SmsMessagenet.instance_variable_set('@logger', @logger)
130
+ Flapjack::Gateways::SmsMessagenet.instance_variable_set('@sent', 0)
131
+ Flapjack::Gateways::SmsMessagenet.perform(@sms_notification)
137
132
  end
138
133
 
139
134
  When /^the SMS notification handler fails to send an SMS$/ do
140
- stub_request(:any, /.*/).to_return(:status => [500, "Internal Server Error"])
141
-
142
- lambda {
143
- Flapjack::Gateways::Sms.dispatch(@sms_notification, :logger => @logger, :redis => @redis)
144
- }.should raise_error
145
- @sms_sent = false
135
+ @request = stub_request(:get, /^#{Regexp.escape(Flapjack::Gateways::SmsMessagenet::MESSAGENET_URL)}/).to_return(:status => [500, "Internal Server Error"])
136
+ Flapjack::Gateways::SmsMessagenet.instance_variable_set('@config', {'username' => 'abcd', 'password' => 'efgh'})
137
+ Flapjack::Gateways::SmsMessagenet.instance_variable_set('@logger', @logger)
138
+ Flapjack::Gateways::SmsMessagenet.instance_variable_set('@sent', 0)
139
+ Flapjack::Gateways::SmsMessagenet.perform(@sms_notification)
146
140
  end
147
141
 
148
142
  When /^the email notification handler runs successfully$/ do
149
143
  Resque.redis = @redis
150
- Flapjack::Gateways::Email.bootstrap(:config => {})
151
- lambda {
152
- Flapjack::Gateways::Email.perform(@email_notification)
153
- }.should_not raise_error
144
+ Flapjack::Gateways::Email.bootstrap(:config => {'smtp_config' => {'host' => '127.0.0.1', 'port' => 2525}})
145
+ Flapjack::Gateways::Email.instance_variable_set('@logger', @logger)
146
+ Flapjack::Gateways::Email.instance_variable_set('@sent', 0)
147
+
148
+ # poor man's stubbing
149
+ EM::P::SmtpClient.class_eval {
150
+ def self.send(args = {})
151
+ me = MockEmailer.new
152
+ me.set_deferred_status :succeeded, OpenStruct.new(:code => 250)
153
+ me
154
+ end
155
+ }
156
+
157
+ Flapjack::Gateways::Email.perform(@email_notification)
154
158
  end
155
159
 
156
- # This doesn't work as I have it here -- sends a mail with an empty To: header instead.
157
- # Might have to introduce Rspec's stubs here to fake bad mailer behaviour -- or if mail sending
158
- # won't ever fail, don't test for failure?
159
160
  When /^the email notification handler fails to send an email$/ do
160
- pending
161
- lambda {
162
- @email_notification['address'] = nil
163
- Flapjack::Gateways::Email.perform(@email_notification)
164
- }.should_not raise_error
161
+ Resque.redis = @redis
162
+ Flapjack::Gateways::Email.bootstrap(:config => {'smtp_config' => {'host' => '127.0.0.1', 'port' => 2525}})
163
+ Flapjack::Gateways::Email.instance_variable_set('@logger', @logger)
164
+ Flapjack::Gateways::Email.instance_variable_set('@sent', 0)
165
+
166
+ # poor man's stubbing
167
+ EM::P::SmtpClient.class_eval {
168
+ def self.send(args = {})
169
+ me = MockEmailer.new
170
+ me.set_deferred_status :failed, OpenStruct.new(:code => 500)
171
+ me
172
+ end
173
+ }
174
+
175
+ Flapjack::Gateways::Email.perform(@email_notification)
165
176
  end
166
177
 
167
178
  Then /^the user should receive an SMS notification$/ do
168
- @sms_sent.should be_true
179
+ @request.should have_been_requested
180
+ Flapjack::Gateways::SmsMessagenet.instance_variable_get('@sent').should == 1
169
181
  end
170
182
 
171
183
  Then /^the user should receive an email notification$/ do
172
- have_sent_email.should be_true
184
+ Flapjack::Gateways::Email.instance_variable_get('@sent').should == 1
173
185
  end
174
186
 
175
187
  Then /^the user should not receive an SMS notification$/ do
176
- @sms_sent.should be_false
188
+ @request.should have_been_requested
189
+ Flapjack::Gateways::SmsMessagenet.instance_variable_get('@sent').should == 0
177
190
  end
178
191
 
179
192
  Then /^the user should not receive an email notification$/ do
180
- have_sent_email.should be_false
193
+ Flapjack::Gateways::Email.instance_variable_get('@sent').should == 0
181
194
  end
@@ -38,8 +38,9 @@ class MockLogger
38
38
  end
39
39
  end
40
40
 
41
- Mail.defaults do
42
- delivery_method :test
41
+ # poor man's stubbing
42
+ class MockEmailer
43
+ include EM::Deferrable
43
44
  end
44
45
 
45
46
  redis_opts = { :db => 14, :driver => :ruby }
@@ -79,10 +80,6 @@ Before('@resque') do
79
80
  ResqueSpec.reset!
80
81
  end
81
82
 
82
- Before('@email') do
83
- Mail::TestMailer.deliveries.clear
84
- end
85
-
86
83
  After('@time') do
87
84
  Delorean.back_to_the_present
88
85
  end
@@ -27,7 +27,7 @@ require 'flapjack/gateways/jabber'
27
27
  require 'flapjack/gateways/oobetet'
28
28
  require 'flapjack/gateways/pagerduty'
29
29
  require 'flapjack/gateways/email'
30
- require 'flapjack/gateways/sms'
30
+ require 'flapjack/gateways/sms_messagenet'
31
31
  require 'flapjack/gateways/web'
32
32
 
33
33
  module Flapjack
@@ -270,7 +270,7 @@ module Flapjack
270
270
  'pagerduty' => Flapjack::Gateways::Pagerduty,
271
271
  'oobetet' => Flapjack::Gateways::Oobetet,
272
272
  'email' => Flapjack::Gateways::Email,
273
- 'sms' => Flapjack::Gateways::Sms}
273
+ 'sms' => Flapjack::Gateways::SmsMessagenet}
274
274
 
275
275
 
276
276
  def pikelets(config_env)
@@ -36,24 +36,24 @@ module Flapjack
36
36
  redis.keys('contacts_for:*') )
37
37
  end
38
38
 
39
- def self.find_by_id(id, options = {})
39
+ def self.find_by_id(contact_id, options = {})
40
40
  raise "Redis connection not set" unless redis = options[:redis]
41
- raise "No id value passed" unless id
41
+ raise "No id value passed" unless contact_id
42
42
  logger = options[:logger]
43
43
 
44
- return unless redis.hexists("contact:#{id}", 'first_name')
44
+ return unless redis.hexists("contact:#{contact_id}", 'first_name')
45
45
 
46
- fn, ln, em = redis.hmget("contact:#{id}", 'first_name', 'last_name', 'email')
47
- me = redis.hgetall("contact_media:#{id}")
46
+ fn, ln, em = redis.hmget("contact:#{contact_id}", 'first_name', 'last_name', 'email')
47
+ me = redis.hgetall("contact_media:#{contact_id}")
48
48
 
49
49
  # similar to code in instance method pagerduty_credentials
50
50
  pc = nil
51
- if service_key = redis.hget("contact_media:#{id}", 'pagerduty')
52
- pc = redis.hgetall("contact_pagerduty:#{id}").merge('service_key' => service_key)
51
+ if service_key = redis.hget("contact_media:#{contact_id}", 'pagerduty')
52
+ pc = redis.hgetall("contact_pagerduty:#{contact_id}").merge('service_key' => service_key)
53
53
  end
54
54
 
55
55
  self.new(:first_name => fn, :last_name => ln,
56
- :email => em, :id => id, :media => me, :pagerduty_credentials => pc, :redis => redis )
56
+ :email => em, :id => contact_id, :media => me, :pagerduty_credentials => pc, :redis => redis )
57
57
  end
58
58
 
59
59
 
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'flapjack/data/contact'
4
+ require 'flapjack/data/tag'
4
5
 
5
6
  module Flapjack
6
7
 
@@ -8,7 +9,7 @@ module Flapjack
8
9
 
9
10
  class Entity
10
11
 
11
- attr_accessor :name, :id
12
+ attr_accessor :name, :id, :tags
12
13
 
13
14
  def self.all(options = {})
14
15
  raise "Redis connection not set" unless redis = options[:redis]
@@ -38,10 +39,14 @@ module Flapjack
38
39
  redis.sadd("contacts_for:#{entity['id']}", contact_id)
39
40
  }
40
41
  end
42
+ self.new(:name => entity['name'],
43
+ :id => entity['id'],
44
+ :redis => redis)
41
45
  else
42
46
  # empty string is the redis equivalent of a Ruby nil, i.e. key with
43
47
  # no value
44
48
  redis.set("entity_id:#{entity['name']}", '')
49
+ nil
45
50
  end
46
51
  end
47
52
 
@@ -102,6 +107,21 @@ module Flapjack
102
107
  checks.length
103
108
  end
104
109
 
110
+ def add_tags(*enum)
111
+ enum.each do |t|
112
+ Flapjack::Data::Tag.create("#{@tag_prefix}:#{t}", [@id], :redis => @redis)
113
+ @tags.add(t)
114
+ end
115
+ end
116
+
117
+ def delete_tags(*enum)
118
+ enum.each do |t|
119
+ tag = Flapjack::Data::Tag.find("#{@tag_prefix}:#{t}", :redis => @redis)
120
+ tag.delete(@id)
121
+ @tags.delete(t)
122
+ end
123
+ end
124
+
105
125
  private
106
126
 
107
127
  # NB: initializer should not be used directly -- instead one of the finder methods
@@ -111,6 +131,16 @@ module Flapjack
111
131
  raise "Entity name not set" unless @name = options[:name]
112
132
  @id = options[:id]
113
133
  @logger = options[:logger]
134
+
135
+ @tag_prefix = 'entity_tag'
136
+ @tags = ::Set.new
137
+ tag_data = @redis.keys("#{@tag_prefix}:*").inject([]) do |memo, entity_tag|
138
+ tag = Flapjack::Data::Tag.find(entity_tag, :redis => @redis)
139
+ memo << entity_tag.sub(%r(^#{@tag_prefix}:), '') if tag.include?(@id.to_s)
140
+ memo
141
+ end
142
+ @tags.merge(tag_data)
143
+
114
144
  end
115
145
 
116
146
  end
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'yajl'
4
+
3
5
  module Flapjack
4
6
  module Data
5
7
  class Event
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'set'
4
+ require 'redis'
5
+
6
+ module Flapjack
7
+ module Data
8
+
9
+ class Tag < ::Set
10
+
11
+ attr_accessor :name
12
+
13
+ def initialize(opts)
14
+ @name = opts[:name]
15
+ @redis = opts[:redis]
16
+ preset = @redis.smembers(@name)
17
+ enum = opts[:create] || []
18
+ @redis.sadd(@name, enum) unless enum.empty?
19
+ super(enum | preset)
20
+ end
21
+
22
+ def self.find(name, opts)
23
+ self.new(:name => name,
24
+ :redis => opts[:redis])
25
+ end
26
+
27
+ def self.create(name, enum = [], opts)
28
+ self.new(:name => name,
29
+ :create => enum,
30
+ :redis => opts[:redis])
31
+ end
32
+
33
+ def add(o)
34
+ @redis.sadd(@name, o) unless o.empty?
35
+ super(o)
36
+ end
37
+
38
+ def delete(o)
39
+ @redis.srem(@name, o)
40
+ super(o)
41
+ end
42
+
43
+ def merge(o)
44
+ @redis.sadd(@name, o) unless o.empty?
45
+ super(o)
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+
@@ -18,7 +18,7 @@ require 'flapjack/pikelet'
18
18
  require 'flapjack/redis_pool'
19
19
 
20
20
  require 'flapjack/gateways/email'
21
- require 'flapjack/gateways/sms'
21
+ require 'flapjack/gateways/sms_messagenet'
22
22
 
23
23
  module Flapjack
24
24
 
@@ -256,7 +256,7 @@ module Flapjack
256
256
  # TODO consider changing Resque jobs to use raw blpop like the others
257
257
  case media_type
258
258
  when :sms
259
- Resque.enqueue_to(@queues[:sms], Flapjack::Gateways::Sms, contents)
259
+ Resque.enqueue_to(@queues[:sms], Flapjack::Gateways::SmsMessagenet, contents)
260
260
  when :email
261
261
  Resque.enqueue_to(@queues[:email], Flapjack::Gateways::Email, contents)
262
262
  when :jabber
@@ -5,8 +5,10 @@ require 'erb'
5
5
  require 'haml'
6
6
  require 'socket'
7
7
 
8
- require 'flapjack/data/entity_check'
8
+ require 'em-synchrony'
9
+ require 'em/protocols/smtpclient'
9
10
 
11
+ require 'flapjack/data/entity_check'
10
12
  require 'flapjack/gateways/base'
11
13
 
12
14
  module Flapjack
@@ -19,24 +21,10 @@ module Flapjack
19
21
 
20
22
  alias_method :orig_bootstrap, :bootstrap
21
23
 
22
- # See https://github.com/mikel/mail/blob/master/lib/mail/mail.rb#L53
23
- # & https://github.com/mikel/mail/blob/master/spec/mail/configuration_spec.rb
24
- # for details of configuring mail gem. defaults to SMTP, localhost, port 25
25
24
  def bootstrap(opts = {})
26
25
  return if @bootstrapped
27
-
28
- sc = opts[:config].delete('smtp_config')
29
-
30
- if sc
31
- smtp_config = sc.keys.inject({}) do |ret,obj|
32
- ret[obj.to_sym] = sc[obj]
33
- ret
34
- end
35
-
36
- Mail.defaults {
37
- delivery_method :smtp, {:enable_starttls_auto => false}.merge(smtp_config)
38
- }
39
- end
26
+ @smtp_config = opts[:config].delete('smtp_config')
27
+ @sent = 0
40
28
  orig_bootstrap(opts)
41
29
  end
42
30
 
@@ -49,7 +37,6 @@ module Flapjack
49
37
  state = notification['state']
50
38
  summary = notification['summary']
51
39
  time = notification['time']
52
- entity, check = notification['event_id'].split(':')
53
40
 
54
41
  entity_check = Flapjack::Data::EntityCheck.for_event_id(notification['event_id'],
55
42
  :redis => ::Resque.redis)
@@ -63,37 +50,58 @@ module Flapjack
63
50
 
64
51
  headline = headline_map[notification_type] || ''
65
52
 
66
- subject = "#{headline}'#{check}' on #{entity}"
53
+ subject = "#{headline}'#{entity_check.check}' on #{entity_check.entity_name}"
67
54
  subject += " is #{state.upcase}" unless ['acknowledgement', 'test'].include?(notification_type)
68
55
 
69
56
  notification['subject'] = subject
70
57
 
71
- mail = prepare_email(notification, :logger => @logger,
72
- :in_scheduled_maintenance => entity_check.in_scheduled_maintenance?,
73
- :in_unscheduled_maintenance => entity_check.in_unscheduled_maintenance?)
74
- mail.deliver!
58
+ begin
59
+ host = @smtp_config ? @smtp_config['host'] : nil
60
+ port = @smtp_config ? @smtp_config['port'] : nil
61
+
62
+ fqdn = `/bin/hostname -f`.chomp
63
+ m_from = "flapjack@#{fqdn}"
64
+ logger.debug("flapjack_mailer: set from to #{m_from}")
65
+ m_reply_to = m_from
66
+ m_to = notification['address']
67
+
68
+ mail = prepare_email(notification,
69
+ :from => m_from, :to => m_to,
70
+ :in_scheduled_maintenance => entity_check.in_scheduled_maintenance?,
71
+ :in_unscheduled_maintenance => entity_check.in_unscheduled_maintenance?)
72
+
73
+ email = EM::P::SmtpClient.send(
74
+ :from => m_from,
75
+ :to => m_to,
76
+ :content => "#{mail.to_s}\r\n.\r\n",
77
+ :domain => fqdn,
78
+ :host => host || 'localhost',
79
+ :port => port || 25)
80
+
81
+ response = EM::Synchrony.sync(email)
82
+
83
+ # http://tools.ietf.org/html/rfc821#page-36 SMTP response codes
84
+ if response && response.respond_to?(:code) &&
85
+ ((response.code == 250) || (response.code == 251))
86
+ @logger.info "Email sending succeeded"
87
+ @sent += 1
88
+ else
89
+ @logger.info "Email sending failed"
90
+ end
91
+
92
+ @logger.info "Email response: #{response.inspect}"
93
+
94
+ rescue Exception => e
95
+ @logger.error "Error delivering email to #{mail.to}: #{e.message}"
96
+ @logger.error e.backtrace.join("\n")
97
+ end
75
98
  end
76
99
 
77
100
  end
78
101
 
79
102
  private
80
103
 
81
- def self.prepare_email(notification, opts)
82
-
83
- logger = opts[:logger]
84
-
85
- # not using socket and gethostname as that doesn't give you a fqdn.
86
- # see the facter issue: https://projects.puppetlabs.com/issues/3898
87
- fqdn = `/bin/hostname -f`.chomp
88
- m_from = "flapjack@#{fqdn}"
89
- logger.debug("flapjack_mailer: set from to #{m_from}")
90
- m_reply_to = m_from
91
-
92
- m_to = notification['address']
93
- m_subject = notification['subject']
94
-
95
- logger.debug("sending Flapjack::Notification::Email " +
96
- "#{notification['id']} to: #{m_to} subject: #{m_subject}")
104
+ def self.prepare_email(notification, opts = {})
97
105
 
98
106
  @notification_type = notification['notification_type']
99
107
  @contact_first_name = notification['contact_first_name']
@@ -105,6 +113,11 @@ module Flapjack
105
113
  @in_unscheduled_maintenance = opts[:in_unscheduled_maintenance]
106
114
  @in_scheduled_maintenance = opts[:in_scheduled_maintenance]
107
115
 
116
+ m_subject = notification['subject']
117
+
118
+ @logger.debug("sending Flapjack::Notification::Email " +
119
+ "#{notification['id']} to: #{opts[:to]} subject: #{m_subject}")
120
+
108
121
  text_template = ERB.new(File.read(File.dirname(__FILE__) +
109
122
  '/email/alert.text.erb'))
110
123
 
@@ -113,11 +126,13 @@ module Flapjack
113
126
 
114
127
  mail_scope = self
115
128
 
129
+ # this part is the only use of the mail gem -- maybe this can be done
130
+ # using standard library calls instead?
116
131
  mail = Mail.new do
117
- from m_from
118
- to m_to
132
+ from opts[:from]
133
+ to opts[:to]
119
134
  subject m_subject
120
- reply_to m_reply_to
135
+ reply_to opts[:from]
121
136
 
122
137
  text_part do
123
138
  body text_template.result(binding)
@@ -111,7 +111,7 @@ module Flapjack
111
111
 
112
112
  stanza_body = stanza.body
113
113
 
114
- logger.debug("groupchat stanza body: " + stanza_body)
114
+ logger.debug("groupchat stanza body: #{stanza_body}")
115
115
  logger.debug("groupchat message received: #{stanza.inspect}")
116
116
 
117
117
  if (stanza_body =~ /^(?:problem|recovery|acknowledgement)/i) &&
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'em-synchrony'
4
+ require 'em-synchrony/em-http'
5
+
6
+ require 'flapjack/gateways/base'
7
+
8
+ module Flapjack
9
+ module Gateways
10
+ class SmsMessagenet
11
+ extend Flapjack::Gateways::Resque
12
+
13
+ MESSAGENET_URL = 'https://www.messagenet.com.au/dotnet/Lodge.asmx/LodgeSMSMessage'
14
+
15
+ class << self
16
+
17
+ alias_method :orig_bootstrap, :bootstrap
18
+
19
+ def bootstrap(opts = {})
20
+ return if @bootstrapped
21
+ @sent = 0
22
+ orig_bootstrap(opts)
23
+ end
24
+
25
+ def perform(notification)
26
+ logger.debug "Woo, got a notification to send out: #{notification.inspect}"
27
+
28
+ notification_type = notification['notification_type']
29
+ contact_first_name = notification['contact_first_name']
30
+ contact_last_name = notification['contact_last_name']
31
+ state = notification['state']
32
+ summary = notification['summary']
33
+ time = notification['time']
34
+ entity, check = notification['event_id'].split(':')
35
+
36
+ headline_map = {'problem' => 'PROBLEM: ',
37
+ 'recovery' => 'RECOVERY: ',
38
+ 'acknowledgement' => 'ACK: ',
39
+ 'test' => 'TEST NOTIFICATION: ',
40
+ 'unknown' => '',
41
+ '' => '',
42
+ }
43
+
44
+ headline = headline_map[notification_type] || ''
45
+
46
+ message = "#{headline}'#{check}' on #{entity}"
47
+ message += " is #{state.upcase}" unless ['acknowledgement', 'test'].include?(notification_type)
48
+ message += " at #{Time.at(time).strftime('%-d %b %H:%M')}, #{summary}"
49
+
50
+ notification['message'] = message
51
+
52
+ # TODO log error and skip instead of raising errors
53
+ if config.nil? || (config.respond_to?(:empty?) && config.empty?)
54
+ logger.error "Messagenet config is missing"
55
+ return
56
+ end
57
+
58
+ errors = []
59
+
60
+ username = config["username"]
61
+ password = config["password"]
62
+ address = notification['address']
63
+ message = notification['message']
64
+ notification_id = notification['id']
65
+
66
+ [[username, "Messagenet username is missing"],
67
+ [password, "Messagenet password is missing"],
68
+ [address, "SMS address is missing"],
69
+ [message, "SMS message is missing"],
70
+ [notification_id, "Notification id is missing"]].each do |val_err|
71
+
72
+ next unless val_err.first.nil? || (val_err.first.respond_to?(:empty?) && val_err.first.empty?)
73
+ errors << val_err.last
74
+ end
75
+
76
+ unless errors.empty?
77
+ errors.each {|err| logger.error err }
78
+ return
79
+ end
80
+
81
+ query = {'Username' => username,
82
+ 'Pwd' => password,
83
+ 'PhoneNumber' => address,
84
+ 'PhoneMessage' => message}
85
+
86
+ http = EM::HttpRequest.new(MESSAGENET_URL).get(:query => query)
87
+
88
+ logger.debug "server response: #{http.response}"
89
+
90
+ status = (http.nil? || http.response_header.nil?) ? nil : http.response_header.status
91
+ if (status >= 200) && (status <= 206)
92
+ @sent += 1
93
+ logger.info "Sent SMS via Messagenet, response status is #{status}, " +
94
+ "notification_id: #{notification_id}"
95
+ else
96
+ logger.error "Failed to send SMS via Messagenet, response status is #{status}, " +
97
+ "notification_id: #{notification_id}"
98
+ end
99
+
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  module Flapjack
4
- VERSION = "0.6.46"
4
+ VERSION = "0.6.47"
5
5
  end
@@ -135,4 +135,57 @@ describe Flapjack::Data::Entity, :redis => true do
135
135
  entities.first.should == 'abc-123'
136
136
  end
137
137
 
138
- end
138
+ it "adds tags to entities" do
139
+ entity = Flapjack::Data::Entity.add({'id' => '5000',
140
+ 'name' => 'abc-123',
141
+ 'contacts' => []},
142
+ :redis => @redis)
143
+
144
+ entity.add_tags('source:foobar', 'foo')
145
+
146
+ entity.should_not be_nil
147
+ entity.should be_an(Flapjack::Data::Entity)
148
+ entity.name.should == 'abc-123'
149
+ entity.tags.should include("source:foobar")
150
+ entity.tags.should include("foo")
151
+
152
+ # and test the tags as read back from redis
153
+ entity = Flapjack::Data::Entity.find_by_id('5000', :redis => @redis)
154
+ entity.tags.should include("source:foobar")
155
+ entity.tags.should include("foo")
156
+
157
+ end
158
+
159
+ it "deletes tags from entities" do
160
+ entity = Flapjack::Data::Entity.add({'id' => '5000',
161
+ 'name' => 'abc-123',
162
+ 'contacts' => []},
163
+ :redis => @redis)
164
+
165
+ entity.add_tags('source:foobar', 'foo')
166
+
167
+ entity.should_not be_nil
168
+ entity.tags.should include("source:foobar")
169
+ entity.tags.should include("foo")
170
+
171
+ entity.delete_tags('source:foobar')
172
+
173
+ entity.tags.should_not include("source:foobar")
174
+ entity.tags.should include("foo")
175
+
176
+ end
177
+
178
+ it "finds entities by tag" do
179
+ entity = Flapjack::Data::Entity.add({'id' => '5000',
180
+ 'name' => 'abc-123',
181
+ 'contacts' => []},
182
+ :redis => @redis)
183
+
184
+ entity.add_tags('source:foobar', 'foo')
185
+
186
+ entity.should_not be_nil
187
+ entity.should be_an(Flapjack::Data::Entity)
188
+ # TODO - the rest of it
189
+ end
190
+
191
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+ require 'flapjack/data/entity'
3
+
4
+ describe Flapjack::Data::Tag, :redis => true do
5
+
6
+ it "adds references to tags"
7
+
8
+ it "deletes references from tags"
9
+
10
+ it "lists references contained in a tag"
11
+
12
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'flapjack/gateways/sms_messagenet'
3
+
4
+ describe Flapjack::Gateways::SmsMessagenet do
5
+
6
+ end
data/tasks/events.rake CHANGED
@@ -13,12 +13,17 @@ namespace :events do
13
13
 
14
14
  require 'flapjack/configuration'
15
15
  require 'flapjack/data/event'
16
+ require 'flapjack/data/entity_check'
16
17
 
17
18
  FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
18
19
  config_file = File.join('etc', 'flapjack_config.yaml')
19
- @config, @redis_config = Flapjack::Configuration.new.load( config_file )
20
+ config = Flapjack::Configuration.new
21
+ config.load( config_file )
20
22
 
21
- if @config.nil? || @config.empty?
23
+ @config_env = config.all
24
+ @redis_config = config.for_redis
25
+
26
+ if @config_env.nil? || @config_env.empty?
22
27
  puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{config_file}'"
23
28
  exit(false)
24
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flapjack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.46
4
+ version: 0.6.47
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-11-12 00:00:00.000000000 Z
14
+ date: 2012-11-21 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: daemons
@@ -390,6 +390,7 @@ files:
390
390
  - lib/flapjack/data/global.rb
391
391
  - lib/flapjack/data/message.rb
392
392
  - lib/flapjack/data/notification.rb
393
+ - lib/flapjack/data/tag.rb
393
394
  - lib/flapjack/executive.rb
394
395
  - lib/flapjack/filters/acknowledgement.rb
395
396
  - lib/flapjack/filters/base.rb
@@ -408,8 +409,7 @@ files:
408
409
  - lib/flapjack/gateways/jabber.rb
409
410
  - lib/flapjack/gateways/oobetet.rb
410
411
  - lib/flapjack/gateways/pagerduty.rb
411
- - lib/flapjack/gateways/sms.rb
412
- - lib/flapjack/gateways/sms/messagenet.rb
412
+ - lib/flapjack/gateways/sms_messagenet.rb
413
413
  - lib/flapjack/gateways/web.rb
414
414
  - lib/flapjack/gateways/web/views/_css.haml
415
415
  - lib/flapjack/gateways/web/views/_nav.haml
@@ -432,6 +432,7 @@ files:
432
432
  - spec/lib/flapjack/data/global_spec.rb
433
433
  - spec/lib/flapjack/data/message_spec.rb
434
434
  - spec/lib/flapjack/data/notification_spec.rb
435
+ - spec/lib/flapjack/data/tag_spec.rb
435
436
  - spec/lib/flapjack/executive_spec.rb
436
437
  - spec/lib/flapjack/filters/acknowledgement_spec.rb
437
438
  - spec/lib/flapjack/filters/delays_spec.rb
@@ -446,7 +447,7 @@ files:
446
447
  - spec/lib/flapjack/gateways/jabber_spec.rb
447
448
  - spec/lib/flapjack/gateways/oobetet_spec.rb
448
449
  - spec/lib/flapjack/gateways/pagerduty_spec.rb
449
- - spec/lib/flapjack/gateways/sms_spec.rb
450
+ - spec/lib/flapjack/gateways/sms_messagenet.spec.rb
450
451
  - spec/lib/flapjack/gateways/web_spec.rb
451
452
  - spec/lib/flapjack/pikelet_spec.rb
452
453
  - spec/lib/flapjack/redis_pool_spec.rb
@@ -511,6 +512,7 @@ test_files:
511
512
  - spec/lib/flapjack/data/global_spec.rb
512
513
  - spec/lib/flapjack/data/message_spec.rb
513
514
  - spec/lib/flapjack/data/notification_spec.rb
515
+ - spec/lib/flapjack/data/tag_spec.rb
514
516
  - spec/lib/flapjack/executive_spec.rb
515
517
  - spec/lib/flapjack/filters/acknowledgement_spec.rb
516
518
  - spec/lib/flapjack/filters/delays_spec.rb
@@ -525,7 +527,7 @@ test_files:
525
527
  - spec/lib/flapjack/gateways/jabber_spec.rb
526
528
  - spec/lib/flapjack/gateways/oobetet_spec.rb
527
529
  - spec/lib/flapjack/gateways/pagerduty_spec.rb
528
- - spec/lib/flapjack/gateways/sms_spec.rb
530
+ - spec/lib/flapjack/gateways/sms_messagenet.spec.rb
529
531
  - spec/lib/flapjack/gateways/web_spec.rb
530
532
  - spec/lib/flapjack/pikelet_spec.rb
531
533
  - spec/lib/flapjack/redis_pool_spec.rb
@@ -1,53 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'flapjack/pikelet'
4
- require 'flapjack/gateways/sms/messagenet'
5
-
6
- module Flapjack
7
- module Gateways
8
-
9
- class Sms
10
- extend Flapjack::Gateways::Resque
11
-
12
- class << self
13
-
14
- def perform(notification)
15
- @logger.debug "Woo, got a notification to send out: #{notification.inspect}"
16
- dispatch(notification, :logger => @logger, :redis => ::Resque.redis)
17
- end
18
-
19
- def dispatch(notification, opts = {})
20
- notification_type = notification['notification_type']
21
- contact_first_name = notification['contact_first_name']
22
- contact_last_name = notification['contact_last_name']
23
- state = notification['state']
24
- summary = notification['summary']
25
- time = notification['time']
26
- entity, check = notification['event_id'].split(':')
27
-
28
- headline_map = {'problem' => 'PROBLEM: ',
29
- 'recovery' => 'RECOVERY: ',
30
- 'acknowledgement' => 'ACK: ',
31
- 'test' => 'TEST NOTIFICATION: ',
32
- 'unknown' => '',
33
- '' => '',
34
- }
35
-
36
- headline = headline_map[notification_type] || ''
37
-
38
- message = "#{headline}'#{check}' on #{entity}"
39
- message += " is #{state.upcase}" unless ['acknowledgement', 'test'].include?(notification_type)
40
- message += " at #{Time.at(time).strftime('%-d %b %H:%M')}, #{summary}"
41
-
42
- notification['message'] = message
43
- Flapjack::Gateways::Sms::Messagenet.sender(notification,
44
- :logger => opts[:logger],
45
- :config => Flapjack::Gateways::Sms.instance_variable_get('@config'))
46
- end
47
-
48
- end
49
-
50
- end
51
- end
52
- end
53
-
@@ -1,49 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'net/http'
4
- require 'uri'
5
-
6
- module Flapjack
7
- module Gateways
8
- class Sms
9
- class Messagenet
10
-
11
- def self.sender(notification, options = {})
12
- logger = options[:logger]
13
- config = options[:config]
14
-
15
- unless config && (username = config["username"])
16
- raise RuntimeError.new('sms_messagenet: username is missing')
17
- end
18
- unless config && (password = config["password"])
19
- raise RuntimeError.new('sms_messagenet: password is missing')
20
- end
21
-
22
- raise RuntimeError.new('address is missing') unless address = notification['address']
23
- raise RuntimeError.new('message is missing') unless message = notification['message']
24
- raise RuntimeError.new('id is missing') unless notification_id = notification['id']
25
-
26
- params = { 'Username' => username,
27
- 'Pwd' => password,
28
- 'PhoneNumber' => address,
29
- 'PhoneMessage' => message }
30
-
31
- uri = URI('https://www.messagenet.com.au/dotnet/Lodge.asmx/LodgeSMSMessage')
32
- uri.query = URI.encode_www_form(params)
33
- logger.debug("request_uri: #{uri.request_uri.inspect}")
34
-
35
- Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
36
- request = Net::HTTP::Get.new uri.request_uri
37
- response = http.request request
38
- http_success = ( response.is_a?(Net::HTTPSuccess) == true )
39
- logger.debug("Flapjack::Notification::SMSMessagenet: response from server: #{response.body}")
40
- raise RuntimeError.new "Failed to send SMS via messagenet, http response is a #{response.class}, notification_id: #{notification_id}" unless http_success
41
- end
42
-
43
- end
44
- end
45
- end
46
- end
47
- end
48
-
49
-
@@ -1,6 +0,0 @@
1
- require 'spec_helper'
2
- require 'flapjack/gateways/sms'
3
-
4
- describe Flapjack::Gateways::Sms do
5
-
6
- end