vx-worker 0.2.0.pre28
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +3 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +276 -0
- data/Rakefile +27 -0
- data/bin/vx-worker +6 -0
- data/docker/Dockerfile +15 -0
- data/docker/bootstrap.sh +106 -0
- data/docker/sv-enable +26 -0
- data/docker/sv-gen +50 -0
- data/lib/vx/worker/cli.rb +55 -0
- data/lib/vx/worker/configuration.rb +62 -0
- data/lib/vx/worker/consumers/job_logs_consumer.rb +13 -0
- data/lib/vx/worker/consumers/job_status_consumer.rb +13 -0
- data/lib/vx/worker/consumers/jobs_consumer.rb +28 -0
- data/lib/vx/worker/docker.rb +32 -0
- data/lib/vx/worker/ext/string.rb +10 -0
- data/lib/vx/worker/helper/config.rb +11 -0
- data/lib/vx/worker/helper/logger.rb +11 -0
- data/lib/vx/worker/initializers/amqp.rb +3 -0
- data/lib/vx/worker/job.rb +49 -0
- data/lib/vx/worker/local.rb +32 -0
- data/lib/vx/worker/middlewares/log_job.rb +19 -0
- data/lib/vx/worker/middlewares/run_script.rb +84 -0
- data/lib/vx/worker/middlewares/start_connector.rb +32 -0
- data/lib/vx/worker/middlewares/timeout.rb +22 -0
- data/lib/vx/worker/middlewares/update_job_status.rb +69 -0
- data/lib/vx/worker/version.rb +5 -0
- data/lib/vx/worker.rb +83 -0
- data/spec/lib/worker/configuration_spec.rb +40 -0
- data/spec/lib/worker/docker_spec.rb +28 -0
- data/spec/lib/worker/job_spec.rb +104 -0
- data/spec/lib/worker/local_spec.rb +29 -0
- data/spec/lib/worker/middlewares/log_job_spec.rb +15 -0
- data/spec/lib/worker/middlewares/run_script_spec.rb +63 -0
- data/spec/lib/worker/middlewares/start_connector_spec.rb +34 -0
- data/spec/lib/worker/middlewares/timeout_spec.rb +28 -0
- data/spec/lib/worker/middlewares/update_job_status_spec.rb +75 -0
- data/spec/lib/worker_spec.rb +39 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/all_job_log_output.rb +3 -0
- data/spec/support/create.rb +19 -0
- data/spec/support/last_job_logs_message.rb +3 -0
- data/spec/support/shared_examples/update_job_status_message_spec.rb +6 -0
- data/vx-worker.gemspec +31 -0
- metadata +231 -0
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vx::Worker::Job do
|
4
|
+
let(:message) { create :message, 'PerformJob' }
|
5
|
+
let(:job) { described_class.new message }
|
6
|
+
|
7
|
+
subject { job }
|
8
|
+
|
9
|
+
context "just created" do
|
10
|
+
its(:message) { should eq message }
|
11
|
+
its(:output) { should be_an_instance_of(Vx::Common::OutputBuffer) }
|
12
|
+
its(:output_counter) { should eq 0 }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "publish_job_log_message" do
|
16
|
+
let(:data) { 'log' }
|
17
|
+
subject { job.publish_job_log_message data }
|
18
|
+
|
19
|
+
it { should be_an_instance_of(Vx::Message::JobLog) }
|
20
|
+
its(:job_id) { should eq job.message.job_id }
|
21
|
+
its(:build_id) { should eq job.message.id }
|
22
|
+
its(:tm) { should eq 1 }
|
23
|
+
its(:log) { should eq data }
|
24
|
+
|
25
|
+
it "should increment counter" do
|
26
|
+
expect {
|
27
|
+
subject
|
28
|
+
}.to change(job, :output_counter).by(1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "add_to_output" do
|
33
|
+
let(:data) { 'data' }
|
34
|
+
let(:messages) { Vx::Worker::JobLogsConsumer.messages }
|
35
|
+
subject do
|
36
|
+
job.add_to_output(data)
|
37
|
+
job.output.flush
|
38
|
+
job
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should delivery message" do
|
42
|
+
expect {
|
43
|
+
subject
|
44
|
+
}.to change(messages, :size).by(1)
|
45
|
+
expect(messages.first.log).to eq data
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should increment output_counter" do
|
49
|
+
expect {
|
50
|
+
subject
|
51
|
+
}.to change(job, :output_counter).by(1)
|
52
|
+
expect(messages.first.tm).to eq 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "add_command_to_output" do
|
57
|
+
let(:data) { 'data' }
|
58
|
+
let(:messages) { Vx::Worker::JobLogsConsumer.messages }
|
59
|
+
subject do
|
60
|
+
job.add_command_to_output(data)
|
61
|
+
job.output.flush
|
62
|
+
job
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should delivery message" do
|
66
|
+
expect {
|
67
|
+
subject
|
68
|
+
}.to change(messages, :size).by(1)
|
69
|
+
expect(messages.first.log).to eq "$ #{data}\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should increment output_counter" do
|
73
|
+
expect {
|
74
|
+
subject
|
75
|
+
}.to change(job, :output_counter).by(1)
|
76
|
+
expect(messages.first.tm).to eq 1
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "add_trace_to_output" do
|
81
|
+
let(:data) { 'data' }
|
82
|
+
let(:messages) { Vx::Worker::JobLogsConsumer.messages }
|
83
|
+
subject do
|
84
|
+
job.add_trace_to_output(data)
|
85
|
+
job.output.flush
|
86
|
+
job
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should delivery message" do
|
90
|
+
expect {
|
91
|
+
subject
|
92
|
+
}.to change(messages, :size).by(1)
|
93
|
+
expect(messages.first.log).to eq " ===> #{data}\n"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should increment output_counter" do
|
97
|
+
expect {
|
98
|
+
subject
|
99
|
+
}.to change(job, :output_counter).by(1)
|
100
|
+
expect(messages.first.tm).to eq 1
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vx::Worker::Local do
|
4
|
+
let(:options) { { } }
|
5
|
+
let(:job) { create :job, options }
|
6
|
+
let(:local) { described_class.new job, nil }
|
7
|
+
subject { local }
|
8
|
+
|
9
|
+
context "perform" do
|
10
|
+
subject { local.perform }
|
11
|
+
|
12
|
+
before do
|
13
|
+
Vx::Worker.config.run = "local"
|
14
|
+
end
|
15
|
+
|
16
|
+
it { should eq 0 }
|
17
|
+
|
18
|
+
context "when fail before_script" do
|
19
|
+
let(:options) { { before_script: "/bin/false" } }
|
20
|
+
it { should eq(-1) }
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when fail script" do
|
24
|
+
let(:options) { { script: "/bin/false" } }
|
25
|
+
it { should satisfy { |n| [1,127].include?(n) } }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vx::Worker::LogJob do
|
4
|
+
let(:exit_code) { 0 }
|
5
|
+
let(:app) { ->(_) { exit_code } }
|
6
|
+
let(:job) { create :job }
|
7
|
+
let(:env) { OpenStruct.new job: job }
|
8
|
+
let(:mid) { described_class.new app }
|
9
|
+
|
10
|
+
subject { mid.call env }
|
11
|
+
|
12
|
+
it { should eq 0 }
|
13
|
+
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vx::Worker::RunScript do
|
4
|
+
let(:exit_code) { 0 }
|
5
|
+
let(:app) { ->(_) { exit_code } }
|
6
|
+
let(:script) { "echo script" }
|
7
|
+
let(:before_script) { "echo before_script" }
|
8
|
+
let(:after_script) { "echo after_script" }
|
9
|
+
let(:job) { create :job,
|
10
|
+
script: script,
|
11
|
+
before_script: before_script,
|
12
|
+
after_script: after_script }
|
13
|
+
let(:env) { OpenStruct.new job: job }
|
14
|
+
let(:mid) { described_class.new app }
|
15
|
+
let(:connector_mid) { Vx::Worker::StartConnector.new(mid) }
|
16
|
+
|
17
|
+
subject { connector_mid.call env }
|
18
|
+
|
19
|
+
shared_examples "run script" do
|
20
|
+
|
21
|
+
it "should be" do
|
22
|
+
expect(subject).to eq 0
|
23
|
+
job.release
|
24
|
+
expect(all_job_log_output).to match("script")
|
25
|
+
expect(all_job_log_output).to match("after_script")
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when script failed" do
|
29
|
+
let(:script) { "false" }
|
30
|
+
it "should be" do
|
31
|
+
expect(subject).to eq(1)
|
32
|
+
job.release
|
33
|
+
expect(all_job_log_output).to match("after_script")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when before_script failed" do
|
38
|
+
let(:before_script) { "false" }
|
39
|
+
it "should be" do
|
40
|
+
expect(subject).to eq(-1)
|
41
|
+
job.release
|
42
|
+
expect(all_job_log_output).to match("after_script")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "local connector" do
|
48
|
+
before do
|
49
|
+
Vx::Worker.config.run = "local"
|
50
|
+
end
|
51
|
+
|
52
|
+
it_should_behave_like "run script"
|
53
|
+
end
|
54
|
+
|
55
|
+
context "local connector", docker: true do
|
56
|
+
before do
|
57
|
+
Vx::Worker.config.run = "docker"
|
58
|
+
end
|
59
|
+
|
60
|
+
it_should_behave_like "run script"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vx::Worker::StartConnector do
|
4
|
+
let(:exit_code) { 0 }
|
5
|
+
let(:app) { ->(_) { exit_code } }
|
6
|
+
let(:job) { create :job }
|
7
|
+
let(:env) { OpenStruct.new job: job }
|
8
|
+
let(:mid) { described_class.new app }
|
9
|
+
|
10
|
+
subject { mid.call env }
|
11
|
+
|
12
|
+
context "local connector" do
|
13
|
+
before do
|
14
|
+
Vx::Worker.config.run = "local"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should successfully start" do
|
18
|
+
expect(subject).to eq 0
|
19
|
+
expect(env.connector).to be
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "docker connector", docker: true do
|
24
|
+
before do
|
25
|
+
Vx::Worker.config.run = "docker"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should successfully start" do
|
29
|
+
expect(subject).to eq 0
|
30
|
+
expect(env.connector).to be
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vx::Worker::Timeout do
|
4
|
+
let(:exit_code) { 0 }
|
5
|
+
let(:app) { ->(_) { exit_code } }
|
6
|
+
let(:env) { OpenStruct.new }
|
7
|
+
let(:mid) { described_class.new app }
|
8
|
+
|
9
|
+
subject { mid.call env }
|
10
|
+
|
11
|
+
it { should eq 0 }
|
12
|
+
|
13
|
+
context "when timeout happened" do
|
14
|
+
let(:app) { ->(_) { sleep 1 ; exit_code } }
|
15
|
+
|
16
|
+
before do
|
17
|
+
mock(mid)._timeout { 0.1 }
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should raise" do
|
21
|
+
expect {
|
22
|
+
subject
|
23
|
+
}.to raise_error(Timeout::Error)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vx::Worker::UpdateJobStatus do
|
4
|
+
let(:exit_code) { 0 }
|
5
|
+
let(:app) { ->(_) { exit_code } }
|
6
|
+
let(:job) { create :job }
|
7
|
+
let(:env) { OpenStruct.new job: job }
|
8
|
+
let(:mid) { described_class.new app }
|
9
|
+
let(:messages) { Vx::Worker::JobStatusConsumer.messages }
|
10
|
+
|
11
|
+
subject { mid.call env }
|
12
|
+
|
13
|
+
it "should delivery 2 messages" do
|
14
|
+
expect {
|
15
|
+
subject
|
16
|
+
}.to change(messages, :size).by(2)
|
17
|
+
end
|
18
|
+
|
19
|
+
{ 0 => 3, 1 => 4, -1 => 5 }.each do |code, status|
|
20
|
+
context "when exit code is #{code}" do
|
21
|
+
let(:exit_code) { code }
|
22
|
+
it { should eq code }
|
23
|
+
|
24
|
+
context "messages" do
|
25
|
+
before { mid.call env }
|
26
|
+
|
27
|
+
context "first" do
|
28
|
+
subject { messages.first }
|
29
|
+
it_should_behave_like "UpdateJobStatus message" do
|
30
|
+
its(:status) { should eq 2 }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "last" do
|
35
|
+
subject { messages.last }
|
36
|
+
it_should_behave_like "UpdateJobStatus message" do
|
37
|
+
its(:status) { should eq status }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when raise exception" do
|
46
|
+
let(:app) { ->(_) { raise "Ignore Me" } }
|
47
|
+
it { should eq(-1) }
|
48
|
+
|
49
|
+
context "messages" do
|
50
|
+
before { mid.call env }
|
51
|
+
|
52
|
+
context "first" do
|
53
|
+
subject { messages.first }
|
54
|
+
it_should_behave_like "UpdateJobStatus message" do
|
55
|
+
its(:status) { should eq 2 }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "last" do
|
60
|
+
subject { messages.last }
|
61
|
+
it_should_behave_like "UpdateJobStatus message" do
|
62
|
+
its(:status) { should eq 5 }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "Timeout::Error" do
|
68
|
+
let(:app) { ->(_) { raise Timeout::Error.new("Timeout Ignore Me") } }
|
69
|
+
|
70
|
+
it { should eq(-1) }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vx::Worker do
|
4
|
+
|
5
|
+
context ".perform" do
|
6
|
+
let(:job) { create :job }
|
7
|
+
let(:run) { :docker }
|
8
|
+
subject { described_class.perform job, '/tmp' }
|
9
|
+
|
10
|
+
before do
|
11
|
+
described_class.configure do |c|
|
12
|
+
c.run = run
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when run at :docker" do
|
17
|
+
let(:run) { :docker }
|
18
|
+
let(:docker) { 'docker' }
|
19
|
+
before do
|
20
|
+
mock(Vx::Worker::Docker).new(job, '/tmp') { docker }
|
21
|
+
mock(docker).perform { true }
|
22
|
+
end
|
23
|
+
|
24
|
+
it { should be }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when run at :local" do
|
28
|
+
let(:run) { :local }
|
29
|
+
let(:local) { 'local' }
|
30
|
+
before do
|
31
|
+
mock(Vx::Worker::Local).new(job, '/tmp') { local }
|
32
|
+
mock(local).perform { true }
|
33
|
+
end
|
34
|
+
|
35
|
+
it { should be }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path '../../lib/vx/worker', __FILE__
|
2
|
+
|
3
|
+
Bundler.require(:test)
|
4
|
+
require 'rspec/autorun'
|
5
|
+
require 'vx/common/amqp/testing'
|
6
|
+
require 'vx/message/testing'
|
7
|
+
|
8
|
+
Dir[File.expand_path("../..", __FILE__) + "/spec/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.mock_with :rr
|
12
|
+
|
13
|
+
config.before(:each) do
|
14
|
+
Vx::Common::AMQP::Testing.clear
|
15
|
+
Vx::Worker.reset_config!
|
16
|
+
|
17
|
+
Vx::Worker.configure do |c|
|
18
|
+
=begin
|
19
|
+
c.docker.ssh.port = 2223
|
20
|
+
c.docker.ssh.host = 'localhost'
|
21
|
+
c.docker.create_options = {
|
22
|
+
'PortSpecs' => ['2022:22']
|
23
|
+
}
|
24
|
+
=end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
def create(who, *args)
|
4
|
+
|
5
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
6
|
+
|
7
|
+
case who
|
8
|
+
|
9
|
+
when :message
|
10
|
+
name = args.shift
|
11
|
+
klass = Vx::Message.const_get name
|
12
|
+
klass.test_message options
|
13
|
+
|
14
|
+
when :job
|
15
|
+
message = options[:message] || create(:message, 'PerformJob', options)
|
16
|
+
Vx::Worker::Job.new message
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/vx-worker.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require File.expand_path('../lib/vx/worker/version.rb', __FILE__)
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "vx-worker"
|
8
|
+
spec.version = Vx::Worker::VERSION
|
9
|
+
spec.authors = ["Dmitry Galinsky"]
|
10
|
+
spec.email = ["dima.exe@gmail.com"]
|
11
|
+
spec.description = %q{ ci worker }
|
12
|
+
spec.summary = %q{ ci worker }
|
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_runtime_dependency 'vx-common', "= #{Vx::Worker::VERSION}"
|
22
|
+
spec.add_runtime_dependency 'vx-message', "= #{Vx::Worker::VERSION}"
|
23
|
+
spec.add_runtime_dependency 'vx-container_connector', "= #{Vx::Worker::VERSION}"
|
24
|
+
spec.add_runtime_dependency 'vx-common-amqp', '~> 0.2.5'
|
25
|
+
spec.add_runtime_dependency 'hashr', '= 0.0.22'
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
spec.add_development_dependency "rspec"
|
30
|
+
spec.add_development_dependency "rr"
|
31
|
+
end
|