baleen 0.0.2 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc7921b0867d0a73836d50b562b35e7cf9692d7f
4
- data.tar.gz: 43d2f2f70271efdd4407247e55e0341ffeb689ae
3
+ metadata.gz: abadaf7bacf699bd38b6bc8825b8decd083de9f5
4
+ data.tar.gz: 8bc97b2c0b3806f1288f736dcc7141fd6a7ce7e1
5
5
  SHA512:
6
- metadata.gz: 2c9f0dab84c29a08f66fe481fa110c26ec6a8bf06b20826077c29cc2333696d7693209ea569d0a587a899144fa5bcefb42be29b4ff2824d4b06be2e68e6d8b78
7
- data.tar.gz: 8ec1a88eac0e64c7402f9a2414c88bb9352a08fda0e68b8fdd3c0d90064e311a331c573f1bdfe4e3550d849f133fc5fe46a80949709e718e20c811e337b7c67a
6
+ metadata.gz: ae47b1bff4d6b98b5cfd3def67984d7aac351b680a807b195c24d1135be62b7e1e60551b90a2b9ab6a593c3a1b87615b4a60b4781880ac9d42eacdd106079f75
7
+ data.tar.gz: 3ead613980c270d3095ba89647391d7a9af188d2edaaebead15ed9c8de08d70f8fe238f41cddb8a662ae68a23ad8aa7e157b9606fdff1334af47ad6c974c2913
data/Gemfile CHANGED
@@ -3,4 +3,5 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in baleen.gemspec
4
4
  gemspec
5
5
 
6
- gem 'docker-client', path: File.expand_path("/Users/kimh/git/docker-ruby", __FILE__)
6
+ #gem 'docker-client', path: File.expand_path("/Users/kimh/git/docker-ruby", __FILE__)
7
+ #gem 'baleen', path: File.expand_path("/Users/kimh/git/baleen", __FILE__)
data/README.md CHANGED
@@ -1,24 +1,64 @@
1
1
  # Baleen
2
+ Baleen is a test runner powered by Docker and Celluloid::IO.
3
+ Baleen allows you to run ruby standard tests such as Cucumber or Rspec in totally isolated environment and parallel.
2
4
 
3
- TODO: Write a gem description
5
+ By using Baleen, you can run feature or spec in a dedicated linux container, so test will not affect the state of other tests.
6
+ Also, Baleen will speed up your tests since multiple containers run their tests in parallel.
7
+
8
+ ## Requirement
9
+ Linux machine with Docker installed
4
10
 
5
11
  ## Installation
6
12
 
7
- Add this line to your application's Gemfile:
13
+ TODO
8
14
 
9
- gem 'baleen'
15
+ ## Usage
10
16
 
11
- And then execute:
12
17
 
13
- $ bundle
18
+ Baleen is server-client model. You need to run baleen-server which talks Docker API to Docker and you can use baleen-client to put your request to the server like below.
14
19
 
15
- Or install it yourself as:
20
+ $ bundle exec baleen cucumber --image kimh/baleen-poc --files features/ --work_dir /git/baleen/poc --before_command "source /etc/profile"
21
+ [Summary]
22
+ Result: Pass
23
+ Time: 0min 38sec
24
+ 12 containers
16
25
 
17
- $ gem install baleen
26
+ [Details]
27
+ Id: 5a836a088480f557bf79a00b0c6e34b36e8432f53ee8b5231b8983d902ae21d9
28
+ status code: 0
29
+ feature file: features/io_bound.feature
30
+ logs:
31
+ ------------------------------------
32
+ Rack::File headers parameter replaces cache_control after Rack 1.5.
33
+ Using the default profile...
34
+ Feature: Benchmark IO intensive feature
35
+
36
+ Scenario: Benchmark for IO bound operation # features/io_bound.feature:2
37
+ Then io intensive operation # features/step_definitions/fake_test_steps.rb:20
38
+
39
+ 1 scenario (1 passed)
40
+ 1 step (1 passed)
41
+ 0m1.556s
42
+
43
+ Id: 1e25993136553319379a07efd61fbc2b86094151fa25df4da0fc613f8c4fe87c
44
+ status code: 0
45
+ feature file: features/io_bound.feature
46
+ logs:
47
+ ------------------------------------
48
+ Rack::File headers parameter replaces cache_control after Rack 1.5.
49
+ Using the default profile...
50
+ Feature: Benchmark IO intensive feature
51
+
52
+ Scenario: Benchmark for IO bound operation # features/io_bound.feature:2
53
+ Then io intensive operation # features/step_definitions/fake_test_steps.rb:20
54
+
55
+ 1 scenario (1 passed)
56
+ 1 step (1 passed)
57
+ 0m1.518s
58
+
59
+ ....snip.....
18
60
 
19
- ## Usage
20
61
 
21
- TODO: Write usage instructions here
22
62
 
23
63
  ## Contributing
24
64
 
@@ -27,3 +67,4 @@ TODO: Write usage instructions here
27
67
  3. Commit your changes (`git commit -am 'Add some feature'`)
28
68
  4. Push to the branch (`git push origin my-new-feature`)
29
69
  5. Create new Pull Request
70
+
data/baleen.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Kim, Hirokuni"]
10
10
  spec.email = ["kimh@kvh.co.jp"]
11
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}
12
+ spec.summary = %q{Container-based parallel test runner powered by Docker}
13
13
  spec.homepage = ""
14
14
  spec.license = "MIT"
15
15
 
data/bin/baleen CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "thor"
4
+ require "baleen"
4
5
 
5
6
  class BaleenCommand < Thor
6
7
 
@@ -9,8 +10,19 @@ class BaleenCommand < Thor
9
10
  option :work_dir, :default => "./"
10
11
  option :files, :default => "features"
11
12
  option :before_command, :default => nil
13
+ option :host, :default => "127.0.0.1"
14
+ option :port, :default => "5533"
12
15
  def cucumber
13
- puts options[:image]
16
+ client = Baleen::Client.new(options[:host], options[:port])
17
+ request = Baleen::Message::Request::Cucumber.new(
18
+ image: options[:image],
19
+ work_dir: options[:work_dir],
20
+ files: options[:files],
21
+ before_command: options[:before_command],
22
+ )
23
+
24
+ job = Baleen::Job.new(client, request)
25
+ job.start
14
26
  end
15
27
  end
16
28
 
data/bin/baleen-server ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "thor"
4
+ require "baleen"
5
+
6
+ def pid
7
+ ### Use this when implement restart command
8
+ #pid = `ps ax | grep -E "baleen-server start|restart" | grep -v grep | awk '{print $1}'`
9
+ pid = `ps ax | grep -E "baleen-server start|restart" | grep -v grep | awk '{print $1}'`
10
+ pid.split("\n")
11
+ end
12
+
13
+ def running?
14
+ pid.size >= 1
15
+ end
16
+
17
+ class BaleenServerCli < Thor
18
+
19
+ desc "start", "Start Baleen server"
20
+ option :docker_host, :default => "127.0.0.1"
21
+ option :docker_port, :default => 4243
22
+ option :port, :default => 5533
23
+ option :debug, :type => :boolean
24
+ def start
25
+ if pid.size > 1
26
+ warning "baleen-server is already running"
27
+ warning "Exiting..."
28
+ exit
29
+ end
30
+
31
+ docker_host = options[:docker_host]
32
+ docker_port = options[:docker_port]
33
+ port = options[:port]
34
+ debug = options[:debug]
35
+
36
+ info "Starting baleen-server..."
37
+ info " Listening on: #{port}"
38
+ info " Docker API: http://#{docker_host}:#{docker_port}"
39
+
40
+ Process.daemon(true, debug)
41
+ Baleen::Server.new(docker_host: docker_host, docker_port: docker_port, port: port)
42
+
43
+ # Prevent main thread from exiting for Celluloid actors to continue running
44
+ # See https://github.com/celluloid/celluloid/wiki/Frequently-Asked-Questions
45
+ sleep
46
+ end
47
+
48
+ desc "stop", "Stop Baleen server"
49
+ def stop
50
+ if running?
51
+ notice "Stopping Baleen server..."
52
+ `kill -9 #{pid.first}`
53
+ else
54
+ notice "baleen-server is not running"
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ BaleenServerCli.start
data/lib/baleen.rb CHANGED
@@ -1,5 +1,14 @@
1
1
  require "baleen/version"
2
2
 
3
+ require 'baleen/client'
4
+ require 'baleen/message/message'
5
+ require 'baleen/task'
6
+ require 'baleen/job'
7
+
8
+ require 'baleen/server'
9
+ require 'baleen/container'
10
+ require 'baleen/runner'
11
+
3
12
  module Baleen
4
13
  # Your code goes here...
5
14
  end
data/lib/baleen/client.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'celluloid/io'
2
2
  require 'celluloid/autostart'
3
+ require 'baleen/utils/colored_puts'
3
4
 
4
5
  module Baleen
5
6
  class Client
@@ -8,16 +9,18 @@ module Baleen
8
9
 
9
10
  def initialize(host, port=12345)
10
11
  @socket = TCPSocket.open(host, port)
11
- @result = "running"
12
- async.response
13
12
  end
14
13
 
15
14
  def request(request)
16
15
  @socket.puts(request.to_json)
17
16
  end
18
17
 
19
- def response
20
- loop { break if handle_response(@socket.gets) }
18
+ def wait_response
19
+ loop {
20
+ if response = handle_response(@socket.gets)
21
+ return response
22
+ end
23
+ }
21
24
  end
22
25
 
23
26
  def close
@@ -32,13 +35,7 @@ module Baleen
32
35
  raise RuntimeError, 'Connection closed by server'
33
36
  end
34
37
 
35
- info "Got response"
36
- @result = Baleen::Message::Decoder.new(response).decode
37
- true
38
- end
39
-
40
- def result
41
- @result
38
+ Baleen::Message::Decoder.new(response).decode
42
39
  end
43
40
 
44
41
  end
@@ -0,0 +1,5 @@
1
+ module Baleen
2
+ module Error
3
+ class StartContainerFail < StandardError; end
4
+ end
5
+ end
data/lib/baleen/job.rb CHANGED
@@ -1,17 +1,28 @@
1
+ require 'baleen/result_display'
2
+
1
3
  module Baleen
2
4
  class Job
3
5
 
4
6
  def initialize(client, msg)
5
7
  @client = client
6
8
  @msg = msg
9
+ @response = nil
7
10
  end
8
11
 
9
12
  def start
13
+ start_time = Time.now
10
14
  @client.request(@msg.params)
15
+ @response = @client.wait_response
16
+ end_time = Time.now
17
+ show_results(start_time, end_time)
11
18
  end
12
19
 
13
- def result
14
- @client.result
20
+ private
21
+
22
+ def show_results(s_time, e_time)
23
+ display = ResultDisplay.new(@response, start_time: s_time, end_time: e_time)
24
+ display.summary
25
+ display.detail
15
26
  end
16
27
 
17
28
  end
@@ -3,7 +3,17 @@ require "json"
3
3
  module Baleen
4
4
  module Message
5
5
 
6
+ def symbolize_keys(hash)
7
+ hash.inject({}){|new_hash, key_value|
8
+ key, value = key_value
9
+ value = symbolize_keys(value) if value.is_a?(Hash)
10
+ new_hash[key.to_sym] = value
11
+ new_hash
12
+ }
13
+ end
14
+
6
15
  class Decoder
16
+ include Baleen::Message
7
17
 
8
18
  def initialize(json_string)
9
19
  @params = JSON.parse(json_string)
@@ -13,27 +23,24 @@ module Baleen
13
23
  klass = @params.delete "klass"
14
24
  Object.const_get(klass).new(symbolize_keys(@params))
15
25
  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
26
  end
28
27
 
29
28
  class Base
30
- attr_accessor :json_msg
31
29
 
32
30
  def initialize
33
31
  @params = {}
34
32
  @params[:klass] = self.class.to_s
35
33
  end
36
34
 
35
+ def method_missing(name, *args)
36
+ Base.class_eval{
37
+ define_method "#{name}" do
38
+ @params[name.to_sym]
39
+ end
40
+ }
41
+ send(name)
42
+ end
43
+
37
44
  def params
38
45
  @params
39
46
  end
@@ -0,0 +1,2 @@
1
+ require "baleen/message/request"
2
+ require "baleen/message/response"
@@ -1,4 +1,5 @@
1
1
  require "json"
2
+ require "baleen/message/base"
2
3
 
3
4
  module Baleen
4
5
  module Message
@@ -13,7 +14,7 @@ module Baleen
13
14
  end
14
15
 
15
16
  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
+ def initialize(image: nil, work_dir: "./", files: "features", shell: "/bin/bash", opt: "-c", exe: "bundle exec cucumber", before_command: nil, command: nil)
17
18
  super()
18
19
  @params[:image] = image
19
20
  @params[:shell] = shell
@@ -1,27 +1,32 @@
1
+ require 'json'
2
+
1
3
  module Baleen
2
4
  module Message
3
5
  module Response
4
6
 
5
- class JobComplete < Base
7
+ class RunnerFinish < Base
8
+
6
9
  def initialize(opt = {})
7
10
  super()
8
11
  @params[:status_code] = opt[:status_code]
9
12
  @params[:log ] = opt[:log]
10
- @params[:container_id ] = opt[:log]
13
+ @params[:container_id ] = opt[:container_id]
14
+ @params[:file] = opt[:file]
11
15
  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
16
  end
17
17
 
18
- class RunnerFinish < Base
18
+ class JobComplete < Base
19
+ include Baleen::Message
20
+
19
21
  def initialize(opt = {})
20
22
  super()
21
- @params[:status] = opt[:status]
23
+ @params[:status] = opt[:status]
24
+ @params[:results] = opt[:results]
22
25
  end
23
26
 
24
- def status; @params[:status] end
27
+ def result
28
+ JSON.parse(@params[:results]).map {|r| symbolize_keys(r) }
29
+ end
25
30
  end
26
31
 
27
32
  end
@@ -0,0 +1,47 @@
1
+ require "colorize"
2
+
3
+ module Baleen
4
+ class ResultDisplay
5
+ def initialize(result, start_time: nil, end_time: nil)
6
+ @result = result.result
7
+ @start_time = start_time
8
+ @end_time = end_time
9
+ end
10
+
11
+ def summary
12
+ tests_result = pass_all? ? "Pass".green : "Fail".red
13
+ time = run_time
14
+
15
+ puts ""
16
+ notice "[Summary]"
17
+ puts "Result: ".yellow + tests_result
18
+ puts "Time: ".yellow + time.green
19
+ puts ""
20
+ end
21
+
22
+ def detail
23
+ notice "[Details]"
24
+ @result.each do |r|
25
+ puts "Id: ".yellow + "#{r[:container_id]}".green
26
+ puts "status code: ".yellow + "#{r[:status_code]}".green
27
+ puts "feature file: ".yellow + "#{r[:file]}".green
28
+ puts "logs:".yellow
29
+ puts "------------------------------------".yellow
30
+ puts "#{r[:log]}".green
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def pass_all?
37
+ @result.all? {|r| r[:status_code] == 0}
38
+ end
39
+
40
+ def run_time
41
+ diff = @end_time - @start_time
42
+ min = (diff / 60).floor
43
+ sec = min != 0 ? (diff - (min * 60)).floor : diff.floor
44
+ "#{min}min #{sec}sec"
45
+ end
46
+ end
47
+ end
data/lib/baleen/runner.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require "baleen/error"
2
+
1
3
  module Baleen
2
4
 
3
5
  class DockerParam
@@ -49,6 +51,7 @@ module Baleen
49
51
  @containers = containers
50
52
  @socket = socket
51
53
  @queue = []
54
+ @results = []
52
55
  @params = DockerParam.new(msg.params)
53
56
  end
54
57
 
@@ -59,9 +62,9 @@ module Baleen
59
62
  runner.async.run
60
63
  end
61
64
  loop {break if monitor_runners}
65
+ @results += @queue.map {|runner| runner.status.params}
62
66
  end
63
-
64
- msg = Message::Response::RunnerFinish.new(status: "done")
67
+ msg = Message::Response::JobComplete.new(status: "done", results: @results.to_json)
65
68
  @socket.puts(msg.to_json)
66
69
  end
67
70
 
@@ -100,18 +103,30 @@ module Baleen
100
103
 
101
104
  def run
102
105
  start_runner do |result|
103
- @status = Message::Response::JobComplete.new(
106
+ @status = Message::Response::RunnerFinish.new(
104
107
  status_code: result.status_code,
105
108
  container_id: result.container_id,
106
- log: result.log
109
+ log: result.log,
110
+ file: @params.files,
107
111
  )
108
112
  end
109
113
  sleep 0.1 # Stop a moment until RunnerManager checks the status
110
114
  end
111
115
 
112
116
  def start_runner
113
- @docker_client.create_container(@params)
114
- @docker_client.start_container
117
+ max_retry = 3; count = 0
118
+
119
+ begin
120
+ @docker_client.create_container(@params)
121
+ @docker_client.start_container
122
+ rescue Docker::Error::ContainerNotFound => e
123
+ count += 1
124
+ if count > max_retry
125
+ raise Baleen::Error::StartContainerFail
126
+ else
127
+ retry
128
+ end
129
+ end
115
130
  yield( @docker_client.result )
116
131
  end
117
132
 
data/lib/baleen/server.rb CHANGED
@@ -13,11 +13,11 @@ module Baleen
13
13
 
14
14
  attr_accessor :containers
15
15
 
16
- def initialize(host, port: 4243)
17
- @base_url = "http://#{host}:#{port}"
16
+ def initialize(docker_host: "127.0.0.1", docker_port: 4243, port: 5533)
17
+ @base_url = "http://#{docker_host}:#{docker_port}"
18
18
  @docker = Docker::API.new(base_url: @base_url)
19
19
  @containers = @docker.containers
20
- @server = TCPServer.new("127.0.0.1", 12345)
20
+ @server = TCPServer.new("0.0.0.0", port)
21
21
  async.run
22
22
  end
23
23
 
@@ -7,11 +7,11 @@ module Kernel
7
7
  puts msg.green
8
8
  end
9
9
 
10
- def warn(msg)
10
+ def notice(msg)
11
11
  puts msg.yellow
12
12
  end
13
13
 
14
- def error(msg)
14
+ def warning(msg)
15
15
  puts msg.red
16
16
  end
17
17
  end
@@ -1,3 +1,3 @@
1
1
  module Baleen
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -6,7 +6,7 @@ CiApp::Application.configure do
6
6
  # since you don't have to restart the web server when you make code changes.
7
7
  config.cache_classes = false
8
8
 
9
- # Log error messages when you accidentally call methods on nil.
9
+ # Log error message when you accidentally call methods on nil.
10
10
  config.whiny_nils = true
11
11
 
12
12
  # Show full error reports and disable caching
@@ -11,7 +11,7 @@ CiApp::Application.configure do
11
11
  config.serve_static_assets = true
12
12
  config.static_cache_control = "public, max-age=3600"
13
13
 
14
- # Log error messages when you accidentally call methods on nil
14
+ # Log error message when you accidentally call methods on nil
15
15
  config.whiny_nils = true
16
16
 
17
17
  # Show full error reports and disable caching
@@ -2,11 +2,11 @@ Feature: t1
2
2
  Scenario: Benchmark for IO bound operation
3
3
  Then io intensive operation
4
4
 
5
- Scenario: Benchmark for CPU bound operation
6
- Then cpu intensive operation
5
+ #Scenario: Benchmark for CPU bound operation
6
+ # Then cpu intensive operation
7
7
 
8
- Scenario: Benchmark for IO bound operation
9
- Then io intensive operation
8
+ #Scenario: Benchmark for IO bound operation
9
+ # Then io intensive operation
10
10
 
11
- Scenario: Benchmark for CPU bound operation
12
- Then cpu intensive operation
11
+ #Scenario: Benchmark for CPU bound operation
12
+ # Then cpu intensive operation
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baleen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kim, Hirokuni
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-09 00:00:00.000000000 Z
11
+ date: 2013-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -142,6 +142,7 @@ email:
142
142
  - kimh@kvh.co.jp
143
143
  executables:
144
144
  - baleen
145
+ - baleen-server
145
146
  extensions: []
146
147
  extra_rdoc_files: []
147
148
  files:
@@ -152,13 +153,17 @@ files:
152
153
  - Rakefile
153
154
  - baleen.gemspec
154
155
  - bin/baleen
156
+ - bin/baleen-server
155
157
  - lib/baleen.rb
156
158
  - lib/baleen/client.rb
157
159
  - lib/baleen/container.rb
160
+ - lib/baleen/error.rb
158
161
  - lib/baleen/job.rb
159
- - lib/baleen/messages/messages.rb
160
- - lib/baleen/messages/request.rb
161
- - lib/baleen/messages/response.rb
162
+ - lib/baleen/message/base.rb
163
+ - lib/baleen/message/message.rb
164
+ - lib/baleen/message/request.rb
165
+ - lib/baleen/message/response.rb
166
+ - lib/baleen/result_display.rb
162
167
  - lib/baleen/runner.rb
163
168
  - lib/baleen/server.rb
164
169
  - lib/baleen/task.rb
@@ -258,5 +263,5 @@ rubyforge_project:
258
263
  rubygems_version: 2.0.3
259
264
  signing_key:
260
265
  specification_version: 4
261
- summary: Parallel and container-based test runner powered by Docker
266
+ summary: Container-based parallel test runner powered by Docker
262
267
  test_files: []