baleen 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/baleen.gemspec +33 -0
- data/bin/baleen +17 -0
- data/lib/baleen/client.rb +45 -0
- data/lib/baleen/container.rb +49 -0
- data/lib/baleen/job.rb +19 -0
- data/lib/baleen/messages/messages.rb +48 -0
- data/lib/baleen/messages/request.rb +31 -0
- data/lib/baleen/messages/response.rb +29 -0
- data/lib/baleen/runner.rb +119 -0
- data/lib/baleen/server.rb +75 -0
- data/lib/baleen/task.rb +44 -0
- data/lib/baleen/utils/colored_puts.rb +17 -0
- data/lib/baleen/version.rb +3 -0
- data/lib/baleen.rb +5 -0
- data/poc/.gitignore +15 -0
- data/poc/Gemfile +49 -0
- data/poc/README.rdoc +261 -0
- data/poc/Rakefile +7 -0
- data/poc/app/assets/images/rails.png +0 -0
- data/poc/app/assets/javascripts/application.js +15 -0
- data/poc/app/assets/stylesheets/application.css +13 -0
- data/poc/app/controllers/application_controller.rb +3 -0
- data/poc/app/helpers/application_helper.rb +2 -0
- data/poc/app/mailers/.gitkeep +0 -0
- data/poc/app/models/.gitkeep +0 -0
- data/poc/app/models/ar_profile.rb +3 -0
- data/poc/app/views/layouts/application.html.erb +14 -0
- data/poc/config/application.rb +62 -0
- data/poc/config/boot.rb +6 -0
- data/poc/config/cucumber.yml +8 -0
- data/poc/config/database.yml +28 -0
- data/poc/config/environment.rb +5 -0
- data/poc/config/environments/development.rb +37 -0
- data/poc/config/environments/production.rb +67 -0
- data/poc/config/environments/test.rb +37 -0
- data/poc/config/initializers/backtrace_silencers.rb +7 -0
- data/poc/config/initializers/inflections.rb +15 -0
- data/poc/config/initializers/mime_types.rb +5 -0
- data/poc/config/initializers/secret_token.rb +7 -0
- data/poc/config/initializers/session_store.rb +8 -0
- data/poc/config/initializers/wrap_parameters.rb +14 -0
- data/poc/config/locales/en.yml +5 -0
- data/poc/config/routes.rb +58 -0
- data/poc/config.ru +4 -0
- data/poc/db/.gitkeep +0 -0
- data/poc/db/migrate/20130914144710_create_ar_profiles.rb +11 -0
- data/poc/db/schema.rb +24 -0
- data/poc/db/seeds.rb +7 -0
- data/poc/features/cpu_bound.feature +3 -0
- data/poc/features/io_bound.feature +3 -0
- data/poc/features/step_definitions/fake_test_steps.rb +25 -0
- data/poc/features/support/env.rb +60 -0
- data/poc/features/support/ruby_prof_cucumber.rb +15 -0
- data/poc/features/t1.feature +12 -0
- data/poc/features/t10.feature +12 -0
- data/poc/features/t2.feature +12 -0
- data/poc/features/t3.feature +12 -0
- data/poc/features/t4.feature +12 -0
- data/poc/features/t5.feature +12 -0
- data/poc/features/t6.feature +12 -0
- data/poc/features/t7.feature +12 -0
- data/poc/features/t8.feature +12 -0
- data/poc/features/t9.feature +12 -0
- data/poc/lib/assets/.gitkeep +0 -0
- data/poc/lib/tasks/.gitkeep +0 -0
- data/poc/lib/tasks/cucumber.rake +65 -0
- data/poc/public/404.html +26 -0
- data/poc/public/422.html +26 -0
- data/poc/public/500.html +25 -0
- data/poc/public/favicon.ico +0 -0
- data/poc/public/index.html +241 -0
- data/poc/public/robots.txt +5 -0
- data/poc/script/cucumber +10 -0
- data/poc/script/rails +6 -0
- data/poc/test/fixtures/.gitkeep +0 -0
- data/poc/test/fixtures/ar_profiles.yml +11 -0
- data/poc/test/functional/.gitkeep +0 -0
- data/poc/test/integration/.gitkeep +0 -0
- data/poc/test/performance/browsing_test.rb +12 -0
- data/poc/test/test_helper.rb +13 -0
- data/poc/test/unit/.gitkeep +0 -0
- data/poc/test/unit/ar_profile_test.rb +7 -0
- data/poc/vendor/assets/javascripts/.gitkeep +0 -0
- data/poc/vendor/assets/stylesheets/.gitkeep +0 -0
- data/poc/vendor/plugins/.gitkeep +0 -0
- metadata +262 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fc7921b0867d0a73836d50b562b35e7cf9692d7f
|
4
|
+
data.tar.gz: 43d2f2f70271efdd4407247e55e0341ffeb689ae
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2c9f0dab84c29a08f66fe481fa110c26ec6a8bf06b20826077c29cc2333696d7693209ea569d0a587a899144fa5bcefb42be29b4ff2824d4b06be2e68e6d8b78
|
7
|
+
data.tar.gz: 8ec1a88eac0e64c7402f9a2414c88bb9352a08fda0e68b8fdd3c0d90064e311a331c573f1bdfe4e3550d849f133fc5fe46a80949709e718e20c811e337b7c67a
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Kim, Hirokuni
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Baleen
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'baleen'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install baleen
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/baleen.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'baleen/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "baleen"
|
8
|
+
spec.version = Baleen::VERSION
|
9
|
+
spec.authors = ["Kim, Hirokuni"]
|
10
|
+
spec.email = ["kimh@kvh.co.jp"]
|
11
|
+
spec.description = %q{Ballen allows you to run standard ruby tests in parallel and isolated environment}
|
12
|
+
spec.summary = %q{Parallel and container-based test runner powered by Docker}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "pry"
|
24
|
+
spec.add_development_dependency "awesome_print"
|
25
|
+
spec.add_development_dependency "interactive_editor"
|
26
|
+
|
27
|
+
spec.add_runtime_dependency 'celluloid'
|
28
|
+
spec.add_runtime_dependency 'celluloid-io'
|
29
|
+
spec.add_runtime_dependency 'colorize'
|
30
|
+
spec.add_runtime_dependency 'thor'
|
31
|
+
|
32
|
+
end
|
33
|
+
|
data/bin/baleen
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
|
5
|
+
class BaleenCommand < Thor
|
6
|
+
|
7
|
+
desc "cucumber", "Running cucumber features"
|
8
|
+
option :image, :required => true
|
9
|
+
option :work_dir, :default => "./"
|
10
|
+
option :files, :default => "features"
|
11
|
+
option :before_command, :default => nil
|
12
|
+
def cucumber
|
13
|
+
puts options[:image]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
BaleenCommand.start
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'celluloid/io'
|
2
|
+
require 'celluloid/autostart'
|
3
|
+
|
4
|
+
module Baleen
|
5
|
+
class Client
|
6
|
+
include Celluloid::IO
|
7
|
+
finalizer :close
|
8
|
+
|
9
|
+
def initialize(host, port=12345)
|
10
|
+
@socket = TCPSocket.open(host, port)
|
11
|
+
@result = "running"
|
12
|
+
async.response
|
13
|
+
end
|
14
|
+
|
15
|
+
def request(request)
|
16
|
+
@socket.puts(request.to_json)
|
17
|
+
end
|
18
|
+
|
19
|
+
def response
|
20
|
+
loop { break if handle_response(@socket.gets) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def close
|
24
|
+
@socket.close if @socket
|
25
|
+
info "connection closed"
|
26
|
+
|
27
|
+
rescue IOError; nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def handle_response(response)
|
31
|
+
if response.nil?
|
32
|
+
raise RuntimeError, 'Connection closed by server'
|
33
|
+
end
|
34
|
+
|
35
|
+
info "Got response"
|
36
|
+
@result = Baleen::Message::Decoder.new(response).decode
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def result
|
41
|
+
@result
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Baleen
|
2
|
+
module Container
|
3
|
+
|
4
|
+
class DockerClient
|
5
|
+
Result = Struct.new("Result", :status_code, :container_id, :log)
|
6
|
+
|
7
|
+
def initialize(containers)
|
8
|
+
@containers = containers
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_container(params)
|
12
|
+
@container = @containers.create([params.shell, params.opt, params.commands], params.image)
|
13
|
+
end
|
14
|
+
|
15
|
+
def start_container
|
16
|
+
id = @container["Id"]
|
17
|
+
|
18
|
+
info "Start container #{id}"
|
19
|
+
@containers.start(id)
|
20
|
+
@containers.wait(id)
|
21
|
+
info "Finish container #{id}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def result
|
25
|
+
id = @container["Id"]
|
26
|
+
rst = @containers.show(id)
|
27
|
+
log = @containers.logs(id)
|
28
|
+
|
29
|
+
Result.new(
|
30
|
+
rst["State"]["ExitCode"],
|
31
|
+
rst["ID"],
|
32
|
+
log
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def kill_all
|
37
|
+
@containers.list.each do |container|
|
38
|
+
@containers.kill(container["Id"])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def status
|
43
|
+
info @containers.list
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
data/lib/baleen/job.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Baleen
|
4
|
+
module Message
|
5
|
+
|
6
|
+
class Decoder
|
7
|
+
|
8
|
+
def initialize(json_string)
|
9
|
+
@params = JSON.parse(json_string)
|
10
|
+
end
|
11
|
+
|
12
|
+
def decode
|
13
|
+
klass = @params.delete "klass"
|
14
|
+
Object.const_get(klass).new(symbolize_keys(@params))
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def symbolize_keys(hash)
|
20
|
+
hash.inject({}){|new_hash, key_value|
|
21
|
+
key, value = key_value
|
22
|
+
value = symbolize_keys(value) if value.is_a?(Hash)
|
23
|
+
new_hash[key.to_sym] = value
|
24
|
+
new_hash
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Base
|
30
|
+
attr_accessor :json_msg
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@params = {}
|
34
|
+
@params[:klass] = self.class.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def params
|
38
|
+
@params
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_json
|
42
|
+
@params.to_json
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Baleen
|
4
|
+
module Message
|
5
|
+
module Request
|
6
|
+
|
7
|
+
class ClientDisconnect < Base
|
8
|
+
def initialize(opt = {}); super() end
|
9
|
+
end
|
10
|
+
|
11
|
+
class PingPong < Base
|
12
|
+
def initialize(opt = {}); super() end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Cucumber < Base
|
16
|
+
def initialize(image: "kimh/baleen-poc", work_dir: "./", files: "./features", shell: "/bin/bash", opt: "-c", exe: "bundle exec cucumber", before_command: nil, command: nil)
|
17
|
+
super()
|
18
|
+
@params[:image] = image
|
19
|
+
@params[:shell] = shell
|
20
|
+
@params[:opt] = opt
|
21
|
+
@params[:work_dir] = work_dir
|
22
|
+
@params[:files] = files
|
23
|
+
@params[:exe] = exe
|
24
|
+
@params[:before_command] = before_command
|
25
|
+
@params[:command] = command
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Baleen
|
2
|
+
module Message
|
3
|
+
module Response
|
4
|
+
|
5
|
+
class JobComplete < Base
|
6
|
+
def initialize(opt = {})
|
7
|
+
super()
|
8
|
+
@params[:status_code] = opt[:status_code]
|
9
|
+
@params[:log ] = opt[:log]
|
10
|
+
@params[:container_id ] = opt[:log]
|
11
|
+
end
|
12
|
+
|
13
|
+
def status_code; @params[:status_code] end
|
14
|
+
def log; @params[:log] end
|
15
|
+
def container_id; @params[:container_id] end
|
16
|
+
end
|
17
|
+
|
18
|
+
class RunnerFinish < Base
|
19
|
+
def initialize(opt = {})
|
20
|
+
super()
|
21
|
+
@params[:status] = opt[:status]
|
22
|
+
end
|
23
|
+
|
24
|
+
def status; @params[:status] end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Baleen
|
2
|
+
|
3
|
+
class DockerParam
|
4
|
+
def initialize(params)
|
5
|
+
@params = params
|
6
|
+
end
|
7
|
+
|
8
|
+
def method_missing(name, *args)
|
9
|
+
DockerParam.class_eval{
|
10
|
+
define_method "#{name}" do
|
11
|
+
@params[name.to_sym]
|
12
|
+
end
|
13
|
+
|
14
|
+
define_method "#{name}=" do |*args|
|
15
|
+
@params[name.to_sym] = args.first
|
16
|
+
end
|
17
|
+
}
|
18
|
+
send(name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def commands
|
22
|
+
%{
|
23
|
+
#{@params[:before_command]}
|
24
|
+
cd #{@params[:work_dir]}
|
25
|
+
#{command}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def command
|
30
|
+
@params[:command] ||= %{#{@params[:exe]} #{@params[:files]}}
|
31
|
+
end
|
32
|
+
|
33
|
+
def command=(c)
|
34
|
+
@params[:command] = c
|
35
|
+
end
|
36
|
+
|
37
|
+
def dup
|
38
|
+
copy_params = @params.dup
|
39
|
+
Object.const_get(self.class.to_s).new(copy_params)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class RunnerManager
|
44
|
+
include Celluloid::IO
|
45
|
+
|
46
|
+
CONCURRENCY=2
|
47
|
+
|
48
|
+
def initialize(containers, socket, msg)
|
49
|
+
@containers = containers
|
50
|
+
@socket = socket
|
51
|
+
@queue = []
|
52
|
+
@params = DockerParam.new(msg.params)
|
53
|
+
end
|
54
|
+
|
55
|
+
def run
|
56
|
+
create_runners.each do |runners|
|
57
|
+
@queue = runners
|
58
|
+
@queue.each do |runner|
|
59
|
+
runner.async.run
|
60
|
+
end
|
61
|
+
loop {break if monitor_runners}
|
62
|
+
end
|
63
|
+
|
64
|
+
msg = Message::Response::RunnerFinish.new(status: "done")
|
65
|
+
@socket.puts(msg.to_json)
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def create_runners
|
71
|
+
target_files.map {|file|
|
72
|
+
@params.files = file
|
73
|
+
Runner.new(@containers, @params)
|
74
|
+
}.each_slice(CONCURRENCY).map {|r| r}
|
75
|
+
end
|
76
|
+
|
77
|
+
def target_files
|
78
|
+
params = @params.dup
|
79
|
+
params.command = %{find #{params.files} | grep "\\.feature"}
|
80
|
+
runner = Runner.new(@containers, params)
|
81
|
+
runner.run
|
82
|
+
runner.status.log.split("\n")
|
83
|
+
end
|
84
|
+
|
85
|
+
def monitor_runners
|
86
|
+
@queue.all?{ |r| r.status }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class Runner
|
91
|
+
include Celluloid::IO
|
92
|
+
|
93
|
+
attr_reader :status
|
94
|
+
|
95
|
+
def initialize(containers, params)
|
96
|
+
@docker_client = Container::DockerClient.new(containers)
|
97
|
+
@status = nil
|
98
|
+
@params = params
|
99
|
+
end
|
100
|
+
|
101
|
+
def run
|
102
|
+
start_runner do |result|
|
103
|
+
@status = Message::Response::JobComplete.new(
|
104
|
+
status_code: result.status_code,
|
105
|
+
container_id: result.container_id,
|
106
|
+
log: result.log
|
107
|
+
)
|
108
|
+
end
|
109
|
+
sleep 0.1 # Stop a moment until RunnerManager checks the status
|
110
|
+
end
|
111
|
+
|
112
|
+
def start_runner
|
113
|
+
@docker_client.create_container(@params)
|
114
|
+
@docker_client.start_container
|
115
|
+
yield( @docker_client.result )
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'docker'
|
2
|
+
require 'awesome_print'
|
3
|
+
require 'socket'
|
4
|
+
require 'celluloid/io'
|
5
|
+
require 'celluloid/autostart'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
module Baleen
|
9
|
+
|
10
|
+
class Server
|
11
|
+
include Celluloid::IO
|
12
|
+
finalizer :shutdown
|
13
|
+
|
14
|
+
attr_accessor :containers
|
15
|
+
|
16
|
+
def initialize(host, port: 4243)
|
17
|
+
@base_url = "http://#{host}:#{port}"
|
18
|
+
@docker = Docker::API.new(base_url: @base_url)
|
19
|
+
@containers = @docker.containers
|
20
|
+
@server = TCPServer.new("127.0.0.1", 12345)
|
21
|
+
async.run
|
22
|
+
end
|
23
|
+
|
24
|
+
def run
|
25
|
+
loop { async.handle_connection @server.accept }
|
26
|
+
end
|
27
|
+
|
28
|
+
def shutdown
|
29
|
+
@server.close if @server
|
30
|
+
end
|
31
|
+
|
32
|
+
def handle_connection(socket)
|
33
|
+
loop { handle_request(socket) }
|
34
|
+
|
35
|
+
rescue Exception => ex
|
36
|
+
case ex
|
37
|
+
when IOError; nil # when trying to close already closed socket
|
38
|
+
else
|
39
|
+
warn "Unknown exception occured"
|
40
|
+
ap ex
|
41
|
+
raise ex
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def handle_request(socket)
|
46
|
+
message = socket.gets
|
47
|
+
|
48
|
+
if message.nil?
|
49
|
+
socket.close
|
50
|
+
return
|
51
|
+
end
|
52
|
+
msg = parse_request(message)
|
53
|
+
|
54
|
+
case msg
|
55
|
+
when Message::Request::PingPong
|
56
|
+
socket.puts "pong"
|
57
|
+
when Message::Request::ClientDisconnect
|
58
|
+
socket.close
|
59
|
+
when Message::Request::Cucumber
|
60
|
+
manager = RunnerManager.new(@containers, socket, msg)
|
61
|
+
manager.run
|
62
|
+
else
|
63
|
+
warn "Received unknown request"
|
64
|
+
ap msg
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def parse_request(message)
|
69
|
+
#info "Got request from client"
|
70
|
+
#ap message
|
71
|
+
Baleen::Message::Decoder.new(message).decode
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/lib/baleen/task.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module Baleen
|
2
|
+
module Task
|
3
|
+
|
4
|
+
class Command
|
5
|
+
def initialize(work_dir, files, bundler)
|
6
|
+
@work_dir = work_dir
|
7
|
+
@files = files
|
8
|
+
@bundler = bundler
|
9
|
+
@before = []
|
10
|
+
build_default_arg
|
11
|
+
end
|
12
|
+
|
13
|
+
def before(commands=nil)
|
14
|
+
commands = sanitize_and_tokenize(commands) if commands
|
15
|
+
commands ? @before = commands : @before
|
16
|
+
end
|
17
|
+
|
18
|
+
def commands
|
19
|
+
@before ? @before + @args : @args
|
20
|
+
end
|
21
|
+
|
22
|
+
def <<(arg)
|
23
|
+
@args << arg
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def build_default_arg
|
29
|
+
exe = @bundler ? "bundle exec cucumber" : "cucumber"
|
30
|
+
@args = ["cd #{@work_dir}", "#{exe} #{@files}"]
|
31
|
+
end
|
32
|
+
|
33
|
+
def sanitize_and_tokenize(arg)
|
34
|
+
# sanitize
|
35
|
+
arg = arg.strip.gsub(/^ */, '').gsub(/\n+/, "\n")
|
36
|
+
# tokenize
|
37
|
+
arg = arg.gsub(";", "\n")
|
38
|
+
arg.split("\n")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
data/lib/baleen.rb
ADDED
data/poc/.gitignore
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile ~/.gitignore_global
|
6
|
+
|
7
|
+
# Ignore bundler config
|
8
|
+
/.bundle
|
9
|
+
|
10
|
+
# Ignore the default SQLite database.
|
11
|
+
/db/*.sqlite3
|
12
|
+
|
13
|
+
# Ignore all logfiles and tempfiles.
|
14
|
+
/log/*.log
|
15
|
+
/tmp
|