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.
@@ -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