flapjack 0.5.5 → 0.6.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. data/.gitignore +10 -0
  2. data/.rbenv-version +1 -0
  3. data/.rspec +10 -0
  4. data/Gemfile +18 -0
  5. data/Guardfile +14 -0
  6. data/README.md +152 -173
  7. data/Rakefile +53 -150
  8. data/bin/flapjack +72 -0
  9. data/bin/flapjack-nagios-receiver +111 -0
  10. data/bin/flapjack-nagios-receiver-control +15 -0
  11. data/bin/flapjack-netsaint-parser +0 -2
  12. data/bin/flapjack-populator +133 -16
  13. data/bin/install-flapjack-systemwide +2 -2
  14. data/config.ru +11 -0
  15. data/dist/etc/init.d/flapjack +46 -0
  16. data/dist/etc/init.d/flapjack-nagios-receiver +36 -0
  17. data/doc/GLOSSARY.md +19 -0
  18. data/etc/flapjack_config.yaml.example +90 -0
  19. data/features/events.feature +132 -0
  20. data/features/notifications.feature +57 -0
  21. data/features/packaging-lintian.feature +5 -3
  22. data/features/steps/events_steps.rb +164 -0
  23. data/features/steps/flapjack-importer_steps.rb +2 -5
  24. data/features/steps/flapjack-worker_steps.rb +13 -6
  25. data/features/steps/notifications_steps.rb +178 -0
  26. data/features/steps/packaging-lintian_steps.rb +14 -0
  27. data/features/steps/time_travel_steps.rb +34 -0
  28. data/features/support/env.rb +63 -36
  29. data/flapjack.gemspec +35 -186
  30. data/lib/flapjack.rb +2 -0
  31. data/lib/flapjack/api.rb +274 -0
  32. data/lib/flapjack/api/entity_check_presenter.rb +184 -0
  33. data/lib/flapjack/api/entity_presenter.rb +66 -0
  34. data/lib/flapjack/cli/worker_manager.rb +1 -2
  35. data/lib/flapjack/configuration.rb +11 -0
  36. data/lib/flapjack/coordinator.rb +288 -0
  37. data/lib/flapjack/daemonizing.rb +186 -0
  38. data/lib/flapjack/data/contact.rb +45 -0
  39. data/lib/flapjack/data/entity.rb +89 -0
  40. data/lib/flapjack/data/entity_check.rb +396 -0
  41. data/lib/flapjack/data/event.rb +144 -0
  42. data/lib/flapjack/data/notification.rb +13 -0
  43. data/lib/flapjack/executive.rb +289 -0
  44. data/lib/flapjack/filters/acknowledgement.rb +39 -0
  45. data/lib/flapjack/filters/{any_parents_failed.rb → base.rb} +6 -4
  46. data/lib/flapjack/filters/delays.rb +53 -0
  47. data/lib/flapjack/filters/detect_mass_client_failures.rb +44 -0
  48. data/lib/flapjack/filters/ok.rb +25 -5
  49. data/lib/flapjack/filters/scheduled_maintenance.rb +17 -0
  50. data/lib/flapjack/filters/unscheduled_maintenance.rb +17 -0
  51. data/lib/flapjack/jabber.rb +294 -0
  52. data/lib/flapjack/notification/common.rb +23 -0
  53. data/lib/flapjack/notification/email.rb +107 -0
  54. data/lib/flapjack/notification/email/alert.html.haml +48 -0
  55. data/lib/flapjack/notification/email/alert.text.erb +14 -0
  56. data/lib/flapjack/notification/sms.rb +42 -0
  57. data/lib/flapjack/notification/sms/messagenet.rb +49 -0
  58. data/lib/flapjack/notifier_engine.rb +4 -4
  59. data/lib/flapjack/notifiers/mailer/mailer.rb +6 -7
  60. data/lib/flapjack/notifiers/xmpp/xmpp.rb +12 -12
  61. data/lib/flapjack/pagerduty.rb +230 -0
  62. data/lib/flapjack/patches.rb +108 -19
  63. data/lib/flapjack/persistence/data_mapper/models/check.rb +5 -3
  64. data/lib/flapjack/persistence/data_mapper/models/check_template.rb +2 -0
  65. data/lib/flapjack/persistence/data_mapper/models/event.rb +2 -0
  66. data/lib/flapjack/persistence/data_mapper/models/node.rb +3 -1
  67. data/lib/flapjack/persistence/data_mapper/models/related_check.rb +3 -1
  68. data/lib/flapjack/pikelet.rb +56 -0
  69. data/lib/flapjack/transports/beanstalkd.rb +1 -1
  70. data/lib/flapjack/transports/result.rb +6 -6
  71. data/lib/flapjack/utility.rb +46 -0
  72. data/lib/flapjack/version.rb +5 -0
  73. data/lib/flapjack/web.rb +198 -0
  74. data/lib/flapjack/web/views/acknowledge.haml +55 -0
  75. data/lib/flapjack/web/views/check.haml +162 -0
  76. data/lib/flapjack/web/views/index.haml +92 -0
  77. data/lib/flapjack/web/views/self_stats.haml +56 -0
  78. data/lib/flapjack/{applications/worker.rb → worker/application.rb} +0 -0
  79. data/lib/flapjack/worker/cli.rb +49 -0
  80. data/{spec → spec.old}/check_sandbox/echo +0 -0
  81. data/{spec → spec.old}/check_sandbox/sandboxed_check +0 -0
  82. data/{spec → spec.old}/configs/flapjack-notifier-couchdb.ini +0 -0
  83. data/{spec → spec.old}/configs/flapjack-notifier.ini +0 -0
  84. data/{spec → spec.old}/configs/recipients.ini +0 -0
  85. data/{spec → spec.old}/helpers.rb +0 -0
  86. data/{spec → spec.old}/inifile_spec.rb +0 -0
  87. data/{spec → spec.old}/mock-notifiers/mock/init.rb +0 -0
  88. data/{spec → spec.old}/mock-notifiers/mock/mock.rb +0 -0
  89. data/{spec → spec.old}/notifier-directories/spoons/testmailer/init.rb +0 -0
  90. data/{spec → spec.old}/notifier_application_spec.rb +0 -0
  91. data/{spec → spec.old}/notifier_filters_spec.rb +0 -0
  92. data/{spec → spec.old}/notifier_options_multiplexer_spec.rb +0 -0
  93. data/{spec → spec.old}/notifier_options_spec.rb +0 -0
  94. data/{spec → spec.old}/notifier_spec.rb +0 -0
  95. data/{spec → spec.old}/notifiers/mailer_spec.rb +0 -0
  96. data/{spec → spec.old}/notifiers/xmpp_spec.rb +0 -0
  97. data/{spec → spec.old}/persistence/datamapper_spec.rb +0 -0
  98. data/{spec → spec.old}/persistence/mock_persistence_backend.rb +0 -0
  99. data/{spec → spec.old}/simple.ini +0 -0
  100. data/{spec → spec.old}/spec.opts +0 -0
  101. data/{spec → spec.old}/test-filters/blocker.rb +0 -0
  102. data/{spec → spec.old}/test-filters/mock.rb +0 -0
  103. data/{spec → spec.old}/transports/beanstalkd_spec.rb +0 -0
  104. data/{spec → spec.old}/transports/mock_transport.rb +0 -0
  105. data/{spec → spec.old}/worker_application_spec.rb +0 -0
  106. data/{spec → spec.old}/worker_options_spec.rb +0 -0
  107. data/spec/lib/flapjack/api/entity_check_presenter_spec.rb +117 -0
  108. data/spec/lib/flapjack/api/entity_presenter_spec.rb +92 -0
  109. data/spec/lib/flapjack/api_spec.rb +170 -0
  110. data/spec/lib/flapjack/coordinator_spec.rb +16 -0
  111. data/spec/lib/flapjack/data/entity_check_spec.rb +398 -0
  112. data/spec/lib/flapjack/data/entity_spec.rb +71 -0
  113. data/spec/lib/flapjack/data/event_spec.rb +6 -0
  114. data/spec/lib/flapjack/executive_spec.rb +59 -0
  115. data/spec/lib/flapjack/filters/acknowledgement_spec.rb +6 -0
  116. data/spec/lib/flapjack/filters/delays_spec.rb +6 -0
  117. data/spec/lib/flapjack/filters/detect_mass_client_failures_spec.rb +6 -0
  118. data/spec/lib/flapjack/filters/ok_spec.rb +6 -0
  119. data/spec/lib/flapjack/filters/scheduled_maintenance_spec.rb +6 -0
  120. data/spec/lib/flapjack/filters/unscheduled_maintenance_spec.rb +6 -0
  121. data/spec/lib/flapjack/jabber_spec.rb +150 -0
  122. data/spec/lib/flapjack/notification/email_spec.rb +6 -0
  123. data/spec/lib/flapjack/notification/sms_spec.rb +6 -0
  124. data/spec/lib/flapjack/pikelet_spec.rb +28 -0
  125. data/spec/lib/flapjack/web_spec.rb +188 -0
  126. data/spec/spec_helper.rb +44 -0
  127. data/spec/support/profile_all_formatter.rb +44 -0
  128. data/spec/support/uncolored_doc_formatter.rb +9 -0
  129. data/tasks/events.rake +85 -0
  130. data/tmp/acknowledge.rb +14 -0
  131. data/tmp/create_config_yaml.rb +16 -0
  132. data/tmp/create_events_failure.rb +33 -0
  133. data/tmp/create_events_ok.rb +33 -0
  134. data/tmp/create_events_ok_fail_ack_ok.rb +54 -0
  135. data/tmp/create_events_ok_failure.rb +40 -0
  136. data/tmp/create_events_ok_failure_ack.rb +54 -0
  137. data/tmp/dummy_entities.json +1 -0
  138. data/tmp/generate_nagios_test_hosts.rb +16 -0
  139. data/tmp/parse_config_yaml.rb +7 -0
  140. data/tmp/redis_delete_all_keys.rb +11 -0
  141. data/tmp/test_entities.json +1 -0
  142. metadata +482 -221
  143. data/TODO.md +0 -36
  144. data/VERSION +0 -1
  145. data/bin/flapjack-benchmark +0 -50
  146. data/bin/flapjack-notifier +0 -21
  147. data/bin/flapjack-notifier-manager +0 -43
  148. data/bin/flapjack-stats +0 -27
  149. data/bin/flapjack-worker +0 -13
  150. data/bin/flapjack-worker-manager +0 -35
  151. data/dist/etc/init.d/flapjack-notifier +0 -47
  152. data/dist/etc/init.d/flapjack-workers +0 -44
  153. data/features/flapjack-notifier-manager.feature +0 -19
  154. data/features/flapjack-worker-manager.feature +0 -27
  155. data/features/flapjack-worker.feature +0 -27
  156. data/features/netsaint-config-converter.feature +0 -126
  157. data/features/persistence/couch.feature +0 -105
  158. data/features/persistence/sqlite3.feature +0 -105
  159. data/features/persistence/steps/couch_steps.rb +0 -25
  160. data/features/persistence/steps/generic_steps.rb +0 -102
  161. data/features/persistence/steps/sqlite3_steps.rb +0 -13
  162. data/features/steps/flapjack-notifier-manager_steps.rb +0 -24
  163. data/features/steps/flapjack-worker-manager_steps.rb +0 -48
  164. data/lib/flapjack/applications/notifier.rb +0 -222
  165. data/lib/flapjack/cli/notifier.rb +0 -108
  166. data/lib/flapjack/cli/notifier_manager.rb +0 -86
  167. data/lib/flapjack/cli/worker.rb +0 -51
data/Rakefile CHANGED
@@ -1,176 +1,79 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'rubygems'
3
+ unless $:.include?(File.dirname(__FILE__) + '/lib/')
4
+ $: << File.dirname(__FILE__) + '/lib'
5
+ end
6
+
4
7
  require 'fileutils'
5
- require 'spec/rake/spectask'
6
8
  require 'rake'
7
9
 
8
- #
9
- # Release management
10
- #
11
- begin
12
- require 'jeweler'
13
- Jeweler::Tasks.new do |gem|
14
- gem.name = "flapjack"
15
- gem.summary = %Q{a scalable and distributed monitoring system}
16
- gem.description = %Q{lapjack is highly scalable and distributed monitoring system. It understands the Nagios plugin format, and can easily be scaled from 1 server to 1000.}
17
- gem.email = "lindsay@holmwood.id.au"
18
- gem.homepage = "http://flapjack-project.com/"
19
- gem.authors = ["Lindsay Holmwood"]
20
- gem.has_rdoc = false
21
-
22
- gem.add_dependency('daemons', '= 1.0.10')
23
- gem.add_dependency('beanstalk-client', '= 1.0.2')
24
- gem.add_dependency('log4r', '= 1.1.5')
25
- gem.add_dependency('xmpp4r', '= 0.5')
26
- gem.add_dependency('tmail', '= 1.2.3.1')
27
- gem.add_dependency('yajl-ruby', '= 0.6.4')
28
- gem.add_dependency('sqlite3-ruby', '= 1.2.5')
29
-
30
- # Don't release unsanitised NetSaint config into gem.
31
- gem.files.exclude('features/support/data/etc/netsaint')
32
- end
33
- Jeweler::GemcutterTasks.new
34
- rescue LoadError
35
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
36
- end
10
+ require 'resque/tasks'
37
11
 
38
- #
39
- # Testing
40
- #
41
- require 'rake/testtask'
42
- Rake::TestTask.new(:test) do |test|
43
- test.libs << 'lib' << 'test'
44
- test.pattern = 'test/**/test_*.rb'
45
- test.verbose = true
46
- end
12
+ Dir['tasks/**/*.rake'].each { |t| load t }
47
13
 
48
- begin
49
- require 'rcov/rcovtask'
50
- Rcov::RcovTask.new do |test|
51
- test.libs << 'test'
52
- test.pattern = 'test/**/test_*.rb'
53
- test.verbose = true
54
- end
55
- rescue LoadError
56
- task :rcov do
57
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
58
- end
14
+ require 'cucumber'
15
+ require 'cucumber/rake/task'
16
+ require 'colorize'
17
+ Cucumber::Rake::Task.new(:features) do |t|
18
+ t.cucumber_opts = "features --format pretty"
59
19
  end
60
20
 
61
- begin
62
- require 'cucumber/rake/task'
21
+ require 'rspec/core/rake_task'
22
+ RSpec::Core::RakeTask.new(:spec)
63
23
 
64
- Cucumber::Rake::Task.new do |task|
65
- task.cucumber_opts = "--require features/"
66
- end
67
- rescue LoadError
68
- end
24
+ task :default => :spec
69
25
 
70
- Spec::Rake::SpecTask.new do |t|
71
- t.spec_opts = ["--options", "spec/spec.opts"]
72
- end
73
- task :test => :check_dependencies
74
26
 
75
- task :default => :test
27
+ desc "build gem"
28
+ task :build => :verify do
29
+ build_output = `gem build flapjack.gemspec`
30
+ puts build_output
76
31
 
77
- require 'rake/rdoctask'
78
- Rake::RDocTask.new do |rdoc|
79
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
32
+ gem_filename = build_output[/File: (.*)/,1]
33
+ pkg_path = "pkg"
34
+ FileUtils.mkdir_p(pkg_path)
35
+ FileUtils.mv(gem_filename, pkg_path)
80
36
 
81
- rdoc.rdoc_dir = 'rdoc'
82
- rdoc.title = "flapjack #{version}"
83
- rdoc.rdoc_files.include('README*')
84
- rdoc.rdoc_files.include('lib/**/*.rb')
37
+ puts "Gem built in #{pkg_path}/#{gem_filename}".green
85
38
  end
86
39
 
87
- #
88
- # misc
89
- #
90
- desc "display FIXMEs in the codebase"
91
- task :fixmes do
92
- output = `grep -nR FIXME lib/* spec/* bin/`
93
- output.split("\n").each do |line|
94
- parts = line.split(':')
95
- puts "#{parts[0].strip} +#{parts[1].strip}"
96
- puts " - #{parts[3].strip}"
40
+ desc "push gem"
41
+ task :push do
42
+ filenames = Dir.glob("pkg/*.gem")
43
+ filenames_with_times = filenames.map do |filename|
44
+ [filename, File.mtime(filename)]
97
45
  end
46
+
47
+ newest = filenames_with_times.sort_by { |tuple| tuple.last }.last
48
+ newest_filename = newest.first
49
+
50
+ command = "gem push #{newest_filename}"
51
+ system(command)
98
52
  end
99
53
 
100
- desc "build a tarball suitable for building packages from"
101
- task :tarball do
102
- require 'open-uri'
103
- require 'tmpdir'
104
- tmpdir = Dir.mktmpdir
105
-
106
- current_commit = `git log`.first.split[1][0..5]
107
- release_tarball = "/tmp/flapjack-#{current_commit}.tar.gz"
108
- flapjack_path = File.join(tmpdir, "flapjack-#{current_commit}")
109
- repo_path = File.expand_path(File.dirname(__FILE__))
110
- ignores = %w(.gitignore .git)
111
-
112
- # create new staging directory
113
- command = "git clone #{repo_path} #{flapjack_path}"
114
- `#{command}`
115
-
116
- # remove files we don't want to publish
117
- ignores.each do |filename|
118
- path = File.join(flapjack_path, filename)
119
- FileUtils.rm_rf(path)
54
+ desc "clean up various generated files"
55
+ task :clean do
56
+ [ "pkg/"].each do |filename|
57
+ puts "Removing #{filename}"
58
+ FileUtils.rm_rf(filename)
120
59
  end
60
+ end
121
61
 
122
- deps = { :daemons => {
123
- :source => "http://rubyforge.org/frs/download.php/34223/daemons-1.0.10.tgz",
124
- :filename => "daemons-1.0.10.tar.gz"
125
- },
126
- :beanstalkd_client => {
127
- :source => "http://github.com/kr/beanstalk-client-ruby/tarball/v1.0.2",
128
- :filename => "beanstalkd-client-1.0.2.tar.gz"
129
- },
130
- :yajl_ruby => {
131
- :source => "http://github.com/brianmario/yajl-ruby/tarball/0.6.4",
132
- :filename => "yajl-ruby-0.6.4.tar.gz"
133
- },
134
- :tmail => {
135
- :source => "http://rubyforge.org/frs/download.php/35297/tmail-1.2.3.1.tgz",
136
- :filename => "tmail-1.2.3.1.tar.gz"
137
- },
138
- :xmpp4r => {
139
- :source => "http://download.gna.org/xmpp4r/xmpp4r-0.4.tgz",
140
- :filename => "xmpp4r-0.4.tar.gz"
141
- },
142
- :log4r => {
143
- :source => "http://qa.debian.org/watch/sf.php/log4r/log4r-1.0.5.tgz",
144
- :filename => "log4r-1.0.5.tar.gz"
145
- }
146
- }
147
- deps.each_pair do |name, details|
148
- puts "Pulling in #{name} dependency..."
149
- # save file
150
- saved_file = "/tmp/#{details[:filename]}"
151
- File.open(saved_file, 'w') do |f|
152
- f << open(details[:source]).read
62
+ namespace :verify do
63
+ task :uncommitted do
64
+ uncommitted = `git ls-files -m`.split("\n")
65
+ if uncommitted.size > 0
66
+ puts "The following files are uncommitted:".red
67
+ uncommitted.each do |filename|
68
+ puts " - #{filename}".red
69
+ end
70
+ exit 1
153
71
  end
154
-
155
- `tar zxf #{saved_file} -C #{tmpdir}`
156
72
  end
157
73
 
158
- # build tarball
159
- under = File.dirname(tmpdir)
160
- staging = File.join("/tmp", "flapjack-#{current_commit}")
161
- FileUtils.mv(tmpdir, staging)
162
- actual = File.basename(staging)
163
- command = "cd #{under} ; tar czf #{release_tarball} #{actual}"
164
- system(command)
165
-
166
- puts "Release tarball with deps at #{release_tarball}"
74
+ task :all => [ :uncommitted ]
167
75
  end
168
76
 
169
- desc "dump out statements to create sqlite3 schema"
170
- task :dm_debug do
171
- require 'lib/flapjack/persistence/data_mapper'
172
-
173
- DataMapper.logger.set_log(STDOUT, :debug)
174
- DataMapper.setup(:default, "sqlite3:///tmp/sqlite3.db")
175
- DataMapper.auto_migrate!
176
- end
77
+ # FIXME: getting that intermittent gherken lexing error so removing :features from verify list
78
+ #task :verify => [ 'verify:all', :spec, :features]
79
+ task :verify => [ 'verify:all', :spec]
data/bin/flapjack ADDED
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+ require 'optparse'
5
+ require 'ostruct'
6
+
7
+ options = OpenStruct.new
8
+ options.config = File.join('etc', 'flapjack_config.yaml')
9
+ options.daemonize = nil
10
+
11
+ OptionParser.new do |opts|
12
+ opts.banner = "Usage: flapjack [options]"
13
+
14
+ opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
15
+ options.config = c
16
+ end
17
+
18
+ opts.on("-d", "--[no-]daemonize", "Daemonize?") do |d|
19
+ options.daemonize = d
20
+ end
21
+
22
+ opts.on("-p", "--pidfile [PATH]", String, "PATH to the pidfile to write to") do |p|
23
+ options.pidfile = p
24
+ end
25
+
26
+ end.parse!(ARGV)
27
+
28
+ FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
29
+
30
+ # load the config hash for the current environment
31
+
32
+ if File.file?(options.config)
33
+ config = YAML::load_file(options.config)
34
+ else
35
+ puts "Could not find config file at '#{options.config}', you may want to specify one with the --config option"
36
+ exit(false)
37
+ end
38
+
39
+ config_env = config[FLAPJACK_ENV]
40
+
41
+ if config_env.nil? || config_env.empty?
42
+ puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
43
+ exit(false)
44
+ end
45
+
46
+ if options.pidfile.nil?
47
+ pid_file = (config_env['pid_file'] || 'tmp/pids/flapjack.pid')
48
+ else
49
+ pid_file = options.pidfile
50
+ end
51
+
52
+ # add lib to the default include path
53
+ unless $:.include?(File.dirname(__FILE__) + '/../lib/')
54
+ $: << File.dirname(__FILE__) + '/../lib'
55
+ end
56
+
57
+ # TODO Flapjack falls over when Redis restarted -- trap errors and attempt reconnect
58
+
59
+ require 'flapjack/coordinator'
60
+
61
+ coordinator = Flapjack::Coordinator.new(config_env)
62
+ coordinator.log_file = (config_env['log_file'] || 'log/flapjack.log')
63
+ coordinator.pid_file = pid_file
64
+
65
+ if options.daemonize.nil?
66
+ daemonize = !!config_env['daemonize']
67
+ else
68
+ daemonize = options.daemonize
69
+ end
70
+
71
+ puts "Daemonising ... " if daemonize
72
+ coordinator.start(:daemonize => daemonize)
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'redis'
4
+ require 'json'
5
+ require 'yaml'
6
+ require 'optparse'
7
+ require 'ostruct'
8
+ require 'flapjack/data/entity_check'
9
+
10
+ options = OpenStruct.new
11
+ options.config = File.join('etc', 'flapjack_config.yaml')
12
+ options.daemonize = nil
13
+
14
+ OptionParser.new do |opts|
15
+ opts.banner = "Usage: flapjack-nagios-receiver [options]"
16
+
17
+ opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
18
+ options.config = c
19
+ end
20
+
21
+ opts.on("-f", "--fifo [PATH]", String, "PATH to the nagios perfdata named pipe") do |f|
22
+ options.fifo_path = f
23
+ end
24
+
25
+ end.parse!(ARGV)
26
+
27
+ FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
28
+
29
+ # load the config hash for the current environment
30
+
31
+ if File.file?(options.config)
32
+ config = YAML::load(File.open(options.config))
33
+ else
34
+ puts "Could not find config file at '#{options.config}', you may want to specify one with the --config option"
35
+ exit(false)
36
+ end
37
+
38
+ config_env = config[FLAPJACK_ENV]
39
+
40
+ if config_env.nil? || config_env.empty?
41
+ puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
42
+ exit(false)
43
+ end
44
+
45
+ # add lib to the default include path
46
+ #unless $:.include?(File.dirname(__FILE__) + '/../lib/')
47
+ # $: << File.dirname(__FILE__) + '/../lib'
48
+ #end
49
+
50
+ # nagios.cfg contains the following templates for host and service data (modified from the default
51
+ # to include hoststate / servicestate, and a fake service 'HOST' for hostperfdata, so that the
52
+ # fields match up
53
+ # host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\tHOST\t$HOSTSTATE$\t$HOSTEXECUTIONTIME$\t$HOSTLATENCY$\t$HOSTOUTPUT$\t$HOSTPERFDATA$
54
+ # service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICESTATE$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$
55
+
56
+ @redis_host = config_env['redis']['host'] || 'localhost'
57
+ @redis_port = config_env['redis']['port'] || '6379'
58
+ @redis_path = config_env['redis']['path'] || nil
59
+ @redis_db = config_env['redis']['db'] || 0
60
+
61
+ if config_env.nil? || config_env.empty?
62
+ puts "No config data for environment '#{FLAPJACK_ENV}'"
63
+ exit(false)
64
+ end
65
+
66
+ def process_input
67
+
68
+ if @redis_path
69
+ redis = Redis.new(:db => @redis_db, :path => @redis_path)
70
+ else
71
+ redis = Redis.new(:db => @redis_db, :host => @redis_host, :port => @redis_port)
72
+ end
73
+
74
+ puts "ARGV after option processing looks like this: [#{ARGV.inspect}]"
75
+
76
+ begin
77
+ while line = ARGF.readline.split("\t")
78
+ object_type, timestamp, entity, check, state, check_time, check_latency, check_output, check_perfdata = line
79
+ puts "#{object_type}, #{timestamp}, #{entity}, #{check}, #{state}, #{check_output}"
80
+ next unless line.length == 9
81
+ next unless timestamp =~ /^\d+$/
82
+ next unless (object_type == '[HOSTPERFDATA]') or (object_type == '[SERVICEPERFDATA]')
83
+ state = 'ok' if state.downcase == 'up'
84
+ state = 'critical' if state.downcase == 'down'
85
+ event = {
86
+ 'entity' => entity,
87
+ 'check' => check,
88
+ 'type' => 'service',
89
+ 'state' => state,
90
+ 'summary' => check_output,
91
+ 'timestamp' => timestamp,
92
+ }.to_json
93
+ redis.rpush 'events', event
94
+ end
95
+ rescue Redis::CannotConnectError
96
+ puts "Error, unable to to connect to the redis server (#{$!})"
97
+ rescue EOFError
98
+ puts "Error - end of file reached when reading from the named pipe. Nagios down?"
99
+ sleep 10
100
+ end
101
+ end
102
+
103
+ def main
104
+ while true
105
+ process_input
106
+ sleep 10
107
+ end
108
+ end
109
+
110
+ main
111
+
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'daemons'
4
+ opts = {
5
+ :app_name => 'flapjack-nagios-receiver',
6
+ :dir_mode => :normal,
7
+ :dir => '/var/run/flapjack',
8
+ :multiple => false,
9
+ :backtrace => true,
10
+ :monitor => false,
11
+ :log_dir => '/var/log/flapjack',
12
+ :log_output => true,
13
+ }
14
+ Daemons.run(File.join(File.dirname(__FILE__) ,'flapjack-nagios-receiver'), opts)
15
+
@@ -1,7 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'pathname'
4
- require 'rubygems'
5
3
  require 'yajl/json_gem'
6
4
 
7
5
  module Netsaint
@@ -1,29 +1,146 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'rubygems'
4
3
  require 'yajl'
5
- require 'beanstalk-client'
4
+ require 'redis'
5
+ require 'yaml'
6
+ require 'optparse'
7
+ require 'ostruct'
8
+ require 'flapjack/data/entity_check'
6
9
 
7
- command = ARGV[0]
10
+ options = OpenStruct.new
11
+ options.config = File.join('etc', 'flapjack_config.yaml')
12
+ options.daemonize = nil
8
13
 
9
- case command
10
- when "deploy"
11
- options = ARGV[1..-1]
12
- options = Hash[options.map {|o| o.scan(/--(.+)=(.+)/).flatten }]
14
+ command = ARGV.shift
15
+
16
+ banner = "Usage: flapjack-populator command [options]\n"
17
+ banner += "\n"
18
+ banner += " commands:\n"
19
+ banner += " - import-entities\n"
20
+ banner += " - import-contacts\n"
21
+ banner += " - purge-events (purge queued monitoring events)\n"
22
+
23
+ OptionParser.new do |opts|
24
+ opts.banner = "Usage: flapjack-populator command [options]"
25
+
26
+ opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
27
+ options.config = c
28
+ end
29
+
30
+ opts.on("-f", "--from [FILE]", String, "path to the FILE to import") do |f|
31
+ options.from = f
32
+ end
33
+
34
+ end.parse!(ARGV)
35
+
36
+ FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
37
+
38
+ # load the config hash for the current environment
39
+
40
+ if File.file?(options.config)
41
+ config = YAML::load(File.open(options.config))
42
+ else
43
+ puts "Could not find config file at '#{options.config}', you may want to specify one with the --config option"
44
+ exit(false)
45
+ end
46
+
47
+ config_env = config[FLAPJACK_ENV]
13
48
 
14
- @queue = Beanstalk::Connection.new('localhost:11300', 'checks')
49
+ if config_env.nil? || config_env.empty?
50
+ puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
51
+ exit(false)
52
+ end
15
53
 
16
- filename = options["from"]
54
+ if options.from
55
+ filename = options.from
17
56
  file = File.new(filename)
18
- parser = Yajl::Parser.new
19
- batch = parser.parse(file)
20
- batch_id = batch["batch"]["id"]
57
+ end
58
+
59
+ parser = Yajl::Parser.new
60
+
61
+ @redis_host = config_env['redis']['host'] || 'localhost'
62
+ @redis_port = config_env['redis']['port'] || '6379'
63
+ @redis_path = config_env['redis']['path'] || nil
64
+ @redis_db = config_env['redis']['db'] || 0
21
65
 
22
- batch["checks"].each do |check|
23
- job = check.merge({"batch_id" => batch_id})
24
- @queue.yput(job)
66
+ # add lib to the default include path
67
+ unless $:.include?(File.dirname(__FILE__) + '/../lib/')
68
+ $: << File.dirname(__FILE__) + '/../lib'
69
+ end
70
+
71
+ def get_redis_connection
72
+ if @redis_path
73
+ redis = Redis.new(:db => @redis_db, :path => @redis_path)
74
+ else
75
+ redis = Redis.new(:db => @redis_db, :host => @redis_host, :port => @redis_port)
25
76
  end
77
+ redis
78
+ end
79
+
80
+ case command
81
+ when "import-contacts"
82
+ @persistence = get_redis_connection
83
+ contacts = parser.parse(file)
84
+ contacts.each {|contact|
85
+ if not contact['id']
86
+ puts "Contact not imported as it has no id: " + contact.inspect
87
+ next
88
+ end
89
+ @persistence.multi
90
+ @persistence.del("contact:#{contact['id']}")
91
+ @persistence.del("contact_media:#{contact['id']}")
92
+ @persistence.del("contact_pagerduty:#{contact['id']}")
93
+ @persistence.hset("contact:#{contact['id']}", 'first_name', contact['first_name'])
94
+ @persistence.hset("contact:#{contact['id']}", 'last_name', contact['last_name'])
95
+ @persistence.hset("contact:#{contact['id']}", 'email', contact['email'])
96
+ contact['media'].each_pair {|medium, address|
97
+ case medium
98
+ when 'pagerduty'
99
+ @persistence.hset("contact_media:#{contact['id']}", medium, address['service_key'])
100
+ @persistence.hset("contact_pagerduty:#{contact['id']}", 'subdomain', address['subdomain'])
101
+ @persistence.hset("contact_pagerduty:#{contact['id']}", 'username', address['username'])
102
+ @persistence.hset("contact_pagerduty:#{contact['id']}", 'password', address['password'])
103
+ else
104
+ @persistence.hset("contact_media:#{contact['id']}", medium, address)
105
+ end
106
+ }
107
+ @persistence.exec
108
+ }
109
+
110
+ when "import-entities"
111
+ @persistence = get_redis_connection
112
+ entities = parser.parse(file)
113
+ entities.each {|entity|
114
+ if not entity['id']
115
+ puts "Entity not imported as it has no id: " + entity.inspect
116
+ next
117
+ end
118
+ @persistence.multi
119
+ existing_name = @persistence.hget("entity:#{entity['id']}", 'name')
120
+ @persistence.del("entity_id:#{existing_name}") unless existing_name == entity['name']
121
+ @persistence.set("entity_id:#{entity['name']}", entity['id'])
122
+ @persistence.hset("entity:#{entity['id']}", 'name', entity['name'])
123
+
124
+ @persistence.del("contacts_for:#{entity['id']}")
125
+ entity['contacts'].each {|contact|
126
+ @persistence.sadd("contacts_for:#{entity['id']}", contact)
127
+ }
128
+ @persistence.exec
129
+
130
+ }
131
+
132
+ when "purge-events"
133
+ @persistence = get_redis_connection
134
+ events_size = @persistence.llen('events')
135
+ puts "purging #{events_size} events..."
136
+ timestamp = Time.now.to_i
137
+ puts "renaming events to events.#{timestamp}"
138
+ @persistence.rename('events', "events.#{timestamp}")
139
+ puts "setting expiry of events.#{timestamp} to 8 hours"
140
+ @persistence.expire("events.#{timestamp}", (60 * 60 * 8))
26
141
 
27
- puts "Deployed batch #{batch_id}"
142
+ else
143
+ puts "you need to give me something to do, eg a command like 'import-entities' or 'import-clients' etc"
144
+ raise ArgumentError
28
145
  end
29
146