flapjack 0.5.5 → 0.6.23

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.
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