flapjack 0.5.1 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.gitignore +16 -0
  2. data/Rakefile +72 -32
  3. data/VERSION +1 -0
  4. data/bin/flapjack-netsaint-parser +433 -0
  5. data/bin/flapjack-populator +29 -0
  6. data/bin/flapjack-stats +10 -5
  7. data/{etc → dist/etc}/default/flapjack-notifier +0 -0
  8. data/{etc → dist/etc}/default/flapjack-workers +0 -0
  9. data/{etc → dist/etc}/flapjack/flapjack-notifier.conf.example +0 -0
  10. data/{etc → dist/etc}/flapjack/recipients.conf.example +0 -0
  11. data/{etc → dist/etc}/init.d/flapjack-notifier +0 -0
  12. data/{etc → dist/etc}/init.d/flapjack-workers +7 -7
  13. data/dist/puppet/flapjack/files/.stub +0 -0
  14. data/dist/puppet/flapjack/manifests/common.pp +61 -0
  15. data/dist/puppet/flapjack/manifests/notifier.pp +13 -0
  16. data/dist/puppet/flapjack/manifests/worker.pp +13 -0
  17. data/dist/puppet/flapjack/templates/.stub +0 -0
  18. data/dist/puppet/ruby/manifests/dev.pp +5 -0
  19. data/dist/puppet/ruby/manifests/rubygems.pp +14 -0
  20. data/dist/puppet/sqlite3/manifests/dev.pp +5 -0
  21. data/features/netsaint-config-converter.feature +126 -0
  22. data/features/steps/flapjack-importer_steps.rb +112 -0
  23. data/features/steps/flapjack-netsaint-parser_steps.rb +51 -0
  24. data/features/steps/flapjack-worker-manager_steps.rb +6 -8
  25. data/features/support/env.rb +22 -19
  26. data/flapjack.gemspec +186 -23
  27. data/lib/flapjack.rb +4 -0
  28. data/spec/check_sandbox/echo +3 -0
  29. data/spec/check_sandbox/sandboxed_check +5 -0
  30. data/spec/configs/flapjack-notifier-couchdb.ini +25 -0
  31. data/spec/configs/flapjack-notifier.ini +39 -0
  32. data/spec/configs/recipients.ini +14 -0
  33. data/spec/helpers.rb +15 -0
  34. data/spec/inifile_spec.rb +66 -0
  35. data/spec/mock-notifiers/mock/init.rb +3 -0
  36. data/spec/mock-notifiers/mock/mock.rb +19 -0
  37. data/spec/notifier-directories/spoons/testmailer/init.rb +20 -0
  38. data/spec/notifier_application_spec.rb +222 -0
  39. data/spec/notifier_filters_spec.rb +52 -0
  40. data/spec/notifier_options_multiplexer_spec.rb +71 -0
  41. data/spec/notifier_options_spec.rb +115 -0
  42. data/spec/notifier_spec.rb +57 -0
  43. data/spec/notifiers/mailer_spec.rb +36 -0
  44. data/spec/notifiers/xmpp_spec.rb +36 -0
  45. data/spec/persistence/datamapper_spec.rb +74 -0
  46. data/spec/persistence/mock_persistence_backend.rb +26 -0
  47. data/spec/simple.ini +6 -0
  48. data/spec/spec.opts +4 -0
  49. data/spec/test-filters/blocker.rb +13 -0
  50. data/spec/test-filters/mock.rb +13 -0
  51. data/spec/transports/beanstalkd_spec.rb +44 -0
  52. data/spec/transports/mock_transport.rb +58 -0
  53. data/spec/worker_application_spec.rb +62 -0
  54. data/spec/worker_options_spec.rb +83 -0
  55. metadata +166 -47
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'flapjack', 'inifile')
4
+ require File.join(File.dirname(__FILE__), 'helpers')
5
+
6
+ describe "inifile reader" do
7
+
8
+ it "should turn sections into keys" do
9
+ example = "[forks]\nhello = world\n[spoons]\nfoo = bar\n[splades]\nbar = baz"
10
+ ini = Flapjack::Inifile.new(example)
11
+ ini.keys.sort.should == %w{forks splades spoons}
12
+ end
13
+
14
+ it "should nest parameters under a section" do
15
+ example = "[forks]\nhello = world\n[spoons]\nfoo = bar\n[splades]\nbar = baz"
16
+ ini = Flapjack::Inifile.new(example)
17
+ ini['forks']['hello'].should == "world"
18
+ ini['spoons']['foo'].should == "bar"
19
+ ini['splades']['bar'].should == "baz"
20
+ end
21
+
22
+ it "should read a file" do
23
+ filename = File.join(File.dirname(__FILE__), 'simple.ini')
24
+ ini = Flapjack::Inifile.read(filename)
25
+ ini['forks']['hello'].should == "world"
26
+ ini['spoons']['foo'].should == "bar"
27
+ ini['splades']['bar'].should == "baz"
28
+ end
29
+
30
+ it "should ignore commented lines" do
31
+ example = "[forks]\nhello = world\n[spoons]\nfoo = bar\n# comment goes here\n[splades]\nbar = baz"
32
+ ini = Flapjack::Inifile.new(example)
33
+ ini['spoons'].keys.include?(/#/).should be_false
34
+ ini['spoons'].keys.include?(/comment goes here/).should be_false
35
+ ini['spoons'].values.include?(/#/).should be_false
36
+ ini['spoons'].values.include?(/comment goes here/).should be_false
37
+ end
38
+
39
+ it "should ignore blank lines" do
40
+ example = "\n\n\n\n\n\n\n[spoons]\n\n\n\n[of]\n[doom]"
41
+ ini = Flapjack::Inifile.new(example)
42
+ ini.keys.sort.should == %w(doom of spoons)
43
+ end
44
+
45
+ it "should ignore mid-line comments" do
46
+ example = "[forks] ; a comment \nhello = world ; another comment\n\n"
47
+ ini = Flapjack::Inifile.new(example)
48
+ ini.keys.include?("forks").should be_true
49
+ ini['forks']['hello'].should == 'world'
50
+ end
51
+
52
+ it "should append re-opened sections" do
53
+ example = "[forks]\nhello = world\n[forks]\nfoo = bar\n\n[forks]\nbar = baz"
54
+ ini = Flapjack::Inifile.new(example)
55
+ ini.keys.include?("forks").should be_true
56
+ ini["forks"].keys.sort.should == %w(bar foo hello)
57
+ end
58
+
59
+ it "should dump the raw config" do
60
+ example = "[forks]\nhello = world\n[spoons]\nfoo = bar\n[splades]\nbar = baz"
61
+ ini = Flapjack::Inifile.new(example)
62
+ ini.all.size.should == 3
63
+ end
64
+
65
+
66
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), 'mock')
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'xmpp4r-simple'
4
+
5
+ module Flapjack
6
+ module Notifiers
7
+ class Mock
8
+
9
+ attr_accessor :log, :website_uri
10
+
11
+ def initialize(opts={})
12
+ @log = opts[:log]
13
+ @website_uri = opts[:website_uri]
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Flapjack
4
+ module Notifiers
5
+ class Testmailer
6
+
7
+ def initialize(opts={})
8
+ @log = opts[:log]
9
+ end
10
+
11
+ def notify(opts={})
12
+ @log.debug("TestMailer notifying #{opts[:who].name}")
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+
19
+
20
+
@@ -0,0 +1,222 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'flapjack', 'applications', 'notifier')
2
+ require File.join(File.dirname(__FILE__), 'helpers')
3
+
4
+ describe "notifier application" do
5
+
6
+ #
7
+ # booting interface
8
+ #
9
+
10
+ it "should have a simple interface to start the notifier" do
11
+ options = { :notifiers => {},
12
+ :filters => [],
13
+ :log => MockLogger.new,
14
+ :persistence => {:backend => :mock_persistence_backend,
15
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')} }
16
+ app = Flapjack::Notifier::Application.run(options)
17
+ end
18
+
19
+ it "should log when loading a notifier" do
20
+ options = { :notifiers => {:testmailer => {}},
21
+ :filters => [],
22
+ :log => MockLogger.new,
23
+ :notifier_directories => [File.join(File.dirname(__FILE__),'notifier-directories', 'spoons')],
24
+ :persistence => {:backend => :mock_persistence_backend,
25
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')} }
26
+ app = Flapjack::Notifier::Application.run(options)
27
+ app.log.messages.find {|msg| msg =~ /loading the testmailer notifier/i}.should_not be_nil
28
+ end
29
+
30
+ it "should warn if a specified notifier doesn't exist" do
31
+ options = { :notifiers => {:nonexistant => {}},
32
+ :filters => [],
33
+ :log => MockLogger.new,
34
+ :persistence => {:backend => :mock_persistence_backend,
35
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')} }
36
+ app = Flapjack::Notifier::Application.run(options)
37
+ app.log.messages.find {|msg| msg =~ /Flapjack::Notifiers::Nonexistant doesn't exist/}.should_not be_nil
38
+ end
39
+
40
+ it "should give precedence to notifiers in user-specified notifier directories" do
41
+ options = { :notifiers => {:testmailer => {}},
42
+ :filters => [],
43
+ :log => MockLogger.new,
44
+ :notifier_directories => [File.join(File.dirname(__FILE__),'notifier-directories', 'spoons')],
45
+ :persistence => {:backend => :mock_persistence_backend,
46
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')} }
47
+ app = Flapjack::Notifier::Application.run(options)
48
+ app.log.messages.find {|msg| msg =~ /spoons/i}.should_not be_nil
49
+ # this will raise an exception if the notifier directory isn't specified,
50
+ # as the mailer notifier requires several arguments anyhow
51
+ end
52
+
53
+ it "should pass global notifier config options to each notifier"
54
+
55
+ it "should setup recipients from a list" do
56
+ options = { :notifiers => {},
57
+ :filters => [],
58
+ :log => MockLogger.new,
59
+ :recipients => [{:name => "Spoons McDoom"}],
60
+ :persistence => {:backend => :mock_persistence_backend,
61
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')} }
62
+ app = Flapjack::Notifier::Application.run(options)
63
+ # 1 passed recipient should be here
64
+ app.recipients.size.should == 1
65
+ end
66
+
67
+ #
68
+ # transports
69
+ #
70
+
71
+ it "should use beanstalkd as the default transport" do
72
+ options = { :notifiers => {},
73
+ :filters => [],
74
+ :log => MockLogger.new,
75
+ :persistence => {:backend => :mock_persistence_backend,
76
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')} }
77
+ app = Flapjack::Notifier::Application.run(options)
78
+ app.log.messages.find {|msg| msg =~ /loading.+beanstalkd.+transport/i}.should_not be_nil
79
+ end
80
+
81
+ it "should use a transport as specified in options" do
82
+ options = { :notifiers => {},
83
+ :filters => [],
84
+ :log => MockLogger.new,
85
+ :transport => {:backend => :beanstalkd},
86
+ :persistence => {:backend => :mock_persistence_backend,
87
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')} }
88
+ app = Flapjack::Notifier::Application.run(options)
89
+ app.log.messages.find {|msg| msg =~ /loading.+beanstalkd.+transport/i}.should_not be_nil
90
+ end
91
+
92
+ it "should error if the specified transport doesn't exist" do
93
+ options = { :notifiers => {},
94
+ :filters => [],
95
+ :log => MockLogger.new,
96
+ :transport => {:backend => :nonexistant} }
97
+ lambda {
98
+ app = Flapjack::Notifier::Application.run(options)
99
+ #app.log.messages.find {|msg| msg =~ /attempted to load nonexistant/i}.should_not be_nil
100
+ }.should raise_error
101
+ end
102
+
103
+ it "should use a limited interface for dealing with the results queue" do
104
+
105
+ # Interface for a Flapjack::Transport::<transport> is as follows:
106
+ #
107
+ # methods: next, delete
108
+ #
109
+
110
+ options = { :notifiers => {},
111
+ :filters => [],
112
+ :log => MockLogger.new,
113
+ :transport => {:backend => :mock_transport,
114
+ :basedir => File.join(File.dirname(__FILE__), 'transports')},
115
+ :persistence => {:backend => :mock_persistence_backend,
116
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')} }
117
+ app = Flapjack::Notifier::Application.run(options)
118
+
119
+ # processes a single result
120
+ app.process_result
121
+
122
+ # check that allowed methods were called
123
+ allowed_methods = %w(next delete)
124
+ allowed_methods.each do |method|
125
+ app.log.messages.find {|msg| msg =~ /#{method.gsub(/\?/,'\?')} was called on MockTransport/i}.should_not be_nil
126
+ end
127
+
128
+ # check that no other methods were
129
+ called_methods = app.log.messages.find_all {|msg| msg =~ /^method .+ was called on MockTransport$/i }.map {|msg| msg.split(' ')[1]}
130
+ (allowed_methods - called_methods).size.should == 0
131
+ end
132
+
133
+ it "should use a limited interface for dealing with results" do
134
+
135
+ # Interface for a Flapjack::Transport::Result is as follows:
136
+ #
137
+ # methods: id, warning?, critical?
138
+ #
139
+
140
+ options = { :notifiers => {},
141
+ :filters => ['ok'],
142
+ :log => MockLogger.new,
143
+ :transport => {:backend => :mock_transport,
144
+ :basedir => File.join(File.dirname(__FILE__), 'transports')},
145
+ :persistence => {:backend => :mock_persistence_backend,
146
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')} }
147
+ app = Flapjack::Notifier::Application.run(options)
148
+
149
+ # processes a single result
150
+ app.process_result
151
+
152
+ # check that allowed methods were called
153
+ allowed_methods = %w(check_id warning?)
154
+ allowed_methods.each do |method|
155
+ app.log.messages.find {|msg| msg =~ /#{method.gsub(/\?/,'\?')} was called/i}.should_not be_nil
156
+ end
157
+
158
+ # check that no other methods were called
159
+ called_methods = app.log.messages.find_all {|msg| msg =~ /^method .+ was called on MockResult$/i }.map {|msg| msg.split(' ')[1]}.uniq
160
+ (allowed_methods - called_methods).size.should == 0
161
+ end
162
+
163
+ it "should use a limited interface for dealing with the persistence backend" do
164
+
165
+ # Interface for a Flapjack::Persistence::<backend> is as follows:
166
+ #
167
+ # methods: any_parents_failed?, save
168
+ #
169
+
170
+ options = { :notifiers => {},
171
+ :filters => ['any_parents_failed'],
172
+ :log => MockLogger.new,
173
+ :transport => {:backend => :mock_transport,
174
+ :basedir => File.join(File.dirname(__FILE__), 'transports')},
175
+ :persistence => {:backend => :mock_persistence_backend,
176
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')} }
177
+ app = Flapjack::Notifier::Application.run(options)
178
+
179
+ # processes a single result
180
+ app.process_result
181
+
182
+ # check that allowed methods were called
183
+ allowed_methods = %w(any_parents_failed? save)
184
+ allowed_methods.each do |method|
185
+ app.log.messages.find {|msg| msg =~ /#{method.gsub(/\?/,'\?')} was called/i}.should_not be_nil
186
+ end
187
+
188
+ # check that no other methods were called
189
+ called_methods = app.log.messages.find_all {|msg| msg =~ /^method .+ was called on MockPersistenceBackend$/i }.map {|msg| msg.split(' ')[1]}
190
+ (allowed_methods - called_methods).size.should == 0
191
+ end
192
+
193
+
194
+ #
195
+ # persistence backend
196
+ #
197
+
198
+ it "should load couchdb as the default persistence backend"
199
+
200
+ it "should load a persistence backend as specified in options" do
201
+ options = { :notifiers => {},
202
+ :filters => [],
203
+ :log => MockLogger.new,
204
+ :persistence => {:backend => :mock_persistence_backend,
205
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')} }
206
+ app = Flapjack::Notifier::Application.run(options)
207
+ app.log.messages.find {|msg| msg =~ /loading.+MockPersistenceBackend.+backend/i}.should_not be_nil
208
+ end
209
+
210
+ it "should raise if the specified persistence backend doesn't exist" do
211
+ options = { :notifiers => {},
212
+ :filters => [],
213
+ :log => MockLogger.new,
214
+ :persistence => {:backend => :nonexistant} }
215
+ lambda {
216
+ app = Flapjack::Notifier::Application.run(options)
217
+ }.should raise_error(LoadError)
218
+ end
219
+
220
+ end
221
+
222
+ def puts(*args) ; end
@@ -0,0 +1,52 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'flapjack', 'applications', 'notifier')
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'flapjack', 'transports', 'result')
3
+ require File.join(File.dirname(__FILE__), 'helpers')
4
+
5
+ describe "running the notifier" do
6
+
7
+ before(:all) do
8
+ @options = { :notifiers => {:testmailer => {}},
9
+ :notifier_directories => [File.join(File.dirname(__FILE__),'notifier-directories', 'spoons')],
10
+ :recipients => [{:name => "Spoons McDoom"}],
11
+ :transport => {:backend => :mock_transport,
12
+ :basedir => File.join(File.dirname(__FILE__), 'transports')},
13
+ :persistence => {:backend => :mock_persistence_backend,
14
+ :basedir => File.join(File.dirname(__FILE__), 'persistence')},
15
+ :filter_directories => [File.join(File.dirname(__FILE__),'test-filters')]
16
+ }
17
+ end
18
+
19
+ it "should notify by default" do
20
+ @options[:filters] = []
21
+ @options[:log] = MockLogger.new
22
+
23
+ app = Flapjack::Notifier::Application.run(@options)
24
+ # processes a MockResult, as defined in spec/transports/mock_transport.rb
25
+ app.process_result
26
+
27
+ app.log.messages.find {|m| m =~ /testmailer notifying/i}.should be_true
28
+ end
29
+
30
+ it "should not notify if any filters fail" do
31
+ @options[:filters] = ['blocker']
32
+ @options[:log] = MockLogger.new
33
+
34
+ app = Flapjack::Notifier::Application.run(@options)
35
+ # processes a MockResult, as defined in spec/transports/mock_transport.rb
36
+ app.process_result
37
+
38
+ app.log.messages.find {|m| m =~ /testmailer notifying/i}.should be_nil
39
+ end
40
+
41
+ it "should notify if all filters pass" do
42
+ @options[:filters] = ['mock']
43
+ @options[:log] = MockLogger.new
44
+
45
+ app = Flapjack::Notifier::Application.run(@options)
46
+ # processes a MockResult, as defined in spec/transports/mock_transport.rb
47
+ app.process_result
48
+
49
+ app.log.messages.find {|m| m =~ /testmailer notifying/i}.should be_true
50
+ end
51
+
52
+ end
@@ -0,0 +1,71 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'flapjack', 'cli', 'notifier')
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'flapjack', 'patches')
3
+
4
+
5
+ describe "notifier options multiplexer" do
6
+
7
+ before(:all) do
8
+ @config_filename = File.join(File.dirname(__FILE__), 'configs', 'flapjack-notifier.ini')
9
+ @recipients_filename = File.join(File.dirname(__FILE__), 'configs', 'recipients.ini')
10
+
11
+ @couchdb_config_filename = File.join(File.dirname(__FILE__), 'configs', 'flapjack-notifier-couchdb.ini')
12
+ end
13
+
14
+ it "should setup notifier options from specified config file" do
15
+ args = ["-c", @config_filename, "-r", @recipients_filename]
16
+ config = Flapjack::Notifier::Options.parse(args)
17
+ config.notifiers.each do |key, value|
18
+ %w(mailer xmpp).include?(key)
19
+ end
20
+
21
+ config.notifier_directories.each do |dir|
22
+ %w(/usr/lib/flapjack/notifiers/ /path/to/my/notifiers).include?(dir)
23
+ end
24
+ end
25
+
26
+ it "should setup beanstalkd transport options from specified config file" do
27
+ args = ["-c", @config_filename, "-r", @recipients_filename]
28
+ config = Flapjack::Notifier::Options.parse(args)
29
+ config.transport[:backend].should == "beanstalkd"
30
+ config.transport[:host].should == "localhost"
31
+ config.transport[:port].should == "11300"
32
+ end
33
+
34
+ it "should setup datamapper persistence options from specified config file" do
35
+ args = ["-c", @config_filename, "-r", @recipients_filename]
36
+ config = Flapjack::Notifier::Options.parse(args)
37
+ config.persistence[:backend].should == "data_mapper"
38
+ config.persistence[:uri].should == "sqlite3:///tmp/flapjack.db"
39
+ end
40
+
41
+ it "should setup couchdb persistence backend from specified config file" do
42
+ args = [ "-c", @couchdb_config_filename, "-r", @recipients_filename ]
43
+ config = Flapjack::Notifier::Options.parse(args)
44
+ config.persistence[:backend].should == "couchdb"
45
+ config.persistence[:host].should == "localhost"
46
+ config.persistence[:port].should == "5984"
47
+ config.persistence[:version].should == "0.8"
48
+ config.persistence[:database].should == "flapjack_production"
49
+ end
50
+
51
+ it "should setup individual notifiers from a specified config file" do
52
+ args = [ "-c", @config_filename, "-r", @recipients_filename ]
53
+ config = Flapjack::Notifier::Options.parse(args)
54
+ config.notifiers.size.should > 0
55
+ end
56
+
57
+ it "should setup notifier directories options from a specified config file" do
58
+ args = [ "-c", @config_filename, "-r", @recipients_filename ]
59
+ config = Flapjack::Notifier::Options.parse(args)
60
+ config.notifier_directories.size.should > 0
61
+ end
62
+
63
+ it "should setup recipients from a specified config file" do
64
+ args = [ "-c", @config_filename, "-r", @recipients_filename ]
65
+ config = Flapjack::Notifier::Options.parse(args)
66
+ config.recipients.size.should > 0
67
+ end
68
+
69
+ end
70
+
71
+