baleen 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.gitmodules +3 -0
- data/Dockerfile +1 -0
- data/Gemfile +1 -0
- data/README.md +1 -0
- data/baleen.gemspec +2 -0
- data/baleen.yml.sample +46 -0
- data/bin/baleen +91 -22
- data/bin/baleen-server +47 -16
- data/lib/baleen/builder.rb +46 -0
- data/lib/baleen/ci_server.rb +63 -0
- data/lib/baleen/client.rb +19 -9
- data/lib/baleen/configuration.rb +24 -0
- data/lib/baleen/connection.rb +47 -0
- data/lib/baleen/default.rb +57 -0
- data/lib/baleen/error.rb +9 -0
- data/lib/baleen/job.rb +7 -5
- data/lib/baleen/message/base.rb +9 -40
- data/lib/baleen/message/exception.rb +21 -0
- data/lib/baleen/message/message.rb +3 -2
- data/lib/baleen/message/to_client.rb +32 -0
- data/lib/baleen/project.rb +122 -0
- data/lib/baleen/result_display.rb +24 -16
- data/lib/baleen/runner.rb +41 -92
- data/lib/baleen/serializable.rb +61 -0
- data/lib/baleen/server.rb +40 -18
- data/lib/baleen/task/base.rb +55 -0
- data/lib/baleen/task/cucumber.rb +44 -0
- data/lib/baleen/task/generic.rb +17 -0
- data/lib/baleen/task/image_update.rb +22 -0
- data/lib/baleen/task/run_project.rb +14 -0
- data/lib/baleen/task/task.rb +5 -0
- data/lib/baleen/utils/{colored_puts.rb → highlighter.rb} +3 -3
- data/lib/baleen/utils/logger.rb +74 -0
- data/lib/baleen/validator.rb +115 -0
- data/lib/baleen/version.rb +1 -1
- data/lib/baleen.rb +11 -3
- data/spec/lib/baleen/spec_result_display.rb +47 -0
- data/spec/lib/baleen/spec_serializable.rb +45 -0
- data/spec/lib/baleen/spec_task.rb +62 -0
- data/spec/lib/baleen/spec_validator.rb +53 -0
- data/spec/spec_helper.rb +31 -0
- metadata +62 -76
- data/lib/baleen/container.rb +0 -32
- data/lib/baleen/message/request.rb +0 -29
- data/lib/baleen/message/response.rb +0 -34
- data/poc/.gitignore +0 -15
- data/poc/Gemfile +0 -49
- data/poc/README.rdoc +0 -261
- data/poc/Rakefile +0 -7
- data/poc/app/assets/images/rails.png +0 -0
- data/poc/app/assets/javascripts/application.js +0 -15
- data/poc/app/assets/stylesheets/application.css +0 -13
- data/poc/app/controllers/application_controller.rb +0 -3
- data/poc/app/helpers/application_helper.rb +0 -2
- data/poc/app/mailers/.gitkeep +0 -0
- data/poc/app/models/.gitkeep +0 -0
- data/poc/app/models/ar_profile.rb +0 -3
- data/poc/app/views/layouts/application.html.erb +0 -14
- data/poc/config/application.rb +0 -62
- data/poc/config/boot.rb +0 -6
- data/poc/config/cucumber.yml +0 -8
- data/poc/config/database.yml +0 -28
- data/poc/config/environment.rb +0 -5
- data/poc/config/environments/development.rb +0 -37
- data/poc/config/environments/production.rb +0 -67
- data/poc/config/environments/test.rb +0 -37
- data/poc/config/initializers/backtrace_silencers.rb +0 -7
- data/poc/config/initializers/inflections.rb +0 -15
- data/poc/config/initializers/mime_types.rb +0 -5
- data/poc/config/initializers/secret_token.rb +0 -7
- data/poc/config/initializers/session_store.rb +0 -8
- data/poc/config/initializers/wrap_parameters.rb +0 -14
- data/poc/config/locales/en.yml +0 -5
- data/poc/config/routes.rb +0 -58
- data/poc/config.ru +0 -4
- data/poc/db/.gitkeep +0 -0
- data/poc/db/migrate/20130914144710_create_ar_profiles.rb +0 -11
- data/poc/db/schema.rb +0 -24
- data/poc/db/seeds.rb +0 -7
- data/poc/features/step_definitions/fake_test_steps.rb +0 -25
- data/poc/features/support/env.rb +0 -60
- data/poc/features/support/ruby_prof_cucumber.rb +0 -15
- data/poc/features/t1.feature +0 -12
- data/poc/features/t10.feature +0 -12
- data/poc/features/t2.feature +0 -12
- data/poc/features/t3.feature +0 -12
- data/poc/features/t4.feature +0 -12
- data/poc/features/t5.feature +0 -12
- data/poc/features/t6.feature +0 -12
- data/poc/features/t7.feature +0 -12
- data/poc/features/t8.feature +0 -12
- data/poc/features/t9.feature +0 -12
- data/poc/lib/assets/.gitkeep +0 -0
- data/poc/lib/tasks/.gitkeep +0 -0
- data/poc/lib/tasks/cucumber.rake +0 -65
- data/poc/public/404.html +0 -26
- data/poc/public/422.html +0 -26
- data/poc/public/500.html +0 -25
- data/poc/public/favicon.ico +0 -0
- data/poc/public/index.html +0 -241
- data/poc/public/robots.txt +0 -5
- data/poc/script/cucumber +0 -10
- data/poc/script/rails +0 -6
- data/poc/test/fixtures/.gitkeep +0 -0
- data/poc/test/fixtures/ar_profiles.yml +0 -11
- data/poc/test/functional/.gitkeep +0 -0
- data/poc/test/integration/.gitkeep +0 -0
- data/poc/test/performance/browsing_test.rb +0 -12
- data/poc/test/test_helper.rb +0 -13
- data/poc/test/unit/.gitkeep +0 -0
- data/poc/test/unit/ar_profile_test.rb +0 -7
- data/poc/vendor/assets/javascripts/.gitkeep +0 -0
- data/poc/vendor/assets/stylesheets/.gitkeep +0 -0
- data/poc/vendor/plugins/.gitkeep +0 -0
data/lib/baleen/message/base.rb
CHANGED
|
@@ -1,55 +1,24 @@
|
|
|
1
|
-
require
|
|
1
|
+
require 'baleen/utils/highlighter'
|
|
2
2
|
|
|
3
3
|
module Baleen
|
|
4
4
|
module Message
|
|
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
|
-
|
|
15
|
-
class Decoder
|
|
16
|
-
include Baleen::Message
|
|
17
|
-
|
|
18
|
-
def initialize(json_string)
|
|
19
|
-
@params = JSON.parse(json_string)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def decode
|
|
23
|
-
klass = @params.delete "klass"
|
|
24
|
-
Object.const_get(klass).new(symbolize_keys(@params))
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
5
|
class Base
|
|
29
6
|
|
|
30
|
-
|
|
7
|
+
include Serializable
|
|
8
|
+
|
|
9
|
+
def initialize()
|
|
31
10
|
@params = {}
|
|
32
11
|
@params[:klass] = self.class.to_s
|
|
33
12
|
end
|
|
34
13
|
|
|
35
|
-
def
|
|
36
|
-
|
|
37
|
-
define_method "#{name}" do
|
|
38
|
-
@params[name.to_sym]
|
|
39
|
-
end
|
|
40
|
-
}
|
|
41
|
-
send(name)
|
|
14
|
+
def results
|
|
15
|
+
nil
|
|
42
16
|
end
|
|
43
17
|
|
|
44
|
-
def
|
|
45
|
-
|
|
18
|
+
def terminate?
|
|
19
|
+
false
|
|
46
20
|
end
|
|
47
21
|
|
|
48
|
-
def to_json
|
|
49
|
-
@params.to_json
|
|
50
|
-
end
|
|
51
22
|
end
|
|
52
|
-
|
|
53
23
|
end
|
|
54
|
-
|
|
55
|
-
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'baleen/utils/highlighter'
|
|
2
|
+
|
|
3
|
+
module Baleen
|
|
4
|
+
module Message
|
|
5
|
+
class Exception < Baleen::Message::Base
|
|
6
|
+
|
|
7
|
+
def initialize(opt)
|
|
8
|
+
super()
|
|
9
|
+
@params[:message] = opt[:message]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def terminate?
|
|
13
|
+
true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def print_message
|
|
17
|
+
hl_error message
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
require "baleen/message/
|
|
2
|
-
require "baleen/message/
|
|
1
|
+
require "baleen/message/base"
|
|
2
|
+
require "baleen/message/to_client"
|
|
3
|
+
require "baleen/message/exception"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'baleen/utils/highlighter'
|
|
2
|
+
|
|
3
|
+
module Baleen
|
|
4
|
+
module Message
|
|
5
|
+
class ToClient < Baleen::Message::Base
|
|
6
|
+
|
|
7
|
+
def initialize(opt)
|
|
8
|
+
super()
|
|
9
|
+
@params[:message] = opt[:message]
|
|
10
|
+
@params[:level] = opt[:level]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def terminate?
|
|
14
|
+
false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def print_message
|
|
18
|
+
case level
|
|
19
|
+
when "info"
|
|
20
|
+
hl_info message
|
|
21
|
+
when "warn"
|
|
22
|
+
hl_warn message
|
|
23
|
+
when "error"
|
|
24
|
+
hl_error message
|
|
25
|
+
else
|
|
26
|
+
hl_error "Unknown message level"
|
|
27
|
+
hl_error inspect
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
module Baleen
|
|
2
|
+
class Project
|
|
3
|
+
|
|
4
|
+
include Default
|
|
5
|
+
|
|
6
|
+
@@projects = {}
|
|
7
|
+
|
|
8
|
+
attr_reader :name, :config
|
|
9
|
+
|
|
10
|
+
def self.projects(name=nil)
|
|
11
|
+
if name
|
|
12
|
+
@@projects[name.to_sym]
|
|
13
|
+
else
|
|
14
|
+
@@projects
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.load_project(config)
|
|
19
|
+
if File.exists?(config)
|
|
20
|
+
yaml = Baleen::Serializable.symbolize_keys(YAML.load_file(config))
|
|
21
|
+
else
|
|
22
|
+
hl_error "Config file not found"
|
|
23
|
+
raise Baleen::Error::ConfigMissing
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
yaml.each do |project, cfg|
|
|
27
|
+
if Baleen::Validation::Validator.check(cfg)
|
|
28
|
+
@@projects[project] = self.new(project, cfg)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.find_project(name, attribute, params={})
|
|
34
|
+
projects = Baleen::Project.projects
|
|
35
|
+
|
|
36
|
+
if name && attribute
|
|
37
|
+
raise "You cannot specify name and attribute at the same time"
|
|
38
|
+
elsif name
|
|
39
|
+
return projects[name.to_sym]
|
|
40
|
+
elsif attribute
|
|
41
|
+
projects.each do |project, attributes|
|
|
42
|
+
attributes.config.each do |attr, values|
|
|
43
|
+
if attr == attribute
|
|
44
|
+
params.each do |_k, _v|
|
|
45
|
+
return nil unless values[_k] == _v
|
|
46
|
+
end
|
|
47
|
+
return projects[project]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.find_project_by_name(name)
|
|
55
|
+
find_project(name.to_sym, nil)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.find_project_by_ci(params)
|
|
59
|
+
find_project(nil, :ci, params)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.find_project_by_runner(params)
|
|
63
|
+
find_project(nil, :runner, params)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def self.find_project_by_framework(params)
|
|
67
|
+
find_project(nil, :framework, params)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def initialize(name, cfg)
|
|
71
|
+
@name = name
|
|
72
|
+
load_config(cfg)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def load_config(cfg)
|
|
76
|
+
if Baleen::Validation::Validator.check(cfg)
|
|
77
|
+
cfg[:runner][:before_command] ||= default_before_command
|
|
78
|
+
cfg[:runner][:concurrency] ||= default_concurrency
|
|
79
|
+
cfg[:runner][:work_dir] ||= default_work_dir
|
|
80
|
+
cfg[:runner][:image]
|
|
81
|
+
|
|
82
|
+
case cfg[:framework][:type]
|
|
83
|
+
when "cucumber"
|
|
84
|
+
cfg[:framework][:files] = cfg[:framework][:features] || default_features
|
|
85
|
+
else
|
|
86
|
+
raise "Passed unknown framework from config yml: #{cfg[:framework][:type]}"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
@config = cfg
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def ci
|
|
93
|
+
@config[:ci]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def image
|
|
97
|
+
@config[:runner][:image]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def branch
|
|
101
|
+
ci[:branch]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def repo
|
|
105
|
+
ci[:repo]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def url
|
|
109
|
+
ci[:url]
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def task
|
|
113
|
+
Baleen::Task::Cucumber.new(
|
|
114
|
+
image: @config[:runner][:image],
|
|
115
|
+
work_dir: @config[:runner][:work_dir],
|
|
116
|
+
files: @config[:framework][:files],
|
|
117
|
+
before_command: @config[:runner][:before_command],
|
|
118
|
+
concurrency: @config[:runner][:concurrency].to_i,
|
|
119
|
+
)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -2,39 +2,47 @@ require "colorize"
|
|
|
2
2
|
|
|
3
3
|
module Baleen
|
|
4
4
|
class ResultDisplay
|
|
5
|
-
def initialize(result, start_time
|
|
6
|
-
@result = result
|
|
5
|
+
def initialize(result, start_time, end_time, output)
|
|
6
|
+
@result = result
|
|
7
7
|
@start_time = start_time
|
|
8
8
|
@end_time = end_time
|
|
9
|
+
@output = output
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def report_result
|
|
13
|
+
if @result
|
|
14
|
+
summary
|
|
15
|
+
detail
|
|
16
|
+
end
|
|
9
17
|
end
|
|
10
18
|
|
|
11
19
|
def summary
|
|
12
|
-
tests_result = pass_all? ? "Pass".
|
|
20
|
+
tests_result = pass_all? ? "Pass".blue : "Fail".red
|
|
13
21
|
time = run_time
|
|
14
22
|
|
|
15
|
-
puts ""
|
|
16
|
-
|
|
17
|
-
puts "Result: ".yellow + tests_result
|
|
18
|
-
puts "Time: ".yellow + time.green
|
|
19
|
-
puts ""
|
|
23
|
+
@output.puts ""
|
|
24
|
+
@output.puts "[Summary]".yellow
|
|
25
|
+
@output.puts "Result: ".yellow + tests_result
|
|
26
|
+
@output.puts "Time: ".yellow + time.green
|
|
27
|
+
@output.puts ""
|
|
20
28
|
end
|
|
21
29
|
|
|
22
30
|
def detail
|
|
23
|
-
|
|
31
|
+
@output.puts "[Details]".yellow
|
|
24
32
|
@result.each do |r|
|
|
25
|
-
puts "Id: ".yellow + "#{r[
|
|
26
|
-
puts "status code: ".yellow + "#{r[
|
|
27
|
-
puts "feature file: ".yellow + "#{r[
|
|
28
|
-
puts "logs:".yellow
|
|
29
|
-
puts "------------------------------------".yellow
|
|
30
|
-
puts "#{r[
|
|
33
|
+
@output.puts "Id: ".yellow + "#{r['container_id']}".green
|
|
34
|
+
@output.puts "status code: ".yellow + "#{r['status_code']}".green
|
|
35
|
+
@output.puts "feature file: ".yellow + "#{r['file']}".green
|
|
36
|
+
@output.puts "logs:".yellow
|
|
37
|
+
@output.puts "------------------------------------".yellow
|
|
38
|
+
@output.puts "#{r['log']}".green
|
|
31
39
|
end
|
|
32
40
|
end
|
|
33
41
|
|
|
34
42
|
private
|
|
35
43
|
|
|
36
44
|
def pass_all?
|
|
37
|
-
@result.all? {|r| r[
|
|
45
|
+
@result.all? {|r| r['status_code'] == 0}
|
|
38
46
|
end
|
|
39
47
|
|
|
40
48
|
def run_time
|
data/lib/baleen/runner.rb
CHANGED
|
@@ -1,124 +1,67 @@
|
|
|
1
1
|
require "baleen/error"
|
|
2
|
+
require 'forwardable'
|
|
2
3
|
|
|
3
4
|
module Baleen
|
|
4
5
|
|
|
5
|
-
class DockerParam
|
|
6
|
-
def initialize(params)
|
|
7
|
-
@params = params
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def method_missing(name, *args)
|
|
11
|
-
DockerParam.class_eval{
|
|
12
|
-
define_method "#{name}" do
|
|
13
|
-
@params[name.to_sym]
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
define_method "#{name}=" do |*args|
|
|
17
|
-
@params[name.to_sym] = args.first
|
|
18
|
-
end
|
|
19
|
-
}
|
|
20
|
-
send(name)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def commands
|
|
24
|
-
%{
|
|
25
|
-
#{@params[:before_command]}
|
|
26
|
-
cd #{@params[:work_dir]}
|
|
27
|
-
#{command}
|
|
28
|
-
}
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def command
|
|
32
|
-
@params[:command] ||= %{#{@params[:exe]} #{@params[:files]}}
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def command=(c)
|
|
36
|
-
@params[:command] = c
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def dup
|
|
40
|
-
copy_params = @params.dup
|
|
41
|
-
Object.const_get(self.class.to_s).new(copy_params)
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
6
|
class RunnerManager
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def initialize(socket, msg)
|
|
51
|
-
@socket = socket
|
|
52
|
-
@queue = []
|
|
53
|
-
@results = []
|
|
54
|
-
@params = DockerParam.new(msg.params)
|
|
7
|
+
def initialize(connection, task)
|
|
8
|
+
@task = task
|
|
9
|
+
@connection = connection
|
|
55
10
|
end
|
|
56
11
|
|
|
57
12
|
def run
|
|
13
|
+
results = []
|
|
14
|
+
prepare_task
|
|
58
15
|
create_runners.each do |runners|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
runner.async.run
|
|
16
|
+
runners.map{|runner| runner.future.run}.each do |actor|
|
|
17
|
+
results << actor.value
|
|
62
18
|
end
|
|
63
|
-
loop {break if monitor_runners}
|
|
64
|
-
@results += @queue.map {|runner| runner.status.params}
|
|
65
19
|
end
|
|
66
|
-
|
|
67
|
-
@
|
|
20
|
+
@task.results = results
|
|
21
|
+
yield @task
|
|
68
22
|
end
|
|
69
23
|
|
|
70
24
|
private
|
|
71
25
|
|
|
72
|
-
def
|
|
73
|
-
|
|
74
|
-
params = @params.dup
|
|
75
|
-
params.files = file
|
|
76
|
-
Runner.new(params)
|
|
77
|
-
}.each_slice(@params.concurrency).map {|r| r}
|
|
26
|
+
def prepare_task
|
|
27
|
+
@task.prepare
|
|
78
28
|
end
|
|
79
29
|
|
|
80
|
-
def
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
30
|
+
def create_runners
|
|
31
|
+
@task.target_files.map {|file|
|
|
32
|
+
task = @task.dup
|
|
33
|
+
task.files = file
|
|
34
|
+
Runner.new(task, @connection)
|
|
35
|
+
}.each_slice(@task.concurrency).map {|r| r}
|
|
86
36
|
end
|
|
87
37
|
|
|
88
|
-
def monitor_runners
|
|
89
|
-
@queue.all?{ |r| r.status }
|
|
90
|
-
end
|
|
91
38
|
end
|
|
92
39
|
|
|
93
40
|
class Runner
|
|
94
|
-
include Celluloid
|
|
41
|
+
include Celluloid
|
|
42
|
+
extend Forwardable
|
|
95
43
|
|
|
96
|
-
|
|
44
|
+
def_delegator :@connection, :notify_info
|
|
97
45
|
|
|
98
|
-
def initialize(
|
|
99
|
-
@
|
|
100
|
-
@
|
|
101
|
-
@
|
|
46
|
+
def initialize(task, connection=nil)
|
|
47
|
+
@container = Docker::Container.create('Cmd' => [task.shell, task.opt, task.commands], 'Image' => task.image)
|
|
48
|
+
@connection = connection ? connection : Connection.new
|
|
49
|
+
@task = task
|
|
102
50
|
end
|
|
103
51
|
|
|
104
52
|
def run
|
|
105
|
-
start_runner do |result|
|
|
106
|
-
@status = Message::Response::RunnerFinish.new(
|
|
107
|
-
status_code: result.status_code,
|
|
108
|
-
container_id: result.container_id,
|
|
109
|
-
log: result.log,
|
|
110
|
-
file: @params.files,
|
|
111
|
-
)
|
|
112
|
-
end
|
|
113
|
-
sleep 0.1 # Stop a moment until RunnerManager checks the status
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def start_runner
|
|
117
53
|
max_retry = 3; count = 0
|
|
118
54
|
|
|
119
55
|
begin
|
|
120
|
-
@
|
|
121
|
-
@
|
|
56
|
+
notify_info("Start container #{@container.id}")
|
|
57
|
+
@container.start
|
|
58
|
+
@container.wait(600) #TODO move to configuration
|
|
59
|
+
notify_info("Finish container #{@container.id}")
|
|
60
|
+
|
|
61
|
+
if @task.commit
|
|
62
|
+
notify_info("Committing the change of container #{@container.id}")
|
|
63
|
+
@container.commit({repo: @task.image}) if @task.commit
|
|
64
|
+
end
|
|
122
65
|
rescue Excon::Errors::NotFound => e
|
|
123
66
|
count += 1
|
|
124
67
|
if count > max_retry
|
|
@@ -127,7 +70,13 @@ module Baleen
|
|
|
127
70
|
retry
|
|
128
71
|
end
|
|
129
72
|
end
|
|
130
|
-
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
status_code: @container.json["State"]["ExitCode"],
|
|
76
|
+
container_id: @container.id,
|
|
77
|
+
log: @container.attach(:stream => false, :stdout => true, :stderr => true, :logs => true),
|
|
78
|
+
file: @task.files,
|
|
79
|
+
}
|
|
131
80
|
end
|
|
132
81
|
|
|
133
82
|
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
module Baleen
|
|
4
|
+
module Serializable
|
|
5
|
+
|
|
6
|
+
def self.deserialize(json_string)
|
|
7
|
+
params = JSON.parse(json_string)
|
|
8
|
+
klass = params.delete "klass"
|
|
9
|
+
Object.const_get(klass).new(symbolize_keys(params))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.symbolize_keys(hash)
|
|
13
|
+
hash.inject({}){|new_hash, key_value|
|
|
14
|
+
key, value = key_value
|
|
15
|
+
value = symbolize_keys(value) if value.is_a?(Hash)
|
|
16
|
+
new_hash[key.to_sym] = value
|
|
17
|
+
new_hash
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Dynamically define getter and setter for keys of @params
|
|
22
|
+
def method_missing(name, *args)
|
|
23
|
+
_name = name.to_s.sub("=", "")
|
|
24
|
+
|
|
25
|
+
if @params.has_key?(_name.to_sym)
|
|
26
|
+
self.class.class_eval{
|
|
27
|
+
define_method "#{_name}" do
|
|
28
|
+
@params[_name.to_sym]
|
|
29
|
+
end
|
|
30
|
+
}
|
|
31
|
+
self.class.class_eval{
|
|
32
|
+
define_method "#{_name}=" do |*args|
|
|
33
|
+
@params[_name.to_sym] = args.first
|
|
34
|
+
end
|
|
35
|
+
}
|
|
36
|
+
if name.to_s[-1, 1] == "="
|
|
37
|
+
send(name, args.first)
|
|
38
|
+
else
|
|
39
|
+
send(name)
|
|
40
|
+
end
|
|
41
|
+
else
|
|
42
|
+
raise NoMethodError.new("undefined method: #{name}", name, args)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def params
|
|
47
|
+
@params
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def to_json
|
|
51
|
+
@params.to_json
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def dup
|
|
55
|
+
copy_params = @params.dup
|
|
56
|
+
Object.const_get(self.class.to_s).new(copy_params)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
data/lib/baleen/server.rb
CHANGED
|
@@ -8,10 +8,13 @@ module Baleen
|
|
|
8
8
|
|
|
9
9
|
class Server
|
|
10
10
|
include Celluloid::IO
|
|
11
|
+
include Default
|
|
12
|
+
|
|
11
13
|
finalizer :shutdown
|
|
12
14
|
|
|
13
|
-
def initialize(docker_host
|
|
15
|
+
def initialize(docker_host, docker_port, port, project_file)
|
|
14
16
|
Docker.url = "http://#{docker_host}:#{docker_port}"
|
|
17
|
+
Baleen::Project.load_project(project_file)
|
|
15
18
|
@server = TCPServer.new("0.0.0.0", port)
|
|
16
19
|
async.run
|
|
17
20
|
end
|
|
@@ -21,7 +24,11 @@ module Baleen
|
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
def shutdown
|
|
24
|
-
|
|
27
|
+
begin
|
|
28
|
+
@server.close
|
|
29
|
+
rescue IOError
|
|
30
|
+
BL.info "Shutting down baleen-server..."
|
|
31
|
+
end
|
|
25
32
|
end
|
|
26
33
|
|
|
27
34
|
def handle_connection(socket)
|
|
@@ -31,36 +38,51 @@ module Baleen
|
|
|
31
38
|
case ex
|
|
32
39
|
when IOError; nil # when trying to close already closed socket
|
|
33
40
|
else
|
|
34
|
-
warn "Unknown exception occured"
|
|
35
41
|
puts ex.inspect
|
|
36
42
|
raise ex
|
|
37
43
|
end
|
|
38
44
|
end
|
|
39
45
|
|
|
40
46
|
def handle_request(socket)
|
|
41
|
-
|
|
47
|
+
json_request = socket.gets
|
|
42
48
|
|
|
43
|
-
if
|
|
49
|
+
if json_request.nil?
|
|
44
50
|
socket.close
|
|
45
51
|
return
|
|
46
52
|
end
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
manager.run
|
|
53
|
+
|
|
54
|
+
conn = Connection.new(socket)
|
|
55
|
+
request = parse_request(json_request)
|
|
56
|
+
|
|
57
|
+
begin
|
|
58
|
+
if request.is_a? Baleen::Task::RunProject
|
|
59
|
+
task = find_project(request.project, conn).task
|
|
55
60
|
else
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
task = request # request itself is a task
|
|
62
|
+
end
|
|
63
|
+
rescue Baleen::Error::ProjectNotFound
|
|
64
|
+
return
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
RunnerManager.new(conn, task).run do |response|
|
|
68
|
+
conn.respond(response)
|
|
58
69
|
end
|
|
59
70
|
end
|
|
60
71
|
|
|
61
|
-
def parse_request(
|
|
62
|
-
|
|
72
|
+
def parse_request(request)
|
|
73
|
+
Serializable.deserialize(request)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def find_project(name, conn)
|
|
77
|
+
project = Baleen::Project.find_project_by_name(name.to_sym)
|
|
78
|
+
|
|
79
|
+
unless project
|
|
80
|
+
conn.notify_exception("No project found: #{name}")
|
|
81
|
+
raise Baleen::Error::ProjectNotFound
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
project
|
|
63
85
|
end
|
|
64
86
|
end
|
|
87
|
+
end
|
|
65
88
|
|
|
66
|
-
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Baleen
|
|
2
|
+
module Task
|
|
3
|
+
class Base
|
|
4
|
+
include Serializable
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
@params = {}
|
|
8
|
+
@params[:klass] = self.class.to_s
|
|
9
|
+
@params[:shell] = nil
|
|
10
|
+
@params[:opt] = nil
|
|
11
|
+
@params[:work_dir] = nil
|
|
12
|
+
@params[:files] = nil
|
|
13
|
+
@params[:exe] = nil
|
|
14
|
+
@params[:concurrency] = nil
|
|
15
|
+
@params[:image] = nil
|
|
16
|
+
@params[:before_command] = nil
|
|
17
|
+
@params[:command] = nil
|
|
18
|
+
@params[:results] = nil
|
|
19
|
+
@params[:status] = nil
|
|
20
|
+
@params[:commit] = nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def commands
|
|
24
|
+
%{
|
|
25
|
+
#{@params[:before_command]}
|
|
26
|
+
cd #{@params[:work_dir]}
|
|
27
|
+
#{command}
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def command
|
|
32
|
+
@params[:command] ||= %{#{@params[:exe]} #{@params[:files]}}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def command=(c)
|
|
36
|
+
@params[:command] = c
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def result
|
|
40
|
+
@params[:results]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def respond
|
|
44
|
+
nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def terminate?
|
|
48
|
+
true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
|