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 +1 -1
- data/bin/flapjack-worker +1 -10
- data/features/flapjack-worker-manager.feature +6 -4
- data/features/flapjack-worker.feature +27 -0
- data/features/steps/flapjack-importer_steps.rb +2 -2
- data/features/steps/flapjack-worker_steps.rb +61 -0
- data/features/support/env.rb +44 -18
- data/flapjack.gemspec +4 -2
- data/lib/flapjack/applications/worker.rb +38 -16
- data/lib/flapjack/transports/beanstalkd.rb +21 -4
- metadata +6 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.5
|
data/bin/flapjack-worker
CHANGED
@@ -1,19 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
$: << File.
|
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-
|
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
|
-
@
|
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", @
|
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
|
data/features/support/env.rb
CHANGED
@@ -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
|
-
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
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.
|
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-
|
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
|
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
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
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:
|
4
|
+
hash: 1
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 5
|
9
|
-
-
|
10
|
-
version: 0.5.
|
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-
|
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
|