screwcap 0.3.5 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +7 -5
- data/README.rdoc +13 -0
- data/Rakefile +1 -1
- data/bin/screwcap +24 -9
- data/lib/screwcap.rb +2 -2
- data/lib/screwcap/base.rb +4 -0
- data/lib/screwcap/message_logger.rb +1 -1
- data/lib/screwcap/runner.rb +68 -75
- data/lib/screwcap/sequence.rb +0 -10
- data/lib/screwcap/server.rb +9 -7
- data/lib/screwcap/task.rb +48 -43
- data/lib/screwcap/{deployer.rb → task_manager.rb} +55 -46
- data/recipes/setup_rails.rb +3 -3
- data/runrdoc +1 -0
- data/screwcap.gemspec +1 -1
- data/spec/runner_spec.rb +51 -0
- data/spec/sequence_spec.rb +2 -16
- data/spec/server_spec.rb +0 -9
- data/spec/task_manager_spec.rb +100 -0
- data/spec/task_spec.rb +123 -60
- data/test/config/bad_use.rb +1 -0
- data/test/config/expect.rb +5 -0
- data/test/config/simple_recipe.rb +0 -6
- data/test/config/super_simple_recipe.rb +11 -0
- data/test/config/use.rb +1 -1
- data/test/config/use2.rb +1 -0
- metadata +10 -9
- data/Gemfile +0 -14
- data/Gemfile.lock +0 -49
- data/spec/command_set_spec.rb +0 -57
- data/spec/deployer_spec.rb +0 -78
@@ -1,12 +1,11 @@
|
|
1
|
-
# The
|
1
|
+
# The task manager is the class that holds the overall params from the screwcap tasks file, and it is also in charge of running the requested task.
|
2
2
|
#
|
3
|
-
# The
|
4
|
-
class
|
3
|
+
# The task manager can be thought of as the "global scope" of your tasks file.
|
4
|
+
class TaskManager < Screwcap::Base
|
5
5
|
include MessageLogger
|
6
6
|
|
7
|
-
# create a new
|
7
|
+
# create a new task manager.
|
8
8
|
def initialize(opts = {})
|
9
|
-
opts = {:recipe_file => File.expand_path("./config/recipe.rb")}.merge opts
|
10
9
|
super
|
11
10
|
self.__options = opts
|
12
11
|
self.__tasks = []
|
@@ -14,15 +13,7 @@ class Deployer < Screwcap::Base
|
|
14
13
|
self.__command_sets = []
|
15
14
|
self.__sequences = []
|
16
15
|
|
17
|
-
|
18
|
-
opts.each_key {|k| self.delete_field(k) }
|
19
|
-
|
20
|
-
Deployer.log "Reading #{self.__options[:recipe_file]}\n" unless self.__options[:silent] == true
|
21
|
-
|
22
|
-
file = File.open(self.__options[:recipe_file])
|
23
|
-
data = file.read
|
24
|
-
|
25
|
-
instance_eval(data)
|
16
|
+
instance_eval(File.read(self.__options[:recipe_file])) if self.__options[:recipe_file]
|
26
17
|
end
|
27
18
|
|
28
19
|
|
@@ -89,9 +80,9 @@ class Deployer < Screwcap::Base
|
|
89
80
|
# ====Any command sets that are nested within another command set will inerit all the variables from the parent command set.
|
90
81
|
#
|
91
82
|
def task name, options = {}, &block
|
92
|
-
t = Task.new(options.merge(:name => name
|
93
|
-
|
94
|
-
t.
|
83
|
+
t = Task.new(options.merge(:name => name), &block)
|
84
|
+
t.clone_from(self)
|
85
|
+
t.validate(self.__servers) unless options[:local] == true
|
95
86
|
self.__tasks << t
|
96
87
|
end
|
97
88
|
alias :task_for :task
|
@@ -123,10 +114,9 @@ class Deployer < Screwcap::Base
|
|
123
114
|
# redundant_task
|
124
115
|
# end
|
125
116
|
|
126
|
-
|
127
117
|
def command_set(name,options = {},&block)
|
128
|
-
t = Task.new(options.merge(:name => name
|
129
|
-
|
118
|
+
t = Task.new(options.merge(:name => name), &block)
|
119
|
+
t.clone_from(self)
|
130
120
|
self.__command_sets << t
|
131
121
|
end
|
132
122
|
|
@@ -142,7 +132,7 @@ class Deployer < Screwcap::Base
|
|
142
132
|
# * *:keys* can be used to specify the key to use to connect to the server
|
143
133
|
# * *:password* specify the password to connect with. Not recommended. Use keys.
|
144
134
|
def server(name, options = {}, &block)
|
145
|
-
server = Server.new(options.merge(:name => name
|
135
|
+
server = Server.new(options.merge(:name => name))
|
146
136
|
self.__servers << server
|
147
137
|
end
|
148
138
|
|
@@ -153,7 +143,7 @@ class Deployer < Screwcap::Base
|
|
153
143
|
# * Gateways have the same option as a *:server*.
|
154
144
|
# * You can specify :gateway => :mygateway in the *:server* definition.
|
155
145
|
def gateway(name, options = {}, &block)
|
156
|
-
server = Server.new(options.merge(:name => name, :is_gateway => true))
|
146
|
+
server = Server.new(options.merge(:name => name, :is_gateway => true, :servers => self.__servers))
|
157
147
|
self.__servers << server
|
158
148
|
end
|
159
149
|
|
@@ -182,24 +172,52 @@ class Deployer < Screwcap::Base
|
|
182
172
|
|
183
173
|
# ====Run one or more tasks or sequences.
|
184
174
|
# * :tasks - the list of tasks to run, as an array of symbols.
|
185
|
-
def run!(*
|
186
|
-
|
187
|
-
# sanity check each task
|
175
|
+
def run!(*tasks_to_run)
|
176
|
+
tasks_to_run.flatten!
|
188
177
|
|
189
|
-
|
190
|
-
|
191
|
-
|
178
|
+
tasks_to_run.map! do |ttr|
|
179
|
+
unless ret = self.__tasks.find {|t| t.__name == ttr }
|
180
|
+
seq = self.__sequences.find {|t| t.__name == ttr }
|
181
|
+
ret = seq.__task_names.map {|tn| self.__tasks.find {|t| t.__name == tn }}.compact if seq
|
182
|
+
end
|
183
|
+
ret
|
192
184
|
end
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
185
|
+
tasks_to_run.flatten!
|
186
|
+
tasks_to_run.compact!
|
187
|
+
|
188
|
+
ret = []
|
189
|
+
tasks_to_run.each do |task|
|
190
|
+
commands = task.__build_commands(self.__command_sets)
|
191
|
+
if task.__options[:local] == true
|
192
|
+
Runner.execute_locally! :commands => commands, :silent => self.__options[:silent]
|
198
193
|
else
|
199
|
-
|
194
|
+
threads = []
|
195
|
+
self.__servers.select {|s| task.__servers.include? s.__name }.each do |server|
|
196
|
+
server.__addresses.each do |address|
|
197
|
+
if task.__options[:parallel] == false
|
198
|
+
Runner.execute!(:name => task.__name,
|
199
|
+
:commands => commands,
|
200
|
+
:address => address,
|
201
|
+
:server => server,
|
202
|
+
:silent => self.__options[:silent])
|
203
|
+
else
|
204
|
+
threads << Thread.new(server,address) do |server, address|
|
205
|
+
Runner.execute!(:name => task.__name,
|
206
|
+
:commands => commands,
|
207
|
+
:address => address,
|
208
|
+
:server => server,
|
209
|
+
:silent => self.__options[:silent])
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
threads.each {|t| t.join }
|
200
215
|
end
|
216
|
+
ret << commands
|
201
217
|
end
|
218
|
+
|
202
219
|
$stdout << "\033[0m"
|
220
|
+
ret.flatten
|
203
221
|
end
|
204
222
|
|
205
223
|
# ====Use will dynamically include another file into an existing configuration file.
|
@@ -211,26 +229,17 @@ class Deployer < Screwcap::Base
|
|
211
229
|
def use arg
|
212
230
|
if arg.is_a? Symbol
|
213
231
|
begin
|
214
|
-
dirname = File.dirname(self.__options[:recipe_file])
|
215
|
-
instance_eval
|
232
|
+
dirname = File.expand_path(File.dirname(self.__options[:recipe_file]))
|
233
|
+
instance_eval File.read("#{dirname}/#{arg.to_s}.rb")
|
216
234
|
rescue Errno::ENOENT => e
|
217
235
|
raise Screwcap::IncludeFileNotFound, "Could not find #{File.expand_path("./"+arg.to_s + ".rb")}! If the file is elsewhere, call it by using 'use '/path/to/file.rb'"
|
218
236
|
end
|
219
237
|
else
|
220
238
|
begin
|
221
|
-
instance_eval(File.
|
239
|
+
instance_eval(File.read(arg))
|
222
240
|
rescue Errno::ENOENT => e
|
223
241
|
raise Screwcap::IncludeFileNotFound, "Could not find #{File.expand_path(arg)}! If the file is elsewhere, call it by using 'use '/path/to/file.rb'"
|
224
242
|
end
|
225
243
|
end
|
226
244
|
end
|
227
|
-
|
228
|
-
|
229
|
-
private
|
230
|
-
|
231
|
-
def clone_table_for(object)
|
232
|
-
self.table.each do |k,v|
|
233
|
-
object.set(k, v) unless [:__options, :__tasks, :__servers, :__command_sets].include?(k)
|
234
|
-
end
|
235
|
-
end
|
236
245
|
end
|
data/recipes/setup_rails.rb
CHANGED
@@ -8,7 +8,7 @@ task :setup_rails, :local => true do
|
|
8
8
|
then
|
9
9
|
echo "config/screwcap/rails_tasks.rb already exists!"; exit 1
|
10
10
|
else
|
11
|
-
curl -s
|
11
|
+
curl -s https://github.com/gammons/screwcap_recipes/raw/master/rails/rails_tasks.rb > config/screwcap/rails_tasks.rb
|
12
12
|
fi
|
13
13
|
EOF
|
14
14
|
|
@@ -17,7 +17,7 @@ task :setup_rails, :local => true do
|
|
17
17
|
then
|
18
18
|
echo "lib/tasks/screwcap.rake already exists!"; exit 1
|
19
19
|
else
|
20
|
-
curl -s
|
20
|
+
curl -s https://github.com/gammons/screwcap_recipes/raw/master/rails/screwcap.rake > lib/tasks/screwcap.rake
|
21
21
|
fi
|
22
22
|
EOF
|
23
23
|
|
@@ -26,7 +26,7 @@ task :setup_rails, :local => true do
|
|
26
26
|
then
|
27
27
|
echo "config/screwcap/recipe.rb already exists!"; exit 1
|
28
28
|
else
|
29
|
-
curl -s
|
29
|
+
curl -s https://github.com/gammons/screwcap_recipes/raw/master/rails/recipe.rb > config/screwcap/recipe.rb
|
30
30
|
fi
|
31
31
|
EOF
|
32
32
|
end
|
data/runrdoc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rdoc -x trollop -x spec -x runner -x object -x message -x tasknotfound -x runrdoc
|
data/screwcap.gemspec
CHANGED
data/spec/runner_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "The Runner" do
|
4
|
+
before(:all) do
|
5
|
+
Net::SSH.stubs(:start).yields(SSHObject.new(:return_stream => :stdout, :return_data => "ok\n"))
|
6
|
+
@server = Server.new :name => :server, :address => "fake.com", :user => "fake"
|
7
|
+
@task = Task.new :name => :test, :server => :server do
|
8
|
+
run "one"
|
9
|
+
run "two"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be able to execute commands on an address of a server" do
|
14
|
+
Runner.stubs(:ssh_exec!).returns(["ok\n","",0,nil])
|
15
|
+
|
16
|
+
commands = Runner.execute! :name => "test",
|
17
|
+
:server => @server,
|
18
|
+
:address => "fake.com",
|
19
|
+
:commands => @task.__build_commands,
|
20
|
+
:silent => true
|
21
|
+
|
22
|
+
commands[0][:stderr].should == ""
|
23
|
+
commands[0][:stdout].should == "ok\n"
|
24
|
+
|
25
|
+
commands[1][:stderr].should == ""
|
26
|
+
commands[1][:stdout].should == "ok\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be able to handle error commands" do
|
30
|
+
Runner.stubs(:ssh_exec!).returns(["ok\n","",0,nil]).then.returns(["","no\n",1,nil])
|
31
|
+
commands = Runner.execute! :name => "test",
|
32
|
+
:server => @server,
|
33
|
+
:address => "fake.com",
|
34
|
+
:commands => @task.__build_commands,
|
35
|
+
:silent => true
|
36
|
+
|
37
|
+
commands[0][:stderr].should == ""
|
38
|
+
commands[0][:stdout].should == "ok\n"
|
39
|
+
|
40
|
+
commands[1][:stderr].should == "no\n"
|
41
|
+
commands[1][:stdout].should == ""
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should be able to execute local commands" do
|
45
|
+
task = Task.new :name => :localtest, :local => true do
|
46
|
+
run "echo 'bongle'"
|
47
|
+
end
|
48
|
+
commands = Runner.execute_locally! :name => :localtest, :commands => task.__build_commands, :silent => true
|
49
|
+
commands[0][:stdout].should == "bongle\n"
|
50
|
+
end
|
51
|
+
end
|
data/spec/sequence_spec.rb
CHANGED
@@ -1,22 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "Sequences" do
|
4
|
-
before(:all) do
|
5
|
-
Net::SSH.stubs(:start).yields(SSHObject.new(:return_stream => :stdout, :return_data => "hostname = asdf\n"))
|
6
|
-
Runner.stubs(:ssh_exec!).returns(["ok","",0,nil])
|
7
|
-
end
|
8
|
-
before(:each) do
|
9
|
-
@stdout = []
|
10
|
-
Deployer.any_instance.stubs(:log).with() { |msg| @stdout << msg}
|
11
|
-
@deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true)
|
12
|
-
end
|
13
|
-
|
14
4
|
it "should contain a list of tasks to be called" do
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should be callable via Deployer.run!" do
|
20
|
-
lambda { @deployer.run! :deploy }.should_not raise_error
|
5
|
+
@seq = Sequence.new :tasks => [:task1, :task2]
|
6
|
+
@seq.__task_names.should == [:task1, :task2]
|
21
7
|
end
|
22
8
|
end
|
data/spec/server_spec.rb
CHANGED
@@ -29,13 +29,4 @@ describe "Servers" do
|
|
29
29
|
server = Server.new(:name => :test, :user => :root, :address => "abc.com")
|
30
30
|
server.should respond_to(:__with_connection_for)
|
31
31
|
end
|
32
|
-
|
33
|
-
it "should provide a connection to the server with a gateway" do
|
34
|
-
@deployer = Deployer.new(:recipe_file => "./test/config/gateway.rb", :silent => true)
|
35
|
-
server = @deployer.__servers.find {|s| s.__name == :test}
|
36
|
-
gateway = @deployer.__servers.find {|s| s.__name == :gateway1}
|
37
|
-
|
38
|
-
output = []
|
39
|
-
lambda { server.__with_connection {} }.should_not raise_error
|
40
|
-
end
|
41
32
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Task Managers" do
|
4
|
+
before(:all) do
|
5
|
+
Net::SSH.stubs(:start).yields(SSHObject.new(:return_stream => :stdout, :return_data => "ok\n"))
|
6
|
+
Runner.stubs(:ssh_exec!).returns(["ok\n","",0,nil])
|
7
|
+
end
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
@tm = TaskManager.new :silent => true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can have tasks and servers" do
|
14
|
+
@tm.server :server, :address => "test", :user => "root"
|
15
|
+
@tm.task :deploy, :server => :server do
|
16
|
+
run "test"
|
17
|
+
end
|
18
|
+
|
19
|
+
@tm.should have(1).__servers
|
20
|
+
@tm.should have(1).__tasks
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should validate tasks" do
|
24
|
+
@tm = TaskManager.new
|
25
|
+
@tm.server :server, :address => "test", :user => "root"
|
26
|
+
lambda { @tm.task(:deploy, :server => :not_here) { run "test" } }.should raise_error(Screwcap::ConfigurationError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be able to define variables" do
|
30
|
+
@tm.moon_pie= "moon pie"
|
31
|
+
@tm.moon_pie.should == "moon pie"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should pass variables to tasks" do
|
35
|
+
@tm.pie_type = "moon pie"
|
36
|
+
@tm.server :server, :address => "test", :user => "root"
|
37
|
+
@tm.task :deploy, :server => :server do
|
38
|
+
run "#{pie_type} in the face!"
|
39
|
+
end
|
40
|
+
|
41
|
+
@tm.__tasks[0].__build_commands[0][:command].should == "moon pie in the face!"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should be able to define command sets" do
|
45
|
+
@tm.command_set :my_command_set do
|
46
|
+
run "test"
|
47
|
+
end
|
48
|
+
|
49
|
+
@tm.should have(1).__command_sets
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should be able to load a recipe file" do
|
53
|
+
@tm = TaskManager.new(:recipe_file => "test/config/super_simple_recipe.rb")
|
54
|
+
@tm.pie.should == "moon pie"
|
55
|
+
@tm.should have(1).__command_sets
|
56
|
+
@tm.should have(1).__tasks
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should be able to execute a recipe" do
|
60
|
+
@tm.pie_type = "moon pie"
|
61
|
+
@tm.server :server, :address => "test", :user => "root"
|
62
|
+
@tm.task :deploy, :server => :server do
|
63
|
+
run "#{pie_type} in the face!"
|
64
|
+
end
|
65
|
+
commands = @tm.run! :deploy, :deploy2
|
66
|
+
commands.size.should == 1
|
67
|
+
commands.first[:command].should == "moon pie in the face!"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should be able to include multiple recipe files in a single recipe" do
|
71
|
+
@tm = TaskManager.new(:recipe_file => "test/config/use.rb")
|
72
|
+
@tm.pie.should == "moon pie"
|
73
|
+
@tm.should have(1).__command_sets
|
74
|
+
@tm.should have(1).__tasks
|
75
|
+
|
76
|
+
@tm = TaskManager.new(:recipe_file => "test/config/use2.rb")
|
77
|
+
@tm.pie.should == "moon pie"
|
78
|
+
@tm.should have(1).__command_sets
|
79
|
+
@tm.should have(1).__tasks
|
80
|
+
end
|
81
|
+
|
82
|
+
it "will complain if it can't find the use file" do
|
83
|
+
lambda { TaskManager.new(:recipe_file => "test/config/bad_use.rb") }.should raise_error(Screwcap::IncludeFileNotFound)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should be able to define gateways" do
|
87
|
+
@tm.gateway :gateway, :address => "xyz.com", :user => "root"
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should be able to define and run sequences" do
|
91
|
+
@tm.server :server, :address => "test", :user => "root"
|
92
|
+
@tm.task(:task1, :server => :server) { run "task1" }
|
93
|
+
@tm.task(:task2, :server => :server) { run "task2" }
|
94
|
+
@tm.sequence :seq, :tasks => [:task1, :task2]
|
95
|
+
commands = @tm.run! :seq
|
96
|
+
commands.size.should == 2
|
97
|
+
commands[0][:command].should == "task1"
|
98
|
+
commands[1][:command].should == "task2"
|
99
|
+
end
|
100
|
+
end
|
data/spec/task_spec.rb
CHANGED
@@ -1,87 +1,150 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "Tasks" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
it "should have a task-like structure" do
|
5
|
+
task = Task.new :name => :test do
|
6
|
+
run "test"
|
7
|
+
end
|
8
|
+
|
9
|
+
task.__commands.should have(0).__commands
|
10
|
+
task.__build_commands
|
11
|
+
task.__commands.should_not be_nil
|
12
|
+
task.should have(1).__commands
|
13
|
+
|
14
|
+
task.__commands[0][:type].should == :remote
|
15
|
+
task.__commands[0][:from].should == :test
|
16
|
+
task.__commands[0][:command].should == "test"
|
10
17
|
end
|
11
18
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
19
|
+
it "should be able to build commands" do
|
20
|
+
unknown = Task.new :name => :unknown_action do
|
21
|
+
run "unknown"
|
22
|
+
end
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
24
|
+
task = Task.new :name => :test do
|
25
|
+
run "test"
|
26
|
+
unknown_action
|
27
|
+
end
|
28
|
+
|
29
|
+
commands = task.__build_commands([unknown])
|
30
|
+
commands.size.should == 2
|
31
|
+
|
32
|
+
commands[0][:type].should == :remote
|
33
|
+
commands[0][:from].should == :test
|
34
|
+
commands[0][:command].should == "test"
|
35
|
+
|
36
|
+
commands[1][:type].should == :remote
|
37
|
+
commands[1][:from].should == :unknown_action
|
38
|
+
commands[1][:command].should == "unknown"
|
21
39
|
end
|
22
40
|
|
23
|
-
it "should
|
24
|
-
task =
|
25
|
-
|
41
|
+
it "should throw an error if we cannot find a command" do
|
42
|
+
task = Task.new :name => :test do
|
43
|
+
run "test"
|
44
|
+
unknown_action
|
45
|
+
end
|
46
|
+
|
47
|
+
lambda {task.__build_commands([task]) }.should raise_error(NoMethodError)
|
26
48
|
end
|
27
49
|
|
28
|
-
it "should be able to
|
29
|
-
task =
|
30
|
-
|
31
|
-
|
32
|
-
|
50
|
+
it "should be able to create variables" do
|
51
|
+
task = Task.new :name => :test do
|
52
|
+
set :blaster, "stun"
|
53
|
+
run "fire #{blaster}"
|
54
|
+
end
|
55
|
+
task.__build_commands
|
56
|
+
task.blaster.should == "stun"
|
57
|
+
task.__commands.first[:command].should == "fire stun"
|
33
58
|
end
|
34
59
|
|
35
|
-
it
|
36
|
-
|
37
|
-
|
38
|
-
|
60
|
+
it "command sets should inherit the parent's variables" do
|
61
|
+
subsub = Task.new :name => :subsubtask do
|
62
|
+
set :from, "venus"
|
63
|
+
run "fly to #{where} from #{from}"
|
64
|
+
end
|
65
|
+
|
66
|
+
sub = Task.new :name => :subtask do
|
67
|
+
set :from, "mars"
|
68
|
+
run "fly to #{where} from #{from}"
|
69
|
+
subsubtask
|
70
|
+
end
|
71
|
+
|
72
|
+
task = Task.new :name => :task do
|
73
|
+
set :where, "the moon"
|
74
|
+
set :from, "earth"
|
75
|
+
run "fly to #{where} from #{from}"
|
76
|
+
subtask
|
77
|
+
end
|
78
|
+
|
79
|
+
commands = task.__build_commands([sub, subsub])
|
80
|
+
commands[0][:from].should == :task
|
81
|
+
commands[0][:command].should == "fly to the moon from earth"
|
82
|
+
|
83
|
+
commands[1][:from].should == :subtask
|
84
|
+
commands[1][:command].should == "fly to the moon from mars"
|
85
|
+
|
86
|
+
commands[2][:from].should == :subsubtask
|
87
|
+
commands[2][:command].should == "fly to the moon from venus"
|
39
88
|
end
|
40
89
|
|
41
|
-
it "should
|
42
|
-
|
43
|
-
|
90
|
+
it "should respond to :before or before_ calls" do
|
91
|
+
before = Task.new :name => :do_before do
|
92
|
+
run "before"
|
93
|
+
end
|
94
|
+
task = Task.new :name => :test, :before => :do_before do
|
95
|
+
run "task"
|
96
|
+
end
|
44
97
|
|
45
|
-
|
46
|
-
|
98
|
+
before2 = Task.new :name => :before_deploy do
|
99
|
+
run "before"
|
100
|
+
end
|
47
101
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
102
|
+
task2 = Task.new :name => :deploy do
|
103
|
+
run "deploy"
|
104
|
+
end
|
52
105
|
|
53
|
-
|
54
|
-
|
55
|
-
end
|
106
|
+
commands = task.__build_commands([before])
|
107
|
+
commands.map {|c| c[:command] }.should == ["before","task"]
|
56
108
|
|
57
|
-
|
58
|
-
|
109
|
+
commands = task2.__build_commands([before2])
|
110
|
+
commands.map {|c| c[:command] }.should == ["before","deploy"]
|
59
111
|
end
|
60
112
|
|
61
|
-
it "should
|
62
|
-
|
63
|
-
|
64
|
-
|
113
|
+
it "should respond to :after or after_ calls" do
|
114
|
+
after = Task.new :name => :do_after do
|
115
|
+
run "after"
|
116
|
+
end
|
117
|
+
task = Task.new :name => :test, :after => :do_after do
|
118
|
+
run "task"
|
119
|
+
end
|
65
120
|
|
66
|
-
|
67
|
-
|
68
|
-
|
121
|
+
after2 = Task.new :name => :after_deploy do
|
122
|
+
run "after"
|
123
|
+
end
|
69
124
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
125
|
+
task2 = Task.new :name => :deploy do
|
126
|
+
run "deploy"
|
127
|
+
end
|
128
|
+
|
129
|
+
commands = task.__build_commands([after])
|
130
|
+
commands.map {|c| c[:command] }.should == ["task","after"]
|
74
131
|
|
75
|
-
|
76
|
-
|
77
|
-
t = deployer.__tasks.find {|t| t.__name == :expect }
|
78
|
-
Runner.stubs(:ssh_exec!).returns(["","fail",1,nil]).then.returns(["ok","",0,nil])
|
79
|
-
Runner.execute! t, deployer.__options
|
80
|
-
t.__commands.map {|c| [c[:command], c[:from]] }.first.should == ["echo 'we failed'", :failover]
|
132
|
+
commands = task2.__build_commands([after2])
|
133
|
+
commands.map {|c| c[:command] }.should == ["deploy", "after"]
|
81
134
|
end
|
82
135
|
|
83
|
-
it "should
|
84
|
-
|
85
|
-
lambda {
|
136
|
+
it "should validate" do
|
137
|
+
task = Task.new :name => :test
|
138
|
+
lambda { task.validate([]) }.should raise_error(Screwcap::ConfigurationError)
|
139
|
+
|
140
|
+
server = Server.new :name => :server, :address => "none", :user => "yeah"
|
141
|
+
other_server = Server.new :name => :server2, :address => "none", :user => "yeah"
|
142
|
+
task = Task.new :name => :test, :server => :server
|
143
|
+
lambda { task.validate([server]) }.should_not raise_error
|
144
|
+
lambda { task.validate([other_server]) }.should raise_error(Screwcap::ConfigurationError)
|
145
|
+
task = Task.new :name => :test, :servers => :server
|
146
|
+
lambda { task.validate([server]) }.should_not raise_error
|
147
|
+
task = Task.new :name => :test, :servers => [:server, :server2]
|
148
|
+
lambda { task.validate([server,other_server]) }.should_not raise_error
|
86
149
|
end
|
87
150
|
end
|