robot_sweatshop 0.4.12 → 0.4.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/bin/sweatshop +1 -1
- data/bin/sweatshop-api +2 -1
- data/bin/sweatshop-assembler +8 -6
- data/bin/sweatshop-conveyor +16 -11
- data/bin/sweatshop-job-dictionary +13 -8
- data/bin/sweatshop-logger +32 -0
- data/bin/sweatshop-overseer +0 -1
- data/bin/sweatshop-payload-parser +11 -6
- data/bin/sweatshop-worker +14 -13
- data/config.defaults.yaml +2 -0
- data/lib/robot_sweatshop/connections.rb +26 -0
- data/robot_sweatshop.eye +5 -8
- data/robot_sweatshop.gemspec +1 -1
- data/test/all.rb +1 -0
- data/test/logger_spec.rb +36 -0
- data/test/overseer_spec.rb +5 -5
- data/test/shared/helpers/input.rb +2 -2
- data/test/shared/scaffolding.rb +2 -1
- data/test/shared/stub.rb +2 -0
- data/test/worker_spec.rb +13 -13
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 08cbf83ffc230f92b481c9bd3e050e30c8b2a771
|
4
|
+
data.tar.gz: 3945c41f5f694828ad9651c18e6e8d33e761f0b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0c61a1c671dd53bf48c3aa723cc78b41266817492bc49312d2bdc1cb216491c2f2b597e83659e1ee9479519af92de3d3c207a60f536cd5f8dcebdaf04899195
|
7
|
+
data.tar.gz: 10fa29c67fc744705d541c7846bda2882529c7cf79279838e6c3028ba6795f6cecba7633d5d390efda31483a7db5dcaa5b16515bb18319a331575f871027b27b
|
data/Gemfile.lock
CHANGED
data/bin/sweatshop
CHANGED
@@ -7,7 +7,7 @@ require 'robot_sweatshop/config'
|
|
7
7
|
require 'robot_sweatshop/create-config-directories'
|
8
8
|
|
9
9
|
program :name, 'Robot Sweatshop'
|
10
|
-
program :version, '0.4.
|
10
|
+
program :version, '0.4.13'
|
11
11
|
program :description, 'A lightweight, nonopinionated CI server'
|
12
12
|
program :help, 'Author', 'Justin Scott <jvscott@gmail.com>'
|
13
13
|
|
data/bin/sweatshop-api
CHANGED
@@ -10,6 +10,7 @@ configure do
|
|
10
10
|
set :port, configatron.api_port
|
11
11
|
set :bind, configatron.http_bind
|
12
12
|
set :run, true
|
13
|
+
set :log, EZMQ::Logger.new('api')
|
13
14
|
set :conveyor, EZMQ::Client.new(port: configatron.conveyor_port)
|
14
15
|
settings.conveyor.serialize_with_json!
|
15
16
|
enable :cross_origin if configatron.http_cross_origin
|
@@ -20,7 +21,7 @@ get '/' do
|
|
20
21
|
end
|
21
22
|
|
22
23
|
post '/run/:job_name' do
|
23
|
-
|
24
|
+
settings.log.write "Received payload for #{params['job_name']}"
|
24
25
|
request.body.rewind
|
25
26
|
payload = request.body.read
|
26
27
|
hash = {
|
data/bin/sweatshop-assembler
CHANGED
@@ -5,7 +5,6 @@ require 'exponential_backoff'
|
|
5
5
|
require 'ezmq'
|
6
6
|
require 'robot_sweatshop/config'
|
7
7
|
require 'robot_sweatshop/connections'
|
8
|
-
$stdout.sync = true
|
9
8
|
include Contracts
|
10
9
|
using ExtendedEZMQ
|
11
10
|
|
@@ -45,7 +44,7 @@ def request_job
|
|
45
44
|
job_id = @sockets[:conveyor].request method: 'dequeue'
|
46
45
|
return nil if job_id.nil?
|
47
46
|
raw_job = @sockets[:conveyor].request method: 'lookup', data: job_id
|
48
|
-
|
47
|
+
@sockets[:logger].write "Assembling: '#{raw_job}'"
|
49
48
|
raw_job.merge job_id: job_id
|
50
49
|
end
|
51
50
|
|
@@ -87,15 +86,18 @@ job_search = Fiber.new do
|
|
87
86
|
end
|
88
87
|
end
|
89
88
|
|
90
|
-
puts 'Started'
|
91
89
|
@sockets = {
|
92
90
|
conveyor: EZMQ::Client.new(port: configatron.conveyor_port),
|
93
91
|
worker: EZMQ::Pusher.new(:bind, port: configatron.worker_port),
|
94
92
|
parser: EZMQ::Client.new(port: configatron.payload_parser_port),
|
95
|
-
dictionary: EZMQ::Client.new(port: configatron.job_dictionary_port)
|
93
|
+
dictionary: EZMQ::Client.new(port: configatron.job_dictionary_port),
|
94
|
+
logger: EZMQ::Logger.new('assembler')
|
96
95
|
}
|
97
|
-
@sockets.each
|
96
|
+
@sockets.each do |key, socket|
|
97
|
+
socket.serialize_with_json! unless key == :logger
|
98
|
+
end
|
98
99
|
|
100
|
+
@sockets[:logger].write 'Started'
|
99
101
|
loop do
|
100
102
|
job = job_search.resume
|
101
103
|
begin
|
@@ -104,7 +106,7 @@ loop do
|
|
104
106
|
assembled_job = assemble job, payload, definition
|
105
107
|
@sockets[:worker].send assembled_job
|
106
108
|
rescue RuntimeError => error
|
107
|
-
|
109
|
+
@sockets[:logger].write error.message
|
108
110
|
finish job[:job_id]
|
109
111
|
next
|
110
112
|
end
|
data/bin/sweatshop-conveyor
CHANGED
@@ -5,6 +5,7 @@ require 'contracts'
|
|
5
5
|
require 'robot_sweatshop/config'
|
6
6
|
require 'robot_sweatshop/connections'
|
7
7
|
using ExtendedEZMQ
|
8
|
+
include Contracts
|
8
9
|
|
9
10
|
queue_settings = {
|
10
11
|
name: 'test',
|
@@ -12,30 +13,28 @@ queue_settings = {
|
|
12
13
|
file: "#{configatron.database_path}/conveyor.db"
|
13
14
|
}
|
14
15
|
@items = StubbornQueue.new queue_settings
|
15
|
-
$stdout.sync = true
|
16
|
-
include Contracts
|
17
16
|
|
18
17
|
Contract Hash => Fixnum
|
19
18
|
def enqueue(item)
|
20
|
-
|
19
|
+
@sockets[:logger].write "enqueue #{item}"
|
21
20
|
@items.enqueue item
|
22
21
|
end
|
23
22
|
|
24
23
|
Contract None => Maybe[Fixnum]
|
25
24
|
def dequeue
|
26
|
-
|
25
|
+
@sockets[:logger].write 'dequeue'
|
27
26
|
@items.dequeue
|
28
27
|
end
|
29
28
|
|
30
29
|
Contract Fixnum => Hash
|
31
30
|
def lookup(id)
|
32
|
-
|
31
|
+
@sockets[:logger].write "lookup #{id}"
|
33
32
|
@items.lookup(id)
|
34
33
|
end
|
35
34
|
|
36
35
|
Contract Fixnum => Bool
|
37
36
|
def finish(id)
|
38
|
-
|
37
|
+
@sockets[:logger].write "finish #{id}"
|
39
38
|
@items.finish id
|
40
39
|
end
|
41
40
|
|
@@ -50,11 +49,17 @@ def complete(request)
|
|
50
49
|
send(request[:method])
|
51
50
|
end
|
52
51
|
|
53
|
-
|
54
|
-
server
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
@sockets = {
|
53
|
+
server: EZMQ::Server.new(port: configatron.conveyor_port),
|
54
|
+
logger: EZMQ::Logger.new('conveyor')
|
55
|
+
}
|
56
|
+
@sockets.each do |key, socket|
|
57
|
+
socket.serialize_with_json! unless key == :logger
|
58
|
+
end
|
59
|
+
|
60
|
+
@sockets[:logger].write 'Started'
|
61
|
+
@sockets[:server].listen do |request|
|
62
|
+
@sockets[:logger].write "Received: #{request.inspect}"
|
58
63
|
next unless request.is_a? Hash
|
59
64
|
next unless supported? request[:method]
|
60
65
|
complete request
|
@@ -4,7 +4,6 @@ require 'ezmq'
|
|
4
4
|
require 'contracts'
|
5
5
|
require 'robot_sweatshop/config'
|
6
6
|
require 'robot_sweatshop/connections'
|
7
|
-
$stdout.sync = true
|
8
7
|
include Contracts
|
9
8
|
using ExtendedEZMQ
|
10
9
|
|
@@ -15,13 +14,13 @@ end
|
|
15
14
|
|
16
15
|
Contract String => Or[Hash, nil]
|
17
16
|
def load_if_exists(config_path)
|
18
|
-
|
17
|
+
@sockets[:logger].write "Reading job configuration from #{config_path}"
|
19
18
|
YAML.load_file config_path if File.exist? config_path
|
20
19
|
end
|
21
20
|
|
22
21
|
Contract None => Hash
|
23
22
|
def empty_config
|
24
|
-
|
23
|
+
@sockets[:logger].write 'Job configuration not found or empty'
|
25
24
|
{}
|
26
25
|
end
|
27
26
|
|
@@ -43,10 +42,16 @@ def define(job_name)
|
|
43
42
|
formatted config
|
44
43
|
end
|
45
44
|
|
46
|
-
|
47
|
-
server
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
@sockets = {
|
46
|
+
server: EZMQ::Server.new(port: configatron.job_dictionary_port),
|
47
|
+
logger: EZMQ::Logger.new('job_dictionary')
|
48
|
+
}
|
49
|
+
@sockets.each do |key, socket|
|
50
|
+
socket.serialize_with_json! unless key == :logger
|
51
|
+
end
|
52
|
+
|
53
|
+
@sockets[:logger].write 'Started'
|
54
|
+
@sockets[:server].listen do |job_name|
|
55
|
+
@sockets[:logger].write "Looking up: #{job_name}"
|
51
56
|
define job_name
|
52
57
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'ezmq'
|
3
|
+
require 'robot_sweatshop/config'
|
4
|
+
require 'robot_sweatshop/connections'
|
5
|
+
using ExtendedEZMQ
|
6
|
+
|
7
|
+
@sockets = {
|
8
|
+
subscriber: EZMQ::Subscriber.new(:bind, port: configatron.logger_port, topic: 'robot-sweatshop-logging'),
|
9
|
+
reflector: EZMQ::Publisher.new(:bind, port: configatron.reflector_port)
|
10
|
+
}
|
11
|
+
@sockets.each do |key, socket|
|
12
|
+
socket.serialize_with_json! unless key == :logger
|
13
|
+
end
|
14
|
+
|
15
|
+
def write(text, for_process:)
|
16
|
+
log_file = File.expand_path "#{configatron.logfile_path}/#{for_process}.log"
|
17
|
+
File.open log_file, 'a' do |log|
|
18
|
+
log.write "[#{Time.now.utc}] #{text}\n"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_worker_id_from(data)
|
23
|
+
process, worker_id = data[:process].split '-'
|
24
|
+
data.merge process: process, text: "[#{worker_id}] #{data[:text]}"
|
25
|
+
end
|
26
|
+
|
27
|
+
write 'Started', for_process: 'logger'
|
28
|
+
@sockets[:subscriber].listen do |data, topic|
|
29
|
+
data = parse_worker_id_from data if data[:process] =~ /worker/
|
30
|
+
write data[:text], for_process: data[:process]
|
31
|
+
@sockets[:reflector].send data, topic: topic
|
32
|
+
end
|
data/bin/sweatshop-overseer
CHANGED
@@ -5,7 +5,6 @@ require 'contracts'
|
|
5
5
|
require 'robot_sweatshop/config'
|
6
6
|
require 'robot_sweatshop/payload'
|
7
7
|
require 'robot_sweatshop/connections'
|
8
|
-
$stdout.sync = true
|
9
8
|
include Contracts
|
10
9
|
using ExtendedEZMQ
|
11
10
|
|
@@ -57,11 +56,17 @@ def parse(raw_payload, format)
|
|
57
56
|
formatted payload
|
58
57
|
end
|
59
58
|
|
60
|
-
|
61
|
-
server
|
62
|
-
|
63
|
-
|
64
|
-
|
59
|
+
@sockets = {
|
60
|
+
server: EZMQ::Server.new(port: configatron.payload_parser_port),
|
61
|
+
logger: EZMQ::Logger.new('payload_parser')
|
62
|
+
}
|
63
|
+
@sockets.each do |key, socket|
|
64
|
+
socket.serialize_with_json! unless key == :logger
|
65
|
+
end
|
66
|
+
|
67
|
+
@sockets[:logger].write 'Started'
|
68
|
+
@sockets[:server].listen do |request|
|
69
|
+
@sockets[:logger].write "Parsing: #{request}"
|
65
70
|
format = detect_format_of request
|
66
71
|
parse request[:payload], format
|
67
72
|
end
|
data/bin/sweatshop-worker
CHANGED
@@ -5,10 +5,8 @@ require 'fileutils'
|
|
5
5
|
require 'contracts'
|
6
6
|
require 'robot_sweatshop/config'
|
7
7
|
require 'robot_sweatshop/connections'
|
8
|
-
using ExtendedEZMQ
|
9
|
-
$stdout.sync = true
|
10
|
-
$stderr.sync = true
|
11
8
|
include Contracts
|
9
|
+
using ExtendedEZMQ
|
12
10
|
|
13
11
|
# TODO: check existing worker ids. it'd be a problem to share a workspace
|
14
12
|
@worker_id = ARGV[0] || "#{Faker::Name.first_name}"
|
@@ -16,7 +14,7 @@ include Contracts
|
|
16
14
|
Contract Hash, Proc => Any
|
17
15
|
def from_workspace(named:)
|
18
16
|
workspace = "#{named}-#{@worker_id}"
|
19
|
-
|
17
|
+
@sockets[:logger].write "Workspace: #{workspace}"
|
20
18
|
path = File.expand_path "#{configatron.workspace_path}/#{workspace}"
|
21
19
|
FileUtils.mkpath path
|
22
20
|
Dir.chdir(path) { yield if block_given? }
|
@@ -31,25 +29,25 @@ Contract String, Hash => Maybe[IO]
|
|
31
29
|
def stream(command, with_context:)
|
32
30
|
command = ensure_shell_for command
|
33
31
|
IO.popen(with_context, command) do |stream|
|
34
|
-
|
32
|
+
@sockets[:logger].write stream.gets until stream.eof?
|
35
33
|
end
|
36
34
|
end
|
37
35
|
|
38
36
|
Contract String, Hash => nil
|
39
37
|
def execute(command, context)
|
40
|
-
|
38
|
+
@sockets[:logger].write "Executing '#{command}'"
|
41
39
|
begin
|
42
40
|
stream command, with_context: context
|
43
41
|
rescue Errno::ENOENT => error
|
44
|
-
|
42
|
+
@sockets[:logger].write error.message
|
45
43
|
end
|
46
|
-
|
44
|
+
@sockets[:logger].write "Execution complete with exit status: #{$?.exitstatus}"
|
47
45
|
end
|
48
46
|
|
49
47
|
Contract Fixnum => nil
|
50
48
|
def finish(id)
|
51
49
|
@sockets[:conveyor].request({ method: 'finish', data: id }, {})
|
52
|
-
|
50
|
+
@sockets[:logger].write "Job finished.\n\n"
|
53
51
|
end
|
54
52
|
|
55
53
|
Contract Array, Hash => Any
|
@@ -65,15 +63,18 @@ def run_implicit_job
|
|
65
63
|
run implicit_job['commands'], with_context: implicit_job['environment']
|
66
64
|
end
|
67
65
|
|
68
|
-
puts 'Starting'
|
69
66
|
@sockets = {
|
70
67
|
conveyor: EZMQ::Client.new(port: configatron.conveyor_port),
|
71
|
-
puller: EZMQ::Puller.new(:connect, port: configatron.worker_port)
|
68
|
+
puller: EZMQ::Puller.new(:connect, port: configatron.worker_port),
|
69
|
+
logger: EZMQ::Logger.new("worker-#{@worker_id}")
|
72
70
|
}
|
73
|
-
@sockets.each
|
71
|
+
@sockets.each do |key, socket|
|
72
|
+
socket.serialize_with_json! unless key == :logger
|
73
|
+
end
|
74
74
|
|
75
|
+
@sockets[:logger].write 'Started'
|
75
76
|
@sockets[:puller].listen do |data|
|
76
|
-
|
77
|
+
@sockets[:logger].write "Running: #{data}"
|
77
78
|
from_workspace named: data[:job_name] do
|
78
79
|
run data[:commands], with_context: data[:context]
|
79
80
|
run_implicit_job
|
data/config.defaults.yaml
CHANGED
@@ -16,3 +16,29 @@ module ExtendedEZMQ
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
# A logger that publishes what it writes
|
21
|
+
module EZMQ
|
22
|
+
class Logger
|
23
|
+
using ExtendedEZMQ
|
24
|
+
|
25
|
+
def initialize(process)
|
26
|
+
@process = process
|
27
|
+
@logger = EZMQ::Publisher.new :connect, port: configatron.logger_port
|
28
|
+
@logger.serialize_with_json!
|
29
|
+
@user = `whoami`.chomp
|
30
|
+
@host = `hostname`.chomp
|
31
|
+
end
|
32
|
+
|
33
|
+
def write(text)
|
34
|
+
data = {
|
35
|
+
text: text,
|
36
|
+
process: @process,
|
37
|
+
user: @user,
|
38
|
+
host: @host
|
39
|
+
}
|
40
|
+
@logger.send data, topic: 'robot-sweatshop-logging'
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/robot_sweatshop.eye
CHANGED
@@ -4,7 +4,6 @@ require 'yaml'
|
|
4
4
|
CONFIG_PATH = File.expand_path '~/.robot_sweatshop/compiled_config.yaml'
|
5
5
|
CONFIG = YAML.load_file CONFIG_PATH
|
6
6
|
PID_PATH = CONFIG[:pidfile_path]
|
7
|
-
LOG_PATH = CONFIG[:logfile_path]
|
8
7
|
|
9
8
|
Eye.config do
|
10
9
|
logger "#{CONFIG[:logfile_path]}/eye.log"
|
@@ -18,19 +17,16 @@ Eye.application :robot_sweatshop do
|
|
18
17
|
group 'services' do
|
19
18
|
process :job_dictionary do
|
20
19
|
pid_file "#{PID_PATH}/job-dictionary.pid"
|
21
|
-
stdall "#{LOG_PATH}/job-dictionary.log"
|
22
20
|
start_command "#{__dir__}/bin/sweatshop-job-dictionary"
|
23
21
|
daemonize true
|
24
22
|
end
|
25
23
|
process :payload_parser do
|
26
24
|
pid_file "#{PID_PATH}/payload-parser.pid"
|
27
|
-
stdall "#{LOG_PATH}/payload-parser.log"
|
28
25
|
start_command "#{__dir__}/bin/sweatshop-payload-parser"
|
29
26
|
daemonize true
|
30
27
|
end
|
31
28
|
process :conveyor do
|
32
29
|
pid_file "#{PID_PATH}/conveyor.pid"
|
33
|
-
stdall "#{LOG_PATH}/conveyor.log"
|
34
30
|
start_command "#{__dir__}/bin/sweatshop-conveyor"
|
35
31
|
daemonize true
|
36
32
|
end
|
@@ -38,26 +34,27 @@ Eye.application :robot_sweatshop do
|
|
38
34
|
|
39
35
|
process :overseer do
|
40
36
|
pid_file "#{PID_PATH}/overseer.pid"
|
41
|
-
stdall "#{LOG_PATH}/overseer.log"
|
42
37
|
start_command "#{__dir__}/bin/sweatshop-overseer"
|
43
38
|
daemonize true
|
44
39
|
end
|
45
40
|
process :api do
|
46
41
|
pid_file "#{PID_PATH}/api.pid"
|
47
|
-
stdall "#{LOG_PATH}/api.log"
|
48
42
|
start_command "#{__dir__}/bin/sweatshop-api"
|
49
43
|
daemonize true
|
50
44
|
end
|
51
45
|
process :assembler do
|
52
46
|
pid_file "#{PID_PATH}/assembler.pid"
|
53
|
-
stdall "#{LOG_PATH}/assembler.log"
|
54
47
|
start_command "#{__dir__}/bin/sweatshop-assembler"
|
55
48
|
daemonize true
|
56
49
|
end
|
57
50
|
process :worker do
|
58
51
|
pid_file "#{PID_PATH}/worker.pid"
|
59
|
-
stdall "#{LOG_PATH}/worker.log"
|
60
52
|
start_command "#{__dir__}/bin/sweatshop-worker"
|
61
53
|
daemonize true
|
62
54
|
end
|
55
|
+
process :logger do
|
56
|
+
pid_file "#{PID_PATH}/logger.pid"
|
57
|
+
start_command "#{__dir__}/bin/sweatshop-logger"
|
58
|
+
daemonize true
|
59
|
+
end
|
63
60
|
end
|
data/robot_sweatshop.gemspec
CHANGED
data/test/all.rb
CHANGED
data/test/logger_spec.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'kintama'
|
2
|
+
require 'ezmq'
|
3
|
+
require 'timeout'
|
4
|
+
require 'robot_sweatshop/config'
|
5
|
+
require 'robot_sweatshop/connections'
|
6
|
+
require_relative 'shared/scaffolding'
|
7
|
+
require_relative 'shared/helpers'
|
8
|
+
|
9
|
+
Kintama.on_start do
|
10
|
+
@pids = TestProcess.start %w(logger)
|
11
|
+
end
|
12
|
+
|
13
|
+
Kintama.on_finish do
|
14
|
+
TestProcess.stop @pids
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'the Logger' do
|
18
|
+
given 'log data from a process' do
|
19
|
+
setup do
|
20
|
+
@custom_logger = TestProcess.stub :logger
|
21
|
+
EZMQ::Logger.new('test_spec').write 'success'
|
22
|
+
sleep $a_while # TODO: Timeout wasn't working for some reason
|
23
|
+
# Also breaks if this is in the `should` block :S
|
24
|
+
end
|
25
|
+
|
26
|
+
should 'log the data to file' do
|
27
|
+
log_file = File.expand_path "#{configatron.logfile_path}/test_spec.log"
|
28
|
+
assert_match /success/, File.read(log_file)
|
29
|
+
end
|
30
|
+
|
31
|
+
should 'reflect the published message' do
|
32
|
+
reflection = File.read @custom_logger.output_file
|
33
|
+
assert_match /success/, reflection
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/test/overseer_spec.rb
CHANGED
@@ -7,7 +7,7 @@ require_relative 'shared/helpers'
|
|
7
7
|
$stdout.sync = true
|
8
8
|
|
9
9
|
Kintama.on_start do
|
10
|
-
@pids = TestProcess.start %w(overseer)
|
10
|
+
@pids = TestProcess.start %w(overseer logger)
|
11
11
|
sleep $a_while
|
12
12
|
end
|
13
13
|
|
@@ -23,7 +23,7 @@ given 'the Overseer' do
|
|
23
23
|
should('respond') { assert_equal 200, @response.code }
|
24
24
|
should('link to process logs') do
|
25
25
|
page = Nokogiri::HTML(@response.to_s)
|
26
|
-
links = page.css('a').select { |link| link.text.include? '
|
26
|
+
links = page.css('a').select { |link| link.text.include? 'logger' }
|
27
27
|
assert_not_equal 0, links.count
|
28
28
|
end
|
29
29
|
should('have a form for running jobs') do
|
@@ -36,12 +36,12 @@ given 'the Overseer' do
|
|
36
36
|
setup { Timeout.timeout($a_while) { @response = HTTP.get overseer_url('log') } }
|
37
37
|
should('redirect') { assert_equal 303, @response.code }
|
38
38
|
end
|
39
|
-
context '/log?for=
|
40
|
-
setup { Timeout.timeout($a_while) { @response = HTTP.get overseer_url('log?for=
|
39
|
+
context '/log?for=logger' do
|
40
|
+
setup { Timeout.timeout($a_while) { @response = HTTP.get overseer_url('log?for=logger') } }
|
41
41
|
should('respond') { assert_equal 200, @response.code }
|
42
42
|
should('show logs from file') do
|
43
43
|
page = Nokogiri::HTML(@response.to_s)
|
44
|
-
log = File.read "#{configatron.logfile_path}/
|
44
|
+
log = File.read "#{configatron.logfile_path}/logger.log"
|
45
45
|
output = page.css('.raw_log').first
|
46
46
|
assert_equal log, output.text, 'Expected raw log output'
|
47
47
|
end
|
data/test/shared/scaffolding.rb
CHANGED
@@ -41,7 +41,8 @@ module TestProcess
|
|
41
41
|
def self.stub(process_name)
|
42
42
|
process = {
|
43
43
|
conveyor: {type: 'Server', port: configatron.conveyor_port},
|
44
|
-
worker: {type: 'Puller', port: configatron.worker_port}
|
44
|
+
worker: {type: 'Puller', port: configatron.worker_port},
|
45
|
+
logger: {type: 'Subscriber', port: configatron.reflector_port}
|
45
46
|
}[process_name]
|
46
47
|
Stub.new process[:type], on_port: process[:port]
|
47
48
|
end
|
data/test/shared/stub.rb
CHANGED
data/test/worker_spec.rb
CHANGED
@@ -24,9 +24,13 @@ describe 'the Worker' do
|
|
24
24
|
|
25
25
|
setup do
|
26
26
|
@conveyor = TestProcess.stub :conveyor
|
27
|
+
@workspace_file = "#{configatron.workspace_path}/test_job-testingid/test.txt"
|
27
28
|
@pusher = EZMQ::Pusher.new :bind, port: configatron.worker_port
|
28
29
|
@pusher.serialize_with_json!
|
29
|
-
|
30
|
+
@pusher.send worker_push
|
31
|
+
Timeout.timeout($a_while) do
|
32
|
+
loop while @conveyor.output_empty?
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
teardown do
|
@@ -35,33 +39,29 @@ describe 'the Worker' do
|
|
35
39
|
|
36
40
|
given 'valid job data is pushed' do
|
37
41
|
setup do
|
38
|
-
@
|
39
|
-
|
40
|
-
loop until File.exist? worker_output
|
41
|
-
loop while @conveyor.output_empty?
|
42
|
-
end
|
43
|
-
@worker_data = eval File.read(@conveyor.output_file)
|
42
|
+
@logger_data = File.read @workspace_file
|
43
|
+
@conveyor_data = eval File.read(@conveyor.output_file)
|
44
44
|
end
|
45
45
|
|
46
46
|
should 'run the commands' do
|
47
|
-
|
47
|
+
assert_not_equal '', @logger_data
|
48
48
|
end
|
49
49
|
|
50
50
|
should 'run with the context as environment variables' do
|
51
|
-
assert_match /hello world/,
|
51
|
+
assert_match /hello world/, @logger_data
|
52
52
|
end
|
53
53
|
|
54
54
|
should 'run with custom scripts in the path' do
|
55
|
-
assert_match /custom/,
|
55
|
+
assert_match /custom/, @logger_data
|
56
56
|
end
|
57
57
|
|
58
58
|
should 'run implicit jobs' do
|
59
|
-
assert_match /implicit/,
|
59
|
+
assert_match /implicit/, @logger_data
|
60
60
|
end
|
61
61
|
|
62
62
|
should 'tell the conveyor that job is complete' do
|
63
|
-
assert_equal 'finish', @
|
64
|
-
assert_kind_of Fixnum, @
|
63
|
+
assert_equal 'finish', @conveyor_data[:method]
|
64
|
+
assert_kind_of Fixnum, @conveyor_data[:data]
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: robot_sweatshop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Scott
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faker
|
@@ -270,6 +270,7 @@ executables:
|
|
270
270
|
- sweatshop-assembler
|
271
271
|
- sweatshop-conveyor
|
272
272
|
- sweatshop-job-dictionary
|
273
|
+
- sweatshop-logger
|
273
274
|
- sweatshop-overseer
|
274
275
|
- sweatshop-payload-parser
|
275
276
|
- sweatshop-worker
|
@@ -289,6 +290,7 @@ files:
|
|
289
290
|
- bin/sweatshop-assembler
|
290
291
|
- bin/sweatshop-conveyor
|
291
292
|
- bin/sweatshop-job-dictionary
|
293
|
+
- bin/sweatshop-logger
|
292
294
|
- bin/sweatshop-overseer
|
293
295
|
- bin/sweatshop-payload-parser
|
294
296
|
- bin/sweatshop-worker
|
@@ -331,6 +333,7 @@ files:
|
|
331
333
|
- test/data/weird_job.yaml
|
332
334
|
- test/end-to-end_spec.rb
|
333
335
|
- test/job_dictionary_spec.rb
|
336
|
+
- test/logger_spec.rb
|
334
337
|
- test/overseer_spec.rb
|
335
338
|
- test/payload_parser_spec.rb
|
336
339
|
- test/shared/helpers.rb
|