flapjack 0.9.1 → 0.9.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b98530923891264cb55c429358ca9597f1ef4ca
4
- data.tar.gz: c957beff3e8d6942157ac1e085cd912932f9e287
3
+ metadata.gz: 9aed6403dfdbf11787e5b39b0224f04c00294b8c
4
+ data.tar.gz: 2220ec7584002c684b8b6fdb26c843bb580486d4
5
5
  SHA512:
6
- metadata.gz: dd3e6b3b9af05c5f40ea6f884f985d7b5d6765eb4493f40ee12a12f8a51360933c971227b0afab1f0dd6b57f8c851c5e39276300e319610598208c945288f7aa
7
- data.tar.gz: 8ecf0255ef2f7e6cdac040f62a3b8468138bb74bca9e024fbf8111d8743bedba5d861791d2d17ace0cba27ee70c0befc12155195b79b60ae9e4e2ad4ae31f861
6
+ metadata.gz: 729f88348650bbcbf3f8eb7787a177d22dad350e17fc89333e166c057b57425062fecbe336754b0acb755b61946520900ecb21c003795b40097adbd0eaffe2b6
7
+ data.tar.gz: f9925153a749408ebd31304306835d821e9367df09cda4c5067b5bb5ff70b3b29d7cd4e5b07b4d4fde9abb4d3e93adc2f5d5c2667686174df75f9d756164a982
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## Flapjack Changelog
2
2
 
3
+ # 0.9.2 - 2014-07-17
4
+ - Feature: Add ability to disable check via JSON API #529 (@ali-graham)
5
+ - Feature: Jabber - Resource in JID should be supported in the config #557 (@jessereynolds)
6
+ - Feature: Jabber - add an 'identifiers' list to the config #558 (@jessereynolds)
7
+ - Feature: Jabber - handle HipChat style status updates as per XEP-0085 #559 (@jessereynolds)
8
+
3
9
  # 0.9.1 - 2014-06-27
4
10
  - Bug: PATCHing blackhole properties for notification rule changes other blackholes - further fixes #504 (@ali-graham)
5
11
  - Bug: JSONAPI get all entities/contacts with empty db e3725fc (@ali-graham)
@@ -87,6 +87,8 @@ production:
87
87
  jabberid: "flapjack@jabber.example.com"
88
88
  password: "good-password"
89
89
  alias: "flapjack"
90
+ identifiers:
91
+ - "@flapjack"
90
92
  rooms:
91
93
  - "gimp@conference.jabber.example.com"
92
94
  - "log@conference.jabber.example.com"
@@ -50,9 +50,17 @@ module Flapjack
50
50
  @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 2)
51
51
 
52
52
  @logger = opts[:logger]
53
+ @logger.debug("Jabber Initializing")
53
54
 
54
55
  @buffer = []
55
56
  @hostname = Socket.gethostname
57
+
58
+ # FIXME: i suspect the following should be in #setup so a config reload updates @identifiers
59
+ # I moved it here so the rspec passes :-/
60
+ @alias = @config['alias'] || 'flapjack'
61
+ @identifiers = ((@config['identifiers'] || []) + [@alias]).uniq
62
+ @logger.debug("I will respond to the following identifiers: #{@identifiers.join(', ')}")
63
+
56
64
  super()
57
65
  end
58
66
 
@@ -65,7 +73,9 @@ module Flapjack
65
73
  end
66
74
 
67
75
  def setup
68
- @flapjack_jid = Blather::JID.new((@config['jabberid'] || 'flapjack') + '/' + @hostname)
76
+ jid = @config['jabberid'] || 'flapjack'
77
+ jid += '/' + @hostname unless jid.include?('/')
78
+ @flapjack_jid = Blather::JID.new(jid)
69
79
 
70
80
  super(@flapjack_jid, @config['password'], @config['server'], @config['port'].to_i)
71
81
 
@@ -80,13 +90,19 @@ module Flapjack
80
90
  end
81
91
  end
82
92
 
83
- register_handler :message, :groupchat?, :body => /^#{@config['alias']}:\s+/ do |stanza|
93
+ body_matchers = @identifiers.inject([]) do |memo, identifier|
94
+ @logger.debug("identifier: #{identifier}, memo: #{memo}")
95
+ memo << {:body => /^#{identifier}[:\s]/}
96
+ memo
97
+ end
98
+ @logger.debug("body_matchers: #{body_matchers}")
99
+ register_handler :message, :groupchat?, body_matchers do |stanza|
84
100
  EventMachine::Synchrony.next_tick do
85
101
  on_groupchat(stanza)
86
102
  end
87
103
  end
88
104
 
89
- register_handler :message, :chat? do |stanza|
105
+ register_handler :message, :chat?, :body do |stanza|
90
106
  EventMachine::Synchrony.next_tick do
91
107
  on_chat(stanza)
92
108
  end
@@ -111,11 +127,11 @@ module Flapjack
111
127
  @logger.info("Joining room #{room}")
112
128
  presence = Blather::Stanza::Presence.new
113
129
  presence.from = @flapjack_jid
114
- presence.to = Blather::JID.new("#{room}/#{@config['alias']}")
130
+ presence.to = Blather::JID.new("#{room}/#{@alias}")
115
131
  presence << "<x xmlns='http://jabber.org/protocol/muc'><history maxstanzas='0'></x>"
116
132
  EventMachine::Synchrony.next_tick do
117
133
  write presence
118
- say(room, "flapjack jabber gateway started at #{Time.now}, hello!", :groupchat)
134
+ say(room, "flapjack jabber gateway started at #{Time.now}, hello! Try typing 'help'.", :groupchat)
119
135
  end
120
136
  end
121
137
  end
@@ -160,7 +176,7 @@ module Flapjack
160
176
  out
161
177
  end
162
178
 
163
- def interpreter(command_raw,from)
179
+ def interpreter(command_raw, from)
164
180
  msg = nil
165
181
  action = nil
166
182
  entity_check = nil
@@ -239,7 +255,8 @@ module Flapjack
239
255
  t = Process.times
240
256
  fqdn = `/bin/hostname -f`.chomp
241
257
  pid = Process.pid
242
- msg = "Flapjack #{Flapjack::VERSION} process #{pid} on #{fqdn} \n" +
258
+ msg = "Flapjack #{Flapjack::VERSION} process #{pid} on #{fqdn}\n" +
259
+ "Identifiers: #{@identifiers.join(', ')}\n" +
243
260
  "Boot time: #{@boot_time}\n" +
244
261
  "User CPU Time: #{t.utime}\n" +
245
262
  "System CPU Time: #{t.stime}\n" +
@@ -537,18 +554,23 @@ module Flapjack
537
554
  return if @should_quit
538
555
  @logger.debug("groupchat message received: #{stanza.inspect}")
539
556
 
540
- if stanza.body =~ /^#{@config['alias']}:\s+(.*)/m
541
- command = $1
557
+ the_command = nil
558
+ @identifiers.each do |identifier|
559
+ if stanza.body =~ /^#{identifier}:?\s*(.*)/m
560
+ the_command = $1
561
+ @logger.debug("matched identifier: #{identifier}, command: #{the_command.inspect}")
562
+ break
563
+ end
542
564
  end
543
565
 
544
566
  from = stanza.from
545
567
 
546
568
  begin
547
- results = interpreter(command, from.resource.to_s)
569
+ results = interpreter(the_command, from.to_s)
548
570
  msg = results[:msg]
549
571
  action = results[:action]
550
572
  rescue => e
551
- @logger.error("Exception when interpreting command '#{command}' - #{e.class}, #{e.message}")
573
+ @logger.debug("Exception when interpreting command '#{the_command}' - #{e.class}, #{e.message}")
552
574
  msg = "Oops, something went wrong processing that command (#{e.class}, #{e.message})"
553
575
  end
554
576
 
@@ -571,8 +593,10 @@ module Flapjack
571
593
  command = stanza.body
572
594
  end
573
595
 
596
+ from = stanza.from
597
+
574
598
  begin
575
- results = interpreter(command)
599
+ results = interpreter(command, from.resource.to_s)
576
600
  msg = results[:msg]
577
601
  action = results[:action]
578
602
  rescue => e
@@ -98,6 +98,8 @@ module Flapjack
98
98
 
99
99
  set :dump_errors, false
100
100
 
101
+ set :protection, :except => :path_traversal
102
+
101
103
  rescue_error = Proc.new {|status, exception, request_info, *msg|
102
104
  if !msg || msg.empty?
103
105
  trace = exception.backtrace.join("\n")
@@ -31,8 +31,24 @@ module Flapjack
31
31
  app.helpers Flapjack::Gateways::JSONAPI::Helpers
32
32
  app.helpers Flapjack::Gateways::JSONAPI::CheckMethods::Helpers
33
33
 
34
+ app.patch %r{^/checks/(.+)$} do
35
+ checks_for_check_names(params[:captures][0].split(',')).each do |check|
36
+ apply_json_patch('checks') do |op, property, linked, value|
37
+ case op
38
+ when 'replace'
39
+ if ['enabled'].include?(property)
40
+ # explicitly checking for false being passed in
41
+ check.disable! if value.is_a?(FalseClass)
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ status 204
48
+ end
49
+
34
50
  # create a scheduled maintenance period for a check on an entity
35
- app.post %r{^/scheduled_maintenances/checks/([^/]+)$} do
51
+ app.post %r{^/scheduled_maintenances/checks/(.+)$} do
36
52
  scheduled_maintenances = wrapped_params('scheduled_maintenances')
37
53
  checks_for_check_names(params[:captures][0].split(',')).each do |check|
38
54
  scheduled_maintenances.each do |wp|
@@ -50,7 +66,7 @@ module Flapjack
50
66
  # create an acknowledgement for a service on an entity
51
67
  # NB currently, this does not acknowledge a specific failure event, just
52
68
  # the entity-check as a whole
53
- app.post %r{^/unscheduled_maintenances/checks/([^/]+)$} do
69
+ app.post %r{^/unscheduled_maintenances/checks/(.+)$} do
54
70
  unscheduled_maintenances = wrapped_params('unscheduled_maintenances', false)
55
71
  checks_for_check_names(params[:captures][0].split(',')).each do |check|
56
72
  unscheduled_maintenances.each do |wp|
@@ -69,7 +85,7 @@ module Flapjack
69
85
  status 204
70
86
  end
71
87
 
72
- app.patch %r{^/unscheduled_maintenances/checks/([^/]+)$} do
88
+ app.patch %r{^/unscheduled_maintenances/checks/(.+)$} do
73
89
  checks_for_check_names(params[:captures][0].split(',')).each do |check|
74
90
  apply_json_patch('unscheduled_maintenances') do |op, property, linked, value|
75
91
  case op
@@ -84,7 +100,7 @@ module Flapjack
84
100
  status 204
85
101
  end
86
102
 
87
- app.delete %r{^/scheduled_maintenances/checks/([^/]+)$} do
103
+ app.delete %r{^/scheduled_maintenances/checks/(.+)$} do
88
104
  start_time = validate_and_parsetime(params[:start_time])
89
105
  halt( err(403, "start time must be provided") ) unless start_time
90
106
 
@@ -94,7 +110,7 @@ module Flapjack
94
110
  status 204
95
111
  end
96
112
 
97
- app.post %r{^/test_notifications/checks/([^/]+)$} do
113
+ app.post %r{^/test_notifications/checks/(.+)$} do
98
114
  test_notifications = wrapped_params('test_notifications', false)
99
115
  checks_for_check_names(params[:captures][0].split(',')).each do |check|
100
116
  test_notifications.each do |wp|
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  module Flapjack
4
- VERSION = "0.9.1"
4
+ VERSION = "0.9.2"
5
5
  end
6
6
 
@@ -3,13 +3,14 @@ require 'flapjack/gateways/jabber'
3
3
 
4
4
  describe Flapjack::Gateways::Jabber, :logger => true do
5
5
 
6
- let(:config) { {'queue' => 'jabber_notifications',
7
- 'server' => 'example.com',
8
- 'port' => '5222',
9
- 'jabberid' => 'flapjack@example.com',
10
- 'password' => 'password',
11
- 'alias' => 'flapjack',
12
- 'rooms' => ['flapjacktest@conference.example.com']
6
+ let(:config) { {'queue' => 'jabber_notifications',
7
+ 'server' => 'example.com',
8
+ 'port' => '5222',
9
+ 'jabberid' => 'flapjack@example.com',
10
+ 'password' => 'password',
11
+ 'alias' => 'flapjack',
12
+ 'identifiers' => ['@flapjack'],
13
+ 'rooms' => ['flapjacktest@conference.example.com']
13
14
  }
14
15
  }
15
16
 
@@ -26,10 +27,11 @@ describe Flapjack::Gateways::Jabber, :logger => true do
26
27
  expect(fj).to receive(:register_handler).with(:ready).and_yield(stanza)
27
28
  expect(fj).to receive(:on_ready).with(stanza)
28
29
 
29
- expect(fj).to receive(:register_handler).with(:message, :groupchat?, :body => /^flapjack:\s+/).and_yield(stanza)
30
+ body_matchers = [{:body => /^@flapjack[:\s]/}, {:body => /^flapjack[:\s]/}]
31
+ expect(fj).to receive(:register_handler).with(:message, :groupchat?, body_matchers).and_yield(stanza)
30
32
  expect(fj).to receive(:on_groupchat).with(stanza)
31
33
 
32
- expect(fj).to receive(:register_handler).with(:message, :chat?).and_yield(stanza)
34
+ expect(fj).to receive(:register_handler).with(:message, :chat?, :body).and_yield(stanza)
33
35
  expect(fj).to receive(:on_chat).with(stanza)
34
36
 
35
37
  expect(fj).to receive(:register_handler).with(:disconnected).and_yield(stanza)
@@ -52,9 +54,8 @@ describe Flapjack::Gateways::Jabber, :logger => true do
52
54
  end
53
55
 
54
56
  it "receives an acknowledgement message" do
55
- expect(stanza).to receive(:body).and_return('flapjack: ACKID 1f8ac10f fixing now duration: 90m')
57
+ expect(stanza).to receive(:body).twice.and_return('flapjack: ACKID 1f8ac10f fixing now duration: 90m')
56
58
  from = double('from')
57
- expect(from).to receive(:resource).and_return('sender')
58
59
  expect(from).to receive(:stripped).and_return('sender')
59
60
  expect(stanza).to receive(:from).and_return(from)
60
61
 
@@ -85,12 +86,11 @@ describe Flapjack::Gateways::Jabber, :logger => true do
85
86
  end
86
87
 
87
88
  it "strips XML tags from the received message" do
88
- expect(stanza).to receive(:body).
89
+ expect(stanza).to receive(:body).twice.
89
90
  and_return('flapjack: tell me about <span style="text-decoration: underline;">' +
90
91
  '<a href="http://example.org/">example.org</a></span>')
91
92
 
92
93
  from = double('from')
93
- expect(from).to receive(:resource).and_return('sender')
94
94
  expect(from).to receive(:stripped).and_return('sender')
95
95
  expect(stanza).to receive(:from).and_return(from)
96
96
 
@@ -119,11 +119,10 @@ describe Flapjack::Gateways::Jabber, :logger => true do
119
119
  end
120
120
 
121
121
  it "handles a message with a newline in it" do
122
- expect(stanza).to receive(:body).
122
+ expect(stanza).to receive(:body).twice.
123
123
  and_return("flapjack: tell me about \nexample.com")
124
124
 
125
125
  from = double('from')
126
- expect(from).to receive(:resource).and_return('sender')
127
126
  expect(from).to receive(:stripped).and_return('sender')
128
127
  expect(stanza).to receive(:from).and_return(from)
129
128
 
@@ -152,9 +151,8 @@ describe Flapjack::Gateways::Jabber, :logger => true do
152
151
  end
153
152
 
154
153
  it "receives a message it doesn't understand" do
155
- expect(stanza).to receive(:body).once.and_return('flapjack: hello!')
154
+ expect(stanza).to receive(:body).twice.and_return('flapjack: hello!')
156
155
  from = double('from')
157
- expect(from).to receive(:resource).and_return('sender')
158
156
  expect(from).to receive(:stripped).and_return('sender')
159
157
  expect(stanza).to receive(:from).and_return(from)
160
158
 
@@ -9,11 +9,26 @@ describe 'Flapjack::Gateways::JSONAPI::CheckMethods', :sinatra => true, :logger
9
9
  let(:entity_check) { double(Flapjack::Data::EntityCheck) }
10
10
 
11
11
  let(:entity_name) { 'www.example.net'}
12
- let(:entity_name_esc) { URI.escape(entity_name) }
13
12
  let(:check) { 'ping' }
13
+ let(:check_esc) { URI.escape(entity_name + ':' + check) }
14
14
 
15
15
  let(:check_presenter) { double(Flapjack::Gateways::JSONAPI::CheckPresenter) }
16
16
 
17
+ it 'disables a check' do
18
+ expect(Flapjack::Data::Entity).to receive(:find_by_name).
19
+ with(entity_name, :redis => redis).and_return(entity)
20
+ expect(Flapjack::Data::EntityCheck).to receive(:for_entity).
21
+ with(entity, check, :redis => redis).and_return(entity_check)
22
+
23
+ expect(entity_check).to receive(:disable!)
24
+
25
+ apatch "/checks/#{check_esc}",
26
+ [{:op => 'replace', :path => '/checks/0/enabled', :value => false}].to_json,
27
+ jsonapi_patch_env
28
+ expect(last_response.status).to eq(204)
29
+
30
+ end
31
+
17
32
  it "creates an acknowledgement for an entity check" do
18
33
  expect(Flapjack::Data::Entity).to receive(:find_by_name).
19
34
  with(entity_name, :redis => redis).and_return(entity)
@@ -26,7 +41,7 @@ describe 'Flapjack::Gateways::JSONAPI::CheckMethods', :sinatra => true, :logger
26
41
  expect(Flapjack::Data::Event).to receive(:create_acknowledgement).
27
42
  with(entity_name, check, :redis => redis, :duration => (4 * 60 * 60))
28
43
 
29
- apost "/unscheduled_maintenances/checks/#{entity_name}:#{check}", {}, jsonapi_post_env
44
+ apost "/unscheduled_maintenances/checks/#{check_esc}", {}, jsonapi_post_env
30
45
  expect(last_response.status).to eq(204)
31
46
  end
32
47
 
@@ -40,7 +55,23 @@ describe 'Flapjack::Gateways::JSONAPI::CheckMethods', :sinatra => true, :logger
40
55
  expect(Flapjack::Data::Entity).to receive(:find_by_name).
41
56
  with(entity_name, :redis => redis).and_return(entity)
42
57
 
43
- apatch "/unscheduled_maintenances/checks/#{entity_name}:#{check}",
58
+ apatch "/unscheduled_maintenances/checks/#{check_esc}",
59
+ [{:op => 'replace', :path => '/unscheduled_maintenances/0/end_time', :value => end_time.iso8601}].to_json,
60
+ jsonapi_patch_env
61
+ expect(last_response.status).to eq(204)
62
+ end
63
+
64
+ it "ends an unscheduled maintenance period for an entity check with a / in the check name" do
65
+ end_time = Time.now + (60 * 60) # an hour from now
66
+ expect(entity_check).to receive(:end_unscheduled_maintenance).with(end_time.to_i)
67
+
68
+ expect(Flapjack::Data::EntityCheck).to receive(:for_entity).
69
+ with(entity, 'Disk/Memory Usage', :redis => redis).and_return(entity_check)
70
+
71
+ expect(Flapjack::Data::Entity).to receive(:find_by_name).
72
+ with(entity_name, :redis => redis).and_return(entity)
73
+
74
+ apatch "/unscheduled_maintenances/checks/#{URI.escape(entity_name + ':Disk/Memory Usage')}",
44
75
  [{:op => 'replace', :path => '/unscheduled_maintenances/0/end_time', :value => end_time.iso8601}].to_json,
45
76
  jsonapi_patch_env
46
77
  expect(last_response.status).to eq(204)
@@ -57,7 +88,7 @@ describe 'Flapjack::Gateways::JSONAPI::CheckMethods', :sinatra => true, :logger
57
88
  expect(entity_check).to receive(:create_scheduled_maintenance).
58
89
  with(start.getutc.to_i, duration, :summary => 'test')
59
90
 
60
- apost "/scheduled_maintenances/checks/#{entity_name}:#{check}",
91
+ apost "/scheduled_maintenances/checks/#{check_esc}",
61
92
  {:scheduled_maintenances => [{:start_time => start.iso8601, :summary => 'test', :duration => duration}]}.to_json,
62
93
  jsonapi_post_env
63
94
  expect(last_response.status).to eq(204)
@@ -66,7 +97,7 @@ describe 'Flapjack::Gateways::JSONAPI::CheckMethods', :sinatra => true, :logger
66
97
  it "doesn't create a scheduled maintenance period for an entity check if the start time isn't passed" do
67
98
  duration = (2 * 60 * 60) # two hours
68
99
 
69
- apost "/scheduled_maintenances/checks/#{entity_name}:#{check}",
100
+ apost "/scheduled_maintenances/checks/#{check_esc}",
70
101
  {:summary => 'test', :duration => duration}.to_json, jsonapi_post_env
71
102
  expect(last_response.status).to eq(403)
72
103
  end
@@ -81,7 +112,7 @@ describe 'Flapjack::Gateways::JSONAPI::CheckMethods', :sinatra => true, :logger
81
112
  expect(Flapjack::Data::Entity).to receive(:find_by_name).
82
113
  with(entity_name, :redis => redis).and_return(entity)
83
114
 
84
- adelete "/scheduled_maintenances/checks/#{entity_name}:#{check}",
115
+ adelete "/scheduled_maintenances/checks/#{check_esc}",
85
116
  :start_time => start_time.iso8601
86
117
  expect(last_response.status).to eq(204)
87
118
  end
@@ -89,7 +120,7 @@ describe 'Flapjack::Gateways::JSONAPI::CheckMethods', :sinatra => true, :logger
89
120
  it "doesn't delete a scheduled maintenance period if the start time isn't passed" do
90
121
  expect(entity_check).not_to receive(:end_scheduled_maintenance)
91
122
 
92
- adelete "/scheduled_maintenances/checks/#{entity_name}:#{check}"
123
+ adelete "/scheduled_maintenances/checks/#{check_esc}"
93
124
  expect(last_response.status).to eq(403)
94
125
  end
95
126
 
@@ -109,7 +140,7 @@ describe 'Flapjack::Gateways::JSONAPI::CheckMethods', :sinatra => true, :logger
109
140
  expect(Flapjack::Data::Entity).to receive(:find_by_name).
110
141
  with(entity_name, :redis => redis).and_return(entity)
111
142
 
112
- adelete "/scheduled_maintenances/checks/#{entity_name}:#{check},#{entity_name}:foo",
143
+ adelete "/scheduled_maintenances/checks/#{check_esc},#{entity_name}:foo",
113
144
  :start_time => start_time.iso8601
114
145
  expect(last_response.status).to eq(204)
115
146
  end
@@ -127,7 +158,7 @@ describe 'Flapjack::Gateways::JSONAPI::CheckMethods', :sinatra => true, :logger
127
158
  expect(Flapjack::Data::Event).to receive(:test_notifications).
128
159
  with(entity_name, check, hash_including(:redis => redis))
129
160
 
130
- apost "/test_notifications/checks/#{entity_name}:#{check}"
161
+ apost "/test_notifications/checks/#{check_esc}"
131
162
  expect(last_response.status).to eq(204)
132
163
  end
133
164
 
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.9.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lindsay Holmwood
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-06-26 00:00:00.000000000 Z
13
+ date: 2014-07-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: dante