flapjack 0.5.4 → 0.5.5

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.4
1
+ 0.5.5
data/bin/flapjack-worker CHANGED
@@ -1,19 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $: << File.dirname(__FILE__) + '/../lib' unless $:.include?(File.dirname(__FILE__) + '/../lib/')
3
+ $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
4
4
 
5
5
  require 'flapjack/cli/worker'
6
6
  require 'flapjack/applications/worker'
7
7
 
8
- at_exit do
9
- puts "Shutting down"
10
- end
11
-
12
- trap("INT") do
13
- puts "Caught shutdown signal, cleaning up."
14
- exit
15
- end
16
-
17
8
  @options = Flapjack::WorkerOptions.parse(ARGV)
18
9
  app = Flapjack::Worker::Application.run(:host => @options.host,
19
10
  :port => @options.port,
@@ -1,25 +1,27 @@
1
- Feature: flapjack-notifier-manager
1
+ Feature: flapjack-worker-manager
2
2
  To scale Flapjack easily and efficiently
3
3
  A sysadmin
4
4
  Must be able to manage clusters of workers
5
+ With ease
6
+ From the command line
5
7
 
6
8
  Scenario: Running multiple workers
7
9
  Given the flapjack-worker-manager is on my path
8
10
  And beanstalkd is running on localhost
9
11
  And there are no instances of flapjack-worker running
10
- When I run "flapjack-worker-manager start"
12
+ When I run "flapjack-worker-manager start"
11
13
  Then 5 instances of "flapjack-worker" should be running
12
14
 
13
15
  Scenario: Running a specified number of workers
14
16
  Given the flapjack-worker-manager is on my path
15
17
  And beanstalkd is running on localhost
16
18
  And there are no instances of flapjack-worker running
17
- When I run "flapjack-worker-manager start --workers=10"
19
+ When I run "flapjack-worker-manager start --workers=10"
18
20
  Then 10 instances of "flapjack-worker" should be running
19
21
 
20
22
  Scenario: Stopping all workers
21
23
  Given there are 5 instances of the flapjack-worker running
22
24
  And beanstalkd is running on localhost
23
- When I run "flapjack-worker-manager stop"
25
+ When I run "flapjack-worker-manager stop"
24
26
  Then 0 instances of "flapjack-worker" should be running
25
27
 
@@ -0,0 +1,27 @@
1
+ Feature: flapjack-worker
2
+ To be alerted to problems
3
+ A user
4
+ Needs checks executed
5
+ On a regular schedule
6
+ And the results of those checks
7
+ Need to be reported
8
+
9
+ Scenario: Start a worker
10
+ Given beanstalkd is running
11
+ When I background run "flapjack-worker"
12
+ Then I should see "flapjack-worker" running
13
+ Then I should see "Waiting for check" in the "flapjack-worker" output
14
+
15
+ Scenario: Start a worker without beanstalk running
16
+ Given beanstalkd is not running
17
+ When I background run "flapjack-worker"
18
+ Then I should see "flapjack-worker" running
19
+ Then I should not see "Shutting down" in the "flapjack-worker" output
20
+
21
+ Scenario: Beanstalk disappears while worker running
22
+ Given beanstalkd is running
23
+ When I background run "flapjack-worker"
24
+ And beanstalkd is killed
25
+ Then I should see "flapjack-worker" running
26
+ Then I should not see "Shutting down" in the "flapjack-worker" output
27
+ Then I should see "went away" in the "flapjack-worker" output
@@ -71,13 +71,13 @@ end
71
71
  Given /^beanstalkd is running$/ do
72
72
  system("which beanstalkd > /dev/null 2>&1").should be_true
73
73
 
74
- @pipe = IO.popen("beanstalkd")
74
+ @beanstalk = IO.popen("beanstalkd")
75
75
 
76
76
  # So beanstalkd has a moment to catch its breath.
77
77
  sleep 0.5
78
78
 
79
79
  at_exit do
80
- Process.kill("KILL", @pipe.pid)
80
+ Process.kill("KILL", @beanstalk.pid)
81
81
  end
82
82
  end
83
83
 
@@ -0,0 +1,61 @@
1
+ Given /^beanstalkd is not running$/ do
2
+ if @beanstalk
3
+ Process.kill("KILL", @beanstalk.pid)
4
+ end
5
+ end
6
+
7
+ Then /^I should see "([^"]*)" running$/ do |command|
8
+ instance_variable_name = "@" + command.split("-")[1]
9
+ pipe = instance_variable_get(instance_variable_name)
10
+ pipe.should_not be_nil
11
+ `ps -p #{pipe.pid}`.split("\n").size.should == 2
12
+ end
13
+
14
+ When /^I background run "flapjack-worker"$/ do
15
+ @root = Pathname.new(File.dirname(__FILE__)).parent.parent.expand_path
16
+ bin_path = @root.join('bin')
17
+ command = "#{bin_path}/flapjack-worker 2>&1"
18
+
19
+ @worker = IO.popen(command, 'r')
20
+
21
+ sleep 1
22
+
23
+ at_exit do
24
+ Process.kill("KILL", @worker.pid)
25
+ end
26
+ end
27
+
28
+ Then /^I should see "([^"]*)" in the "([^"]*)" output$/ do |string, command|
29
+ instance_variable_name = "@" + command.split("-")[1]
30
+ pipe = instance_variable_get(instance_variable_name)
31
+ pipe.should_not be_nil
32
+
33
+ @output = read_until_timeout(pipe, 4)
34
+ @output.grep(/#{string}/).size.should > 0
35
+ end
36
+
37
+ Then /^I should not see "([^"]*)" in the "([^"]*)" output$/ do |string, command|
38
+ instance_variable_name = "@" + command.split("-")[1]
39
+ pipe = instance_variable_get(instance_variable_name)
40
+ pipe.should_not be_nil
41
+
42
+ @output = read_until_timeout(pipe, 4)
43
+ @output.grep(/#{string}/).size.should == 0
44
+ end
45
+
46
+ When /^beanstalkd is killed$/ do
47
+ Given "beanstalkd is not running"
48
+ end
49
+
50
+ Then /^show me the output from "([^"]*)"$/ do |command|
51
+ instance_variable_name = "@" + command.split("-")[1]
52
+ pipe = instance_variable_get(instance_variable_name)
53
+ pipe.should_not be_nil
54
+
55
+ @output = read_until_timeout(pipe, 5)
56
+ puts @output
57
+ end
58
+
59
+ When /^I sleep "(\d+)" seconds$/ do |time|
60
+ sleep(time.to_i)
61
+ end
@@ -2,24 +2,50 @@
2
2
 
3
3
  $: << File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib'))
4
4
 
5
+ require 'pathname'
5
6
  require 'yajl'
6
7
  require 'beanstalk-client'
7
8
 
8
- #require 'flapjack/inifile'
9
- #require 'flapjack/filters/ok'
10
- #require 'flapjack/filters/any_parents_failed'
11
- #require 'flapjack/notifier_engine'
12
- #require 'flapjack/transports/result'
13
- #require 'flapjack/transports/beanstalkd'
14
- #require 'flapjack/patches'
15
- #require 'flapjack/inifile'
16
- #require 'flapjack/cli/worker_manager'
17
- #require 'flapjack/cli/notifier_manager'
18
- #require 'flapjack/cli/notifier'
19
- #require 'flapjack/cli/worker'
20
- #require 'flapjack/persistence/couch'
21
- #require 'flapjack/persistence/sqlite3'
22
- #require 'flapjack/applications/notifier'
23
- #require 'flapjack/applications/worker'
24
- #require 'flapjack/notifiers/mailer/init'
25
- #require 'flapjack/notifiers/xmpp/init'
9
+ class ProcessManagement
10
+ # Cleans up daemons that were started in a scenario.
11
+ # We kill these daemons so the test state is clean at the beginning of every
12
+ # scenario, and scenarios don't become coupled with one another.
13
+ def kill_lingering_daemons
14
+ # FIXME: iterate through a collection of daemons registered during the scenario
15
+ Process.kill("KILL", @beanstalk.pid) if @beanstalk
16
+ end
17
+
18
+ # Testing daemons with Ruby backticks blocks indefinitely, because the
19
+ # backtick method waits for the program to exit. We use the select() system
20
+ # call to read from a pipe connected to a daemon, and return if no data is
21
+ # read within the specified timeout.
22
+ #
23
+ # http://weblog.jamisbuck.org/assets/2006/9/25/gdb.rb
24
+ def read_until_timeout(pipe, timeout=1, verbose=false)
25
+ output = []
26
+ line = ""
27
+ while data = IO.select([pipe], nil, nil, timeout) do
28
+ next if data.empty?
29
+ char = pipe.read(1)
30
+ break if char.nil?
31
+
32
+ line << char
33
+ if line[-1] == ?\n
34
+ puts line if verbose
35
+ output << line
36
+ line = ""
37
+ end
38
+ end
39
+
40
+ output
41
+ end
42
+
43
+ end
44
+
45
+ After do |scenario|
46
+ kill_lingering_daemons
47
+ end
48
+
49
+ World do
50
+ ProcessManagement.new
51
+ end
data/flapjack.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{flapjack}
8
- s.version = "0.5.4"
8
+ s.version = "0.5.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Lindsay Holmwood"]
12
- s.date = %q{2011-01-14}
12
+ s.date = %q{2011-01-18}
13
13
  s.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.}
14
14
  s.email = %q{lindsay@holmwood.id.au}
15
15
  s.executables = ["flapjack-benchmark", "flapjack-netsaint-parser", "flapjack-notifier", "flapjack-notifier-manager", "flapjack-populator", "flapjack-stats", "flapjack-worker", "flapjack-worker-manager", "install-flapjack-systemwide"]
@@ -52,6 +52,7 @@ Gem::Specification.new do |s|
52
52
  "doc/PACKAGING.md",
53
53
  "features/flapjack-notifier-manager.feature",
54
54
  "features/flapjack-worker-manager.feature",
55
+ "features/flapjack-worker.feature",
55
56
  "features/netsaint-config-converter.feature",
56
57
  "features/packaging-lintian.feature",
57
58
  "features/persistence/couch.feature",
@@ -63,6 +64,7 @@ Gem::Specification.new do |s|
63
64
  "features/steps/flapjack-netsaint-parser_steps.rb",
64
65
  "features/steps/flapjack-notifier-manager_steps.rb",
65
66
  "features/steps/flapjack-worker-manager_steps.rb",
67
+ "features/steps/flapjack-worker_steps.rb",
66
68
  "features/steps/packaging-lintian_steps.rb",
67
69
  "features/support/env.rb",
68
70
  "features/support/silent_system.rb",
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  require 'log4r'
4
4
  require 'log4r/outputter/syslogoutputter'
@@ -7,8 +7,8 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'patches'))
7
7
  module Flapjack
8
8
  module Worker
9
9
  class Application
10
-
11
- # boots the notifier
10
+
11
+ # boots the worker
12
12
  def self.run(options={})
13
13
  app = self.new(options)
14
14
  app.setup_loggers
@@ -22,15 +22,28 @@ module Flapjack
22
22
 
23
23
  def initialize(options={})
24
24
  @log = options[:log]
25
- @notifier_directories = options[:notifier_directories]
26
25
  @options = options
26
+
27
+ setup_event_handlers
28
+ end
29
+
30
+
31
+ def setup_event_handlers
32
+ at_exit do
33
+ @log.info("Shutting down")
34
+ end
35
+
36
+ trap("INT") do
37
+ puts "Caught shutdown signal, cleaning up."
38
+ exit
39
+ end
27
40
  end
28
41
 
29
42
  def setup_loggers
30
43
  unless @log
31
- @log = Log4r::Logger.new("notifier")
32
- @log.add(Log4r::StdoutOutputter.new("notifier"))
33
- @log.add(Log4r::SyslogOutputter.new("notifier"))
44
+ @log = Log4r::Logger.new("worker")
45
+ @log.add(Log4r::StdoutOutputter.new("worker"))
46
+ @log.add(Log4r::SyslogOutputter.new("worker"))
34
47
  end
35
48
  end
36
49
 
@@ -39,25 +52,26 @@ module Flapjack
39
52
  end
40
53
 
41
54
  def setup_queues
42
- defaults = { :backend => :beanstalkd,
43
- :host => 'localhost',
55
+ defaults = { :backend => :beanstalkd,
56
+ :host => 'localhost',
44
57
  :port => '11300',
45
58
  :log => @log }
46
59
  config = defaults.merge(@config.transport || {})
47
60
  basedir = config.delete(:basedir) || File.join(File.dirname(__FILE__), '..', 'transports')
48
61
 
49
62
  %w(results checks).each do |queue_name|
50
-
63
+
51
64
  queue_config = config.merge(:queue_name => queue_name)
52
-
65
+
53
66
  class_name = config[:backend].to_s.camel_case
54
- filename = File.join(basedir, "#{config[:backend]}.rb")
55
-
67
+ filename = File.expand_path(File.join(basedir, "#{config[:backend]}.rb"))
68
+
56
69
  @log.info("Loading the #{class_name} transport for queue: #{queue_name}.")
57
70
 
58
- begin
71
+ begin
59
72
  require filename
60
- queue = Flapjack::Transport.const_get("#{class_name}").new(queue_config)
73
+ transport = Flapjack::Transport.const_get("#{class_name}")
74
+ queue = transport.new(queue_config)
61
75
  instance_variable_set("@#{queue_name}_queue", queue)
62
76
  rescue LoadError => e
63
77
  @log.warning("Attempted to load #{class_name} transport, but it doesn't exist!")
@@ -67,6 +81,14 @@ module Flapjack
67
81
  end
68
82
  end
69
83
 
84
+ def log(level, opts={})
85
+ if opts[:data]
86
+ @log.method(level).call(pp opts[:data])
87
+ else
88
+ @log.method(level).call(opts[:message])
89
+ end
90
+ end
91
+
70
92
  def process_check
71
93
  @log.info("Waiting for check...")
72
94
  check = @checks_queue.next
@@ -89,7 +111,7 @@ module Flapjack
89
111
 
90
112
  def main
91
113
  @log.info("Booting main loop.")
92
- loop do
114
+ loop do
93
115
  process_check
94
116
  end
95
117
  end
@@ -10,18 +10,35 @@ module Flapjack
10
10
  def initialize(options={})
11
11
  @options = options
12
12
  @config = OpenStruct.new(options)
13
+ @log = @config.log
13
14
 
14
15
  unless @config.host && @config.port && @config.queue_name
15
16
  raise ArgumentError, "You need to specify a beanstalkd host, port, and queue name to connect to."
16
17
  end
17
18
 
18
- @queue = Beanstalk::Pool.new(["#{@config.host}:#{@config.port}"], @config.queue_name)
19
+ connect
20
+ end
21
+
22
+ def connect
23
+ begin
24
+ @queue = Beanstalk::Pool.new(["#{@config.host}:#{@config.port}"], @config.queue_name)
25
+ rescue Beanstalk::NotConnected => e
26
+ @log.error("Couldn't connect to the '#{@config.queue_name}' Beanstalk queue. Waiting 5 seconds, then retrying.")
27
+ sleep 5
28
+ retry
29
+ end
19
30
  end
20
31
 
21
32
  def next
22
- job = @queue.reserve # blocks
23
- result = YAML::load(job.body)
24
- Flapjack::Transport::Result.new(:job => job, :result => result)
33
+ begin
34
+ job = @queue.reserve # blocks
35
+ result = YAML::load(job.body)
36
+ Flapjack::Transport::Result.new(:job => job, :result => result)
37
+ rescue Beanstalk::NotConnected
38
+ @log.error("The '#{@config.queue_name}' Beanstalk queue went away. Waiting 5 seconds, then retrying.")
39
+ sleep 5
40
+ retry
41
+ end
25
42
  end
26
43
 
27
44
  def delete(result)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flapjack
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
4
+ hash: 1
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 5
9
- - 4
10
- version: 0.5.4
9
+ - 5
10
+ version: 0.5.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Lindsay Holmwood
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-14 00:00:00 +11:00
18
+ date: 2011-01-18 00:00:00 +11:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -182,6 +182,7 @@ files:
182
182
  - doc/PACKAGING.md
183
183
  - features/flapjack-notifier-manager.feature
184
184
  - features/flapjack-worker-manager.feature
185
+ - features/flapjack-worker.feature
185
186
  - features/netsaint-config-converter.feature
186
187
  - features/packaging-lintian.feature
187
188
  - features/persistence/couch.feature
@@ -193,6 +194,7 @@ files:
193
194
  - features/steps/flapjack-netsaint-parser_steps.rb
194
195
  - features/steps/flapjack-notifier-manager_steps.rb
195
196
  - features/steps/flapjack-worker-manager_steps.rb
197
+ - features/steps/flapjack-worker_steps.rb
196
198
  - features/steps/packaging-lintian_steps.rb
197
199
  - features/support/env.rb
198
200
  - features/support/silent_system.rb