pd-blender 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +10 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +14 -0
- data/README.md +342 -0
- data/Rakefile +21 -0
- data/bin/blend +20 -0
- data/blender.gemspec +36 -0
- data/lib/blender.rb +67 -0
- data/lib/blender/cli.rb +71 -0
- data/lib/blender/configuration.rb +45 -0
- data/lib/blender/discovery.rb +41 -0
- data/lib/blender/drivers/base.rb +40 -0
- data/lib/blender/drivers/compound.rb +29 -0
- data/lib/blender/drivers/ruby.rb +55 -0
- data/lib/blender/drivers/shellout.rb +63 -0
- data/lib/blender/drivers/ssh.rb +93 -0
- data/lib/blender/drivers/ssh_multi.rb +102 -0
- data/lib/blender/event_dispatcher.rb +45 -0
- data/lib/blender/exceptions.rb +26 -0
- data/lib/blender/handlers/base.rb +39 -0
- data/lib/blender/handlers/doc.rb +73 -0
- data/lib/blender/job.rb +73 -0
- data/lib/blender/lock/flock.rb +64 -0
- data/lib/blender/log.rb +24 -0
- data/lib/blender/rspec.rb +68 -0
- data/lib/blender/rspec/stub_registry.rb +45 -0
- data/lib/blender/scheduled_job.rb +66 -0
- data/lib/blender/scheduler.rb +114 -0
- data/lib/blender/scheduler/dsl.rb +160 -0
- data/lib/blender/scheduling_strategies/base.rb +30 -0
- data/lib/blender/scheduling_strategies/default.rb +37 -0
- data/lib/blender/scheduling_strategies/per_host.rb +38 -0
- data/lib/blender/scheduling_strategies/per_task.rb +37 -0
- data/lib/blender/tasks/base.rb +72 -0
- data/lib/blender/tasks/ruby.rb +31 -0
- data/lib/blender/tasks/shell_out.rb +30 -0
- data/lib/blender/tasks/ssh.rb +25 -0
- data/lib/blender/timer.rb +54 -0
- data/lib/blender/utils/refinements.rb +45 -0
- data/lib/blender/utils/thread_pool.rb +54 -0
- data/lib/blender/utils/ui.rb +51 -0
- data/lib/blender/version.rb +20 -0
- data/spec/blender/blender_rspec.rb +31 -0
- data/spec/blender/discovery_spec.rb +16 -0
- data/spec/blender/drivers/ssh_multi_spec.rb +16 -0
- data/spec/blender/drivers/ssh_spec.rb +17 -0
- data/spec/blender/dsl_spec.rb +19 -0
- data/spec/blender/event_dispatcher_spec.rb +17 -0
- data/spec/blender/job_spec.rb +42 -0
- data/spec/blender/lock_spec.rb +129 -0
- data/spec/blender/scheduled_job_spec.rb +30 -0
- data/spec/blender/scheduler_spec.rb +140 -0
- data/spec/blender/scheduling_strategies/default_spec.rb +75 -0
- data/spec/blender/utils/refinements_spec.rb +16 -0
- data/spec/blender/utils/thread_pool_spec.rb +16 -0
- data/spec/blender_spec.rb +37 -0
- data/spec/data/example.rb +12 -0
- data/spec/spec_helper.rb +35 -0
- metadata +304 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Ranjib Dey (<ranjib@pagerduty.com>)
|
3
|
+
# Copyright:: Copyright (c) 2014 PagerDuty, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
require 'highline'
|
19
|
+
|
20
|
+
module Blender
|
21
|
+
module Utils
|
22
|
+
class UI
|
23
|
+
def initialize
|
24
|
+
@mutex = Mutex.new
|
25
|
+
@highline = HighLine.new
|
26
|
+
end
|
27
|
+
def puts(string)
|
28
|
+
@mutex.synchronize do
|
29
|
+
$stdout.puts(string)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def puts_red(string)
|
34
|
+
puts(color(string, :red))
|
35
|
+
end
|
36
|
+
|
37
|
+
def puts_cyan(string)
|
38
|
+
puts(color(string, :cyan))
|
39
|
+
end
|
40
|
+
|
41
|
+
def puts_green(string)
|
42
|
+
puts(color(string, :green))
|
43
|
+
end
|
44
|
+
|
45
|
+
def color(string, *colors)
|
46
|
+
@highline.color(string, *colors)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Ranjib Dey (<ranjib@pagerduty.com>)
|
3
|
+
# Copyright:: Copyright (c) 2014 PagerDuty, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
module Blender
|
19
|
+
VERSION = '0.0.1'
|
20
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Ranjib Dey (<ranjib@pagerduty.com>)
|
3
|
+
# Copyright:: Copyright (c) 2014 PagerDuty, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
require 'blender/rspec'
|
19
|
+
require 'rspec'
|
20
|
+
require 'rspec/mocks'
|
21
|
+
require 'rspec/expectations'
|
22
|
+
require 'blender'
|
23
|
+
|
24
|
+
describe Blender::RSpec do
|
25
|
+
let(:scheduler) do
|
26
|
+
noop_scheduler_from_file(File.expand_path('../../data/example.rb', __FILE__))
|
27
|
+
end
|
28
|
+
it 'should have 3 tasks' do
|
29
|
+
expect(scheduler.tasks.size).to eq(2)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'blender/discovery'
|
3
|
+
describe Blender::Scheduler do
|
4
|
+
|
5
|
+
let(:scheduler) do
|
6
|
+
Blender::Scheduler.new('test')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should return Chef is type :chef is passed' do
|
10
|
+
class Blender::Discovery::Foo;end
|
11
|
+
disco = double(Blender::Discovery::Foo)
|
12
|
+
allow(disco).to receive(:search).with('name:xx').and_return(['a', 'b', 'c'])
|
13
|
+
allow(Blender::Discovery::Foo).to receive(:new).and_return(disco)
|
14
|
+
expect(scheduler.search(:foo, 'name:xx')).to eq(['a', 'b', 'c'])
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Blender::Driver::SshMulti do
|
4
|
+
let(:driver) {described_class.new(events: Object.new, concurrency: 10)}
|
5
|
+
let(:job) do
|
6
|
+
Blender::Job.new(
|
7
|
+
101,
|
8
|
+
nil,
|
9
|
+
%w{h1 h2 h3 h4 h5},
|
10
|
+
Array.new(1){|n| create_task("t#{n}")}
|
11
|
+
)
|
12
|
+
end
|
13
|
+
it '#concurrency' do
|
14
|
+
expect(driver.concurrency).to eq(10)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Blender::Driver::Ssh do
|
4
|
+
let(:hosts) {['h1']}
|
5
|
+
let(:tasks){ Array.new(3){|n| create_task("t#{n}")}}
|
6
|
+
let(:driver) {described_class.new(events: Object.new)}
|
7
|
+
it 'should execute commands over net ssh channel' do
|
8
|
+
channel = double('channel').as_null_object
|
9
|
+
session = double('session', open_channel: channel, loop: true)
|
10
|
+
expect(Net::SSH).to receive(:start).with(
|
11
|
+
'h1',
|
12
|
+
ENV['USER'],
|
13
|
+
{}
|
14
|
+
).and_return(session)
|
15
|
+
driver.execute(tasks, hosts)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '#dsl' do
|
4
|
+
let(:scheduler) do
|
5
|
+
sched = Blender::Scheduler.new('test')
|
6
|
+
sched.instance_eval do
|
7
|
+
ssh_task 'run' do
|
8
|
+
execute 'sudo /usr/local/sbin/chef-client-cron'
|
9
|
+
members ['a']
|
10
|
+
end
|
11
|
+
end
|
12
|
+
sched
|
13
|
+
end
|
14
|
+
|
15
|
+
it '#check DSL' do
|
16
|
+
allow_any_instance_of(Blender::Driver::Ssh).to receive(:execute)
|
17
|
+
scheduler.run
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Blender::EventDispatcher do
|
4
|
+
let(:dispatcher) do
|
5
|
+
described_class.new
|
6
|
+
end
|
7
|
+
subject(:handler){ Object.new}
|
8
|
+
it '#register' do
|
9
|
+
dispatcher.register(handler)
|
10
|
+
expect(dispatcher.handlers).to include(handler)
|
11
|
+
end
|
12
|
+
it 'should forward all methods to the registered handlers' do
|
13
|
+
dispatcher.register(handler)
|
14
|
+
expect(handler).to receive(:run_started)
|
15
|
+
dispatcher.run_started
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Blender::Job do
|
4
|
+
let(:driver) do
|
5
|
+
Object.new
|
6
|
+
end
|
7
|
+
it '#should use default driver if no tasks are given' do
|
8
|
+
job = Blender::Job.new(1, driver , [] ,[])
|
9
|
+
expect(job.driver).to eq(driver)
|
10
|
+
end
|
11
|
+
describe '#name' do
|
12
|
+
it 'with one host, one task' do
|
13
|
+
t1 = create_task('t1', driver)
|
14
|
+
job = Blender::Job.new(1, Object.new, [t1], ['a'])
|
15
|
+
expect(job.name).to eq('t1 on a')
|
16
|
+
end
|
17
|
+
it 'with one host, many tasks' do
|
18
|
+
t1 = create_task('t1', driver)
|
19
|
+
t2 = create_task('t2', driver)
|
20
|
+
job = Blender::Job.new(1, Object.new,[t1, t2], ['a'])
|
21
|
+
expect(job.name).to eq('2 tasks on a')
|
22
|
+
end
|
23
|
+
it 'with 0 hosts, many tasks' do
|
24
|
+
t1 = create_task('t1', driver)
|
25
|
+
t2 = create_task('t2', driver)
|
26
|
+
t3 = create_task('t3', driver)
|
27
|
+
job = Blender::Job.new(1, Object.new, [t1, t2, t3], [])
|
28
|
+
expect(job.name).to eq('3 tasks on 0 members')
|
29
|
+
end
|
30
|
+
it 'with many hosts, many tasks' do
|
31
|
+
t1 = create_task('t1', driver)
|
32
|
+
t2 = create_task('t2', driver)
|
33
|
+
job = Blender::Job.new(1, Object.new, [t1, t2], ['a', 'b', 'c'])
|
34
|
+
expect(job.name).to eq('2 tasks on 3 members')
|
35
|
+
end
|
36
|
+
it 'with many hosts one task' do
|
37
|
+
t1 = create_task('t1', driver)
|
38
|
+
job = Blender::Job.new(1, Object.new, [t1], ['a', 'b', 'c'])
|
39
|
+
expect(job.name).to eq('t1 on 3 members')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Blender::Lock do
|
4
|
+
|
5
|
+
it 'should not allow two blender run with same name to run at the same time' do
|
6
|
+
|
7
|
+
pid1 = fork do
|
8
|
+
Blender.blend('test-1') do |sched|
|
9
|
+
sched.members(['localhost'])
|
10
|
+
sched.ruby_task('date') do
|
11
|
+
execute do
|
12
|
+
sleep 5
|
13
|
+
puts 'This will succeed'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
pid2 = fork do
|
20
|
+
STDERR.reopen(File::NULL)
|
21
|
+
Blender.blend('test-1') do |sched|
|
22
|
+
sched.members(['localhost'])
|
23
|
+
sched.ruby_task('date') do
|
24
|
+
execute do
|
25
|
+
puts 'This will fail'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
status1 = Process.wait2 pid1
|
31
|
+
status2 = Process.wait2 pid2
|
32
|
+
expect(status1.last.exitstatus).to eq(0)
|
33
|
+
expect(status2.last.exitstatus).to_not eq(0)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should allow two blender run with different name to run at the same time' do
|
37
|
+
pid1 = fork do
|
38
|
+
Blender.blend('test-1') do |sched|
|
39
|
+
sched.members(['localhost'])
|
40
|
+
sched.ruby_task('date') do
|
41
|
+
execute do
|
42
|
+
sleep 5
|
43
|
+
puts 'This will succeed'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
pid2 = fork do
|
50
|
+
Blender.blend('test-2') do |sched|
|
51
|
+
sched.members(['localhost'])
|
52
|
+
sched.ruby_task('date') do
|
53
|
+
execute do
|
54
|
+
puts 'This will succeed'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
status1 = Process.wait2 pid1
|
60
|
+
status2 = Process.wait2 pid2
|
61
|
+
expect(status1.last.exitstatus).to eq(0)
|
62
|
+
expect(status2.last.exitstatus).to eq(0)
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'File based locking with timeout' do
|
66
|
+
|
67
|
+
it 'should raise lock acquisition error when times out' do
|
68
|
+
pid1 = fork do
|
69
|
+
Blender.blend('test-1') do |sched|
|
70
|
+
sched.members(['localhost'])
|
71
|
+
sched.ruby_task('date') do
|
72
|
+
execute do
|
73
|
+
sleep 5
|
74
|
+
puts 'This will succeed'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
pid2 = fork do
|
81
|
+
STDERR.reopen(File::NULL)
|
82
|
+
Blender.blend('test-1') do |sched|
|
83
|
+
sched.members(['localhost'])
|
84
|
+
sched.lock_options('flock', timeout: 3)
|
85
|
+
sched.ruby_task('date') do
|
86
|
+
execute do
|
87
|
+
puts 'This will fail'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
status1 = Process.wait2 pid1
|
93
|
+
status2 = Process.wait2 pid2
|
94
|
+
expect(status1.last.exitstatus).to eq(0)
|
95
|
+
expect(status2.last.exitstatus).to_not eq(0)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should not raise lock acquisition error when able to acquire lock within timeout period' do
|
99
|
+
pid1 = fork do
|
100
|
+
Blender.blend('test-1') do |sched|
|
101
|
+
sched.members(['localhost'])
|
102
|
+
sched.ruby_task('date') do
|
103
|
+
execute do
|
104
|
+
sleep 5
|
105
|
+
puts 'This will succeed'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
pid2 = fork do
|
112
|
+
STDERR.reopen(File::NULL)
|
113
|
+
Blender.blend('test-1') do |sched|
|
114
|
+
sched.members(['localhost'])
|
115
|
+
sched.lock_options('flock', timeout: 3)
|
116
|
+
sched.ruby_task('date') do
|
117
|
+
execute do
|
118
|
+
puts 'This will fail'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
status1 = Process.wait2 pid1
|
124
|
+
status2 = Process.wait2 pid2
|
125
|
+
expect(status1.last.exitstatus).to eq(0)
|
126
|
+
expect(status2.last.exitstatus).to_not eq(0)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'blender/scheduled_job'
|
3
|
+
|
4
|
+
describe Blender::ScheduledJob do
|
5
|
+
let(:scheduled_job) do
|
6
|
+
Blender::ScheduledJob.new('test job')
|
7
|
+
end
|
8
|
+
it '#blender_file' do
|
9
|
+
scheduled_job.blender_file('test.rb')
|
10
|
+
expect(scheduled_job.file).to eq('test.rb')
|
11
|
+
end
|
12
|
+
it '#cron' do
|
13
|
+
time = '*/4 * * * *'
|
14
|
+
scheduled_job.cron(time)
|
15
|
+
expect(scheduled_job.schedule).to eq([:cron, time])
|
16
|
+
end
|
17
|
+
it '#every' do
|
18
|
+
scheduled_job.every(15)
|
19
|
+
expect(scheduled_job.schedule).to eq([:every, 15])
|
20
|
+
end
|
21
|
+
it '#run' do
|
22
|
+
scheduled_job.blender_file('test.rb')
|
23
|
+
scheduled_job.every(15)
|
24
|
+
sched = double(Blender::Scheduler)
|
25
|
+
expect(sched).to receive(:task).with('x')
|
26
|
+
expect(File).to receive(:read).with('test.rb').and_return('task "x"')
|
27
|
+
expect(Blender).to receive(:blend).with('test.rb').and_yield(sched)
|
28
|
+
scheduled_job.run
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Blender::Scheduler do
|
4
|
+
let(:scheduler) do
|
5
|
+
described_class.new('test')
|
6
|
+
end
|
7
|
+
describe '#DSL' do
|
8
|
+
subject(:task){scheduler.tasks.first}
|
9
|
+
it '#ask' do
|
10
|
+
tui = double(HighLine)
|
11
|
+
allow(HighLine).to receive(:new).and_return(tui)
|
12
|
+
expect(tui).to receive(:ask).with('foo')
|
13
|
+
scheduler.ask('foo')
|
14
|
+
end
|
15
|
+
it '#register_handler' do
|
16
|
+
handler = Object.new
|
17
|
+
scheduler.register_handler(handler)
|
18
|
+
expect(scheduler.events.handlers).to include(handler)
|
19
|
+
end
|
20
|
+
describe '#task' do
|
21
|
+
before do
|
22
|
+
scheduler.task('whoa')
|
23
|
+
end
|
24
|
+
it 'should belong to base class' do
|
25
|
+
expect(task).to be_kind_of(Blender::Task::Base)
|
26
|
+
end
|
27
|
+
it 'should use shellout driver' do
|
28
|
+
expect(task.driver).to be_kind_of(Blender::Driver::ShellOut)
|
29
|
+
end
|
30
|
+
it 'should contain only one task' do
|
31
|
+
expect(scheduler.tasks.size).to eq(1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
describe '#ssh_task' do
|
35
|
+
before do
|
36
|
+
scheduler.ssh_task('test') do
|
37
|
+
members ['a']
|
38
|
+
execute('ls -l')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
it 'should have correct hosts list' do
|
42
|
+
expect(task.hosts).to eq(['a'])
|
43
|
+
end
|
44
|
+
it 'should have correct command' do
|
45
|
+
expect(task.command).to eq('ls -l')
|
46
|
+
end
|
47
|
+
it 'should use ssh task subclass' do
|
48
|
+
expect(task).to be_kind_of(Blender::Task::Ssh)
|
49
|
+
end
|
50
|
+
it 'should use the ssh driver' do
|
51
|
+
expect(task.driver).to be_kind_of(Blender::Driver::Ssh)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
describe '#on' do
|
55
|
+
it 'should invoke custom block on specific events' do
|
56
|
+
test = 1
|
57
|
+
Blender.blend('do it') do |sched|
|
58
|
+
sched.on :run_finished do |x|
|
59
|
+
test = 2
|
60
|
+
end
|
61
|
+
sched.task 'ls -alh'
|
62
|
+
end
|
63
|
+
expect(test).to eq(2)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
describe '#ruby_task' do
|
67
|
+
before do
|
68
|
+
scheduler.ruby_task('test') do |t|
|
69
|
+
t.members ['c']
|
70
|
+
t.execute do
|
71
|
+
raise 'Fail'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
it 'should setup correct hosts' do
|
76
|
+
expect(task.hosts).to eq(['c'])
|
77
|
+
end
|
78
|
+
it 'should use the ruby task subclass' do
|
79
|
+
expect(task).to be_kind_of(Blender::Task::Base)
|
80
|
+
end
|
81
|
+
it 'should assign the proc as command' do
|
82
|
+
expect(task.command).to be_kind_of(Proc)
|
83
|
+
end
|
84
|
+
it 'should the ruby driver subclass' do
|
85
|
+
expect(task.driver).to be_kind_of(Blender::Driver::Ruby)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
describe '#strategy' do
|
89
|
+
it '#should raise error for non-existent strategy' do
|
90
|
+
expect do
|
91
|
+
scheduler.strategy(:foo)
|
92
|
+
end.to raise_error(Blender::UnknownSchedulingStrategy)
|
93
|
+
end
|
94
|
+
it '#get default' do
|
95
|
+
expect(scheduler.strategy(:default)).to be_kind_of(Blender::SchedulingStrategy::Default)
|
96
|
+
end
|
97
|
+
it '#get per_host' do
|
98
|
+
expect(scheduler.strategy(:per_host)).to be_kind_of(Blender::SchedulingStrategy::PerHost)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
it '#concurrency' do
|
102
|
+
scheduler.concurrency(112)
|
103
|
+
expect(scheduler.metadata[:concurrency]).to be(112)
|
104
|
+
end
|
105
|
+
it '#ignore_failure' do
|
106
|
+
scheduler.ignore_failure true
|
107
|
+
expect(scheduler.metadata[:ignore_failure]).to be(true)
|
108
|
+
end
|
109
|
+
it '#members' do
|
110
|
+
scheduler.members(['a', 'b'])
|
111
|
+
expect(scheduler.metadata[:members]).to eq(['a', 'b'])
|
112
|
+
end
|
113
|
+
it '#driver' do
|
114
|
+
d = scheduler.driver(:ssh, foo: :bar)
|
115
|
+
expect(d).to be_kind_of(Blender::Driver::Ssh)
|
116
|
+
expect(d.config[:foo]).to be(:bar)
|
117
|
+
end
|
118
|
+
it 'should have no tasks' do
|
119
|
+
expect(scheduler.tasks).to be_empty
|
120
|
+
end
|
121
|
+
it 'should have no hosts' do
|
122
|
+
expect(scheduler.metadata[:members]).to be_empty
|
123
|
+
end
|
124
|
+
describe '#run' do
|
125
|
+
it 'should use serial_run when concurrency is not set' do
|
126
|
+
expect(scheduler).to receive(:serial_run)
|
127
|
+
scheduler.task 'echo HelloWorld'
|
128
|
+
scheduler.run
|
129
|
+
end
|
130
|
+
it 'should use concurrent_run when concurrency is used' do
|
131
|
+
expect(scheduler).to receive(:concurrent_run)
|
132
|
+
scheduler.task 'echo HelloWorld1'
|
133
|
+
scheduler.task 'echo HelloWorld2'
|
134
|
+
scheduler.task 'echo HelloWorld3'
|
135
|
+
scheduler.concurrency(2)
|
136
|
+
scheduler.run
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|