screwcap 0.3.5 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,12 +1,11 @@
1
- # The deployer is the class that holds the overall params from the screwcap tasks file, and it is also in charge of running the requested task.
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 deployer can be thought of as the "global scope" of your tasks file.
4
- class Deployer < Screwcap::Base
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 deployer.
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
- # ensure that deployer options will not be passed to tasks
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, :nocolor => self.__options[:nocolor], :silent => self.__options[:silent], :deployment_servers => self.__servers, :command_sets => self.__command_sets), &block)
93
- clone_table_for(t)
94
- t.instance_eval(&block)
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, :validate => false, :command_set => true, :command_sets => self.__command_sets), &block)
129
- clone_table_for(t)
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, :servers => self.__servers, :silent => self.__options[:silent]))
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!(*tasks)
186
- tasks.flatten!
187
- # sanity check each task
175
+ def run!(*tasks_to_run)
176
+ tasks_to_run.flatten!
188
177
 
189
- tasks_and_sequences = (self.__sequences.map(&:__name) + self.__tasks.map(&:__name))
190
- tasks.each do |task_to_run|
191
- raise(Screwcap::TaskNotFound, "Could not find task or sequence '#{task_to_run}' in recipe file #{self.__options[:recipe_file]}") unless tasks_and_sequences.include? task_to_run
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
- tasks.each do |t|
195
- sequence = self.__sequences.find {|s| s.__name == t }
196
- if sequence
197
- sequence.__task_names.each {|task_name| Runner.execute! self.__tasks.find {|task| task.__name == task_name }, self.__options}
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
- Runner.execute! self.__tasks.select {|task| task.name.to_s == t.to_s }.first, self.__options
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(File.open(File.dirname(File.expand_path(self.__options[:recipe_file])) + "/" + arg.to_s + ".rb").read)
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.open(File.dirname(File.expand_path(self.__options[:recipe_file])) + "/" + arg).read)
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
@@ -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 http://github.com/gammons/screwcap_recipes/raw/master/rails/rails_tasks.rb > config/screwcap/rails_tasks.rb
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 http://github.com/gammons/screwcap_recipes/raw/master/rails/screwcap.rake > lib/tasks/screwcap.rake
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 http://github.com/gammons/screwcap_recipes/raw/master/rails/recipe.rb > config/screwcap/recipe.rb
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
@@ -6,7 +6,7 @@ require 'bundler/version'
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "screwcap"
9
- s.version = "0.3.5"
9
+ s.version = "0.5"
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.author = "Grant Ammons"
12
12
  s.email = ["grant@pipelinedealsco.com"]
@@ -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
@@ -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
- sequence = @deployer.__sequences.find {|s| s.__name == :deploy}
16
- sequence.__task_names.should == [:seq1, :seq2]
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
- before(:each) do
5
- @stdout = []
6
- @stderr = []
7
- Runner.stubs(:log).with() { |msg,opts| @stdout << msg }
8
- Runner.stubs(:errorlog).with() { |msg,opts| @stderr << msg }
9
- @deployer = Deployer.new(:recipe_file => "./test/config/simple_recipe.rb", :silent => true)
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
- before(:all) do
13
- Net::SSH.stubs(:start).yields(SSHObject.new(:return_stream => :stdout, :return_data => "hostname = asdf\n"))
14
- Net::SCP.stubs(:upload!).returns(nil)
15
- Runner.stubs(:ssh_exec!).returns(["ok","",0,nil])
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
- it "should be able to create variables" do
19
- task = @deployer.__tasks.find {|t| t.name == :task1 }
20
- task.bango.should == "bongo"
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 compile run statements" do
24
- task = @deployer.__tasks.find {|t| t.name == :task1 }
25
- task.should have(6).__commands
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 execute statements on a remote server" do
29
- task = @deployer.__tasks.find {|t| t.name == :task1 }
30
- Runner.execute! task, @deployer.__options
31
- @stderr.size.should == 0
32
- @stdout.size.should == 28
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 "should be able to use variables in the run statement" do
36
- task = @deployer.__tasks.find {|t| t.name == :task1 }
37
- command = task.__commands.map{|c| c[:command] }.find {|c| c.index "deploy dir" }
38
- command.should == "deploy dir = tester"
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 be able to override a globally set variable" do
42
- @deployer.deploy_var_2.should == "bongo"
43
- @deployer.deploy_var_3.should == %w(one two)
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
- task = @deployer.__tasks.find {|t| t.name == :task1 }
46
- task.deploy_var_2.should == "shasta"
98
+ before2 = Task.new :name => :before_deploy do
99
+ run "before"
100
+ end
47
101
 
48
- task = @deployer.__tasks.find {|t| t.name == :task2 }
49
- task.deploy_var_2.should == "purple"
50
- task.deploy_var_3.should == "mountain dew"
51
- end
102
+ task2 = Task.new :name => :deploy do
103
+ run "deploy"
104
+ end
52
105
 
53
- it "should complain if you do not pass the task a server argument" do
54
- lambda { Deployer.new(:recipe_file => "./test/config/no_server.rb", :silent => true)}.should raise_error(Screwcap::ConfigurationError)
55
- end
106
+ commands = task.__build_commands([before])
107
+ commands.map {|c| c[:command] }.should == ["before","task"]
56
108
 
57
- it "should complain if you pass a server that is not defined" do
58
- lambda { Deployer.new(:recipe_file => "./test/config/undefined_server.rb", :silent => true)}.should raise_error(Screwcap::ConfigurationError)
109
+ commands = task2.__build_commands([before2])
110
+ commands.map {|c| c[:command] }.should == ["before","deploy"]
59
111
  end
60
112
 
61
- it "should be able to disable parallel running" do
62
- # this is hard to test. with threads and stuff
63
- lambda { @deployer.run! :non_parallel }.should_not raise_error
64
- end
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
- it "should be able to run local commands" do
67
- lambda { @deployer.run! :task3 }.should_not raise_error
68
- end
121
+ after2 = Task.new :name => :after_deploy do
122
+ run "after"
123
+ end
69
124
 
70
- it "should be able to upload files using the scp command" do
71
- deployer = Deployer.new(:recipe_file => "./test/config/upload.rb", :silent => true)
72
- deployer.run! :upload
73
- end
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
- it "should respond to onfailure" do
76
- deployer = Deployer.new(:recipe_file => "./test/config/expect.rb", :silent => true)
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 be able to create local tasks" do
84
- # TODO better testing on this
85
- lambda { Deployer.new(:recipe_file => "./test/config/local_task.rb", :silent => true).run! :local }.should_not raise_error
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