flapjack 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
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