screwcap 0.3.5 → 0.5
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.
- 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
|