yad 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/LICENSE +20 -0
- data/README.rdoc +110 -0
- data/Rakefile +87 -0
- data/VERSION.yml +4 -0
- data/doc/faq.rdoc +9 -0
- data/features/step_definitions/yad_steps.rb +0 -0
- data/features/support/env.rb +9 -0
- data/features/yad.feature +9 -0
- data/lib/ext/rake.rb +66 -0
- data/lib/ext/rake/remote_task.rb +521 -0
- data/lib/ext/string.rb +6 -0
- data/lib/yad.rb +46 -0
- data/lib/yad/app/passenger.rb +28 -0
- data/lib/yad/core.rb +199 -0
- data/lib/yad/db/rails.rb +62 -0
- data/lib/yad/framework/rails.rb +64 -0
- data/lib/yad/maintenance/shared_system.rb +39 -0
- data/lib/yad/scm/git.rb +62 -0
- data/lib/yad/web/apache.rb +62 -0
- data/spec/ext/rake/remote_task_spec.rb +394 -0
- data/spec/spec_helper.rb +79 -0
- data/spec/yad/app/passenger_spec.rb +10 -0
- data/spec/yad/core_spec.rb +69 -0
- data/spec/yad/db/rails_spec.rb +15 -0
- data/spec/yad/framework/rails_spec.rb +25 -0
- data/spec/yad/maintenance/shared_system_spec.rb +15 -0
- data/spec/yad/scm/git_spec.rb +30 -0
- data/spec/yad/web/apache_spec.rb +25 -0
- data/yad.gemspec +87 -0
- metadata +132 -0
data/lib/yad/scm/git.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
module Yad
|
2
|
+
module Scm
|
3
|
+
class Git
|
4
|
+
def self.build_checkout_command(repository, destination_directory, options = {})
|
5
|
+
default_options = { :revision => 'origin/master', :enable_submodules => true }
|
6
|
+
options = default_options.merge(options)
|
7
|
+
|
8
|
+
commands = ["([ -d #{destination_directory}/cached-copy/.git ] && echo 'Existing repository found' || git clone #{repository} #{destination_directory}/cached-copy)",
|
9
|
+
"cd #{destination_directory}/cached-copy",
|
10
|
+
"git fetch",
|
11
|
+
"git reset --hard #{options[:revision]}"
|
12
|
+
]
|
13
|
+
|
14
|
+
if options[:enable_submodules]
|
15
|
+
commands << [ "git submodule -q init",
|
16
|
+
"git submodule -q update"
|
17
|
+
]
|
18
|
+
end
|
19
|
+
commands.join(" && ")
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.build_export_command(source_directory, destination_directory)
|
23
|
+
"mkdir -p #{destination_directory} && rsync -a -f '- .git' #{source_directory}/cached-copy/ #{destination_directory}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.build_inline_revision_identifier_command(scm_directory, options = {})
|
27
|
+
default_options = { :revision => 'origin/master' }
|
28
|
+
options = default_options.merge(options)
|
29
|
+
"`cd #{scm_directory}/cached-copy && git rev-parse #{options[:revision]}`"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.define_tasks
|
33
|
+
return if @tasks_already_defined
|
34
|
+
@tasks_already_defined = true
|
35
|
+
namespace :yad do
|
36
|
+
namespace :scm do
|
37
|
+
|
38
|
+
desc "Updates the source code on the application servers and exports it as the latest release"
|
39
|
+
remote_task :update, :roles => :app do
|
40
|
+
begin
|
41
|
+
options = Rake::RemoteTask.get_options_hash(:revision, :enable_submodules)
|
42
|
+
checkout_command = Yad::Scm::Git.build_checkout_command(repository, scm_path, options)
|
43
|
+
export_command = Yad::Scm::Git.build_export_command(scm_path, release_path)
|
44
|
+
cmd = Yad::Core.build_update_source_code_command(checkout_command, export_command, release_path)
|
45
|
+
run(cmd)
|
46
|
+
puts("source code updated on #{target_host}")
|
47
|
+
rescue => e
|
48
|
+
cmd = Yad::Core.build_remove_directory_command(release_path)
|
49
|
+
run(cmd)
|
50
|
+
raise e
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end # class Git
|
60
|
+
|
61
|
+
end # module Scm
|
62
|
+
end # module Yad
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Yad
|
2
|
+
module Web
|
3
|
+
class Apache
|
4
|
+
def self.build_start_command(options = {})
|
5
|
+
default_options = { :apache_command => 'apachectl' }
|
6
|
+
options = default_options.merge(options)
|
7
|
+
"#{options[:apache_command]} start"
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.build_stop_command(options = {})
|
11
|
+
default_options = { :apache_command => 'apachectl' }
|
12
|
+
options = default_options.merge(options)
|
13
|
+
"#{options[:apache_command]} stop"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.build_restart_command(options = {})
|
17
|
+
default_options = { :apache_command => 'apachectl' }
|
18
|
+
options = default_options.merge(options)
|
19
|
+
"#{options[:apache_command]} restart"
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.define_tasks
|
23
|
+
return if @tasks_already_defined
|
24
|
+
@tasks_already_defined = true
|
25
|
+
namespace :yad do
|
26
|
+
namespace :web do
|
27
|
+
|
28
|
+
desc "Starts the web server"
|
29
|
+
remote_task :start, :roles => :web do
|
30
|
+
options = Rake::RemoteTask.get_options_hash(:apache_command)
|
31
|
+
cmd = Yad::Web::Apache.build_start_command(options)
|
32
|
+
use_sudo_for_apache = Rake::RemoteTask.fetch(:use_sudo_for_apache, true)
|
33
|
+
if use_sudo_for_apache
|
34
|
+
sudo(cmd)
|
35
|
+
else
|
36
|
+
run(cmd)
|
37
|
+
end
|
38
|
+
puts("Apache started on #{target_host}")
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "Stops the web server"
|
42
|
+
remote_task :stop, :roles => :web do
|
43
|
+
options = Rake::RemoteTask.get_options_hash(:apache_command)
|
44
|
+
cmd = Yad::Web::Apache.build_stop_command(options)
|
45
|
+
use_sudo_for_apache = Rake::RemoteTask.fetch(:use_sudo_for_apache, true)
|
46
|
+
if use_sudo_for_apache
|
47
|
+
sudo(cmd)
|
48
|
+
else
|
49
|
+
run(cmd)
|
50
|
+
end
|
51
|
+
puts("Apache stopped on #{target_host}")
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end # class Apache
|
60
|
+
|
61
|
+
end # module Web
|
62
|
+
end # module Yad
|
@@ -0,0 +1,394 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Rake::RemoteTask do
|
4
|
+
def create_example_task(options = {})
|
5
|
+
task = Rake::RemoteTask.remote_task(:test_task, options)
|
6
|
+
task.commands = []
|
7
|
+
task.output = []
|
8
|
+
task.error = []
|
9
|
+
task.action = nil
|
10
|
+
task
|
11
|
+
end
|
12
|
+
|
13
|
+
def capture_output
|
14
|
+
require 'stringio'
|
15
|
+
orig_stdout = $stdout.dup
|
16
|
+
orig_stderr = $stderr.dup
|
17
|
+
captured_stdout = StringIO.new
|
18
|
+
captured_stderr = StringIO.new
|
19
|
+
$stdout = captured_stdout
|
20
|
+
$stderr = captured_stderr
|
21
|
+
yield
|
22
|
+
captured_stdout.rewind
|
23
|
+
captured_stderr.rewind
|
24
|
+
return captured_stdout, captured_stderr
|
25
|
+
ensure
|
26
|
+
$stdout = orig_stdout
|
27
|
+
$stderr = orig_stderr
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should list all remote hosts" do
|
31
|
+
set_example_hosts
|
32
|
+
Rake::RemoteTask.all_hosts.should eql(%w[app.example.com db.example.com])
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should fetch variables that have been set" do
|
36
|
+
set :foo, 5
|
37
|
+
Rake::RemoteTask.fetch(:foo).should eql(5)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should fetch the given default when a variable is not set" do
|
41
|
+
Rake::RemoteTask.fetch(:not_here, 5).should eql(5)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should assign multiple roles to one remote host" do
|
45
|
+
Rake::RemoteTask.host "test.example.com", :app, :db
|
46
|
+
Rake::RemoteTask.roles[:app].should == { "test.example.com" => {} }
|
47
|
+
Rake::RemoteTask.roles[:db].should == { "test.example.com" => {} }
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should error when the host name is invalid" do
|
51
|
+
lambda { Rake::RemoteTask.host nil, :web }.should raise_error(ArgumentError)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should assign multiple roles to multiple remote hosts" do
|
55
|
+
Rake::RemoteTask.host "test.example.com", :app, :db
|
56
|
+
Rake::RemoteTask.host "yarr.example.com", :app, :db, :no_release => true
|
57
|
+
|
58
|
+
expected = {
|
59
|
+
"test.example.com" => {},
|
60
|
+
"yarr.example.com" => {:no_release => true}
|
61
|
+
}
|
62
|
+
|
63
|
+
Rake::RemoteTask.roles[:app].should == expected
|
64
|
+
Rake::RemoteTask.roles[:db].should == expected
|
65
|
+
Rake::RemoteTask.roles[:app]["test.example.com"].object_id.should_not eql(Rake::RemoteTask.roles[:db]["test.example.com"].object_id)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should get remote hosts for an array of roles" do
|
69
|
+
set_example_hosts
|
70
|
+
Rake::RemoteTask.hosts_for([:app, :db]).should eql(%w[app.example.com db.example.com])
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should get remote hosts for one role" do
|
74
|
+
set_example_hosts
|
75
|
+
Rake::RemoteTask.host "app2.example.com", :app
|
76
|
+
Rake::RemoteTask.hosts_for(:app).should eql(%w[app.example.com app2.example.com])
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should get remote hosts for multiple roles" do
|
80
|
+
set_example_hosts
|
81
|
+
Rake::RemoteTask.hosts_for(:app, :db).should eql(%w[app.example.com db.example.com])
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should get a unique list of remote hosts for given roles" do
|
85
|
+
set_example_hosts
|
86
|
+
Rake::RemoteTask.host "app.example.com", :web
|
87
|
+
Rake::RemoteTask.hosts_for(:app, :db, :web).should eql(%w[app.example.com db.example.com])
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should not set defaults for required configuration variables" do
|
91
|
+
Rake::RemoteTask.set_defaults
|
92
|
+
lambda { Rake::RemoteTask.repository }.should raise_error(Rake::RemoteTask::ConfigurationError)
|
93
|
+
lambda { Rake::RemoteTask.deploy_to }.should raise_error(Rake::RemoteTask::ConfigurationError)
|
94
|
+
lambda { Rake::RemoteTask.domain }.should raise_error(Rake::RemoteTask::ConfigurationError)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should assign a role for one remote host" do
|
98
|
+
Rake::RemoteTask.role :app, "test.example.com"
|
99
|
+
Rake::RemoteTask.roles[:app].should == { "test.example.com" => {} }
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should assign a role for multiple remote hosts" do
|
103
|
+
Rake::RemoteTask.role :app, "test.example.com", :primary => true
|
104
|
+
Rake::RemoteTask.role :db, "yarr.example.com", :no_release => true
|
105
|
+
Rake::RemoteTask.roles[:db].should == { "yarr.example.com" => { :no_release => true } }
|
106
|
+
Rake::RemoteTask.roles[:app].should == { "test.example.com" => { :primary => true } }
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should increase the number of tasks when created" do
|
110
|
+
task = Rake::RemoteTask.remote_task(:test_task) { 5 }
|
111
|
+
Rake.application.tasks.size.should eql(@task_count + 1)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should assign an empty set of roles if none are supplied" do
|
115
|
+
task = Rake::RemoteTask.remote_task(:test_task) { 5 }
|
116
|
+
task.options.should == { :roles => [] }
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should assign all remote hosts to a task by default" do
|
120
|
+
set_example_hosts
|
121
|
+
task = Rake::RemoteTask.remote_task(:test_task) { 5 }
|
122
|
+
task.target_hosts.should eql(%w[app.example.com db.example.com])
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should override hosts from environment" do
|
126
|
+
old_env_hosts = ENV["HOSTS"]
|
127
|
+
ENV["HOSTS"] = 'other1.example.com, other2.example.com'
|
128
|
+
set_example_hosts
|
129
|
+
task = Rake::RemoteTask.remote_task(:test_task) { 5 }
|
130
|
+
task.target_hosts.should eql(%w[other1.example.com other2.example.com])
|
131
|
+
ENV["HOSTS"] = old_env_hosts
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should have access set variables within task body" do
|
135
|
+
set(:some_variable, 5)
|
136
|
+
Rake::RemoteTask.host 'www.example.com', :app
|
137
|
+
Rake::RemoteTask.remote_task(:some_task) do $some_task_result = some_variable end
|
138
|
+
Rake::Task['some_task'].execute nil
|
139
|
+
Rake::RemoteTask.fetch(:some_variable).should eql($some_task_result)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should assign roles when creating a task" do
|
143
|
+
task = Rake::RemoteTask.remote_task :test_task, :roles => [:app, :db] do
|
144
|
+
fail "should not run"
|
145
|
+
end
|
146
|
+
task.options.should == { :roles => [:app, :db] }
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should allow hosts to be assigned to a role after a task for a role has been created" do
|
150
|
+
task = Rake::RemoteTask.remote_task :test_task, :roles => :web do 5 end
|
151
|
+
Rake::RemoteTask.host 'www.example.com', :web
|
152
|
+
task.target_hosts.should eql(%w[www.example.com])
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should allow for roles to be overridden" do
|
156
|
+
host "db1", :db
|
157
|
+
host "db2", :db
|
158
|
+
host "db3", :db
|
159
|
+
host "master", :master_db
|
160
|
+
|
161
|
+
remote_task(:migrate_the_db, :roles => [:db]) { fail "bad!" }
|
162
|
+
task = Rake::Task["migrate_the_db"]
|
163
|
+
task.target_hosts.should eql(%w[db1 db2 db3])
|
164
|
+
|
165
|
+
task.options[:roles] = :master_db
|
166
|
+
task.target_hosts.should eql(%w[master])
|
167
|
+
|
168
|
+
task.options[:roles] = [:master_db]
|
169
|
+
task.target_hosts.should eql(%w[master])
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should set variables" do
|
173
|
+
set :test, 5
|
174
|
+
Rake::RemoteTask.test.should eql(5)
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should do lazy evaluation of set blocks" do
|
178
|
+
set(:test) { fail "lose" }
|
179
|
+
lambda { Rake::RemoteTask.test }.should raise_error(RuntimeError)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should evaluate a set block the first time" do
|
183
|
+
x = 1
|
184
|
+
set(:test) { x += 2 }
|
185
|
+
Rake::RemoteTask.test.should eql(3)
|
186
|
+
Rake::RemoteTask.test.should eql(3)
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should have access to set variables within set blocks" do
|
190
|
+
Rake::RemoteTask.instance_eval do
|
191
|
+
set(:var_one) { var_two }
|
192
|
+
set(:var_two) { var_three }
|
193
|
+
set(:var_three) { 5 }
|
194
|
+
end
|
195
|
+
|
196
|
+
Rake::RemoteTask.var_one.should eql(5)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should error when a value and a block is supplied with set" do
|
200
|
+
lambda { set(:test, 5) { 6 } }.should raise_error(ArgumentError, "cannot provide both a value and a block")
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should allow a variable to be set to nil" do
|
204
|
+
set(:test, nil)
|
205
|
+
Rake::RemoteTask.test.should be_nil
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should not allow variables with reserved names to be set" do
|
209
|
+
$TESTING = false
|
210
|
+
lambda { set(:all_hosts, []) }.should raise_error(ArgumentError, "cannot set reserved name: 'all_hosts'")
|
211
|
+
$TESTING = true
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should allow a variable to be set to false" do
|
215
|
+
set(:can_set_nil, nil)
|
216
|
+
set(:lies_are, false)
|
217
|
+
|
218
|
+
Rake::RemoteTask.can_set_nil.should be_nil
|
219
|
+
Rake::RemoteTask.lies_are.should be_false
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should fetch false as a default for a variable" do
|
223
|
+
Rake::RemoteTask.fetch(:unknown, false).should be_false
|
224
|
+
end
|
225
|
+
|
226
|
+
it "should be enhanced with prerequisites and actions when it has been created with a body" do
|
227
|
+
set_example_hosts
|
228
|
+
body = Proc.new { 5 }
|
229
|
+
task = Rake::RemoteTask.remote_task(:some_task => :foo, &body)
|
230
|
+
action = Rake::RemoteTask::Action.new(task, body)
|
231
|
+
task.remote_actions.should == [action]
|
232
|
+
action.task.should eql(task)
|
233
|
+
task.prerequisites.should eql(["foo"])
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should not be enhanced with prerequisites or actions when it has been created without a body" do
|
237
|
+
set_example_hosts
|
238
|
+
task = create_example_task
|
239
|
+
task.remote_actions.should be_empty
|
240
|
+
task.prerequisites.should be_empty
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should execute on all remote hosts when no role is given" do
|
244
|
+
set_example_hosts
|
245
|
+
set :some_variable, 1
|
246
|
+
x = 5
|
247
|
+
task = Rake::RemoteTask.remote_task(:some_task) { x += some_variable }
|
248
|
+
task.execute nil
|
249
|
+
task.some_variable.should eql(1)
|
250
|
+
x.should eql(7)
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should allow variables to be set inside of the body" do
|
254
|
+
host "app.example.com", :app
|
255
|
+
task = Rake::RemoteTask.remote_task(:target_task) { set(:test_target_host, target_host) }
|
256
|
+
task.execute nil
|
257
|
+
Rake::RemoteTask.fetch(:test_target_host).should eql("app.example.com")
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should not excute with no remote hosts set" do
|
261
|
+
Rake::RemoteTask.host "app.example.com", :app
|
262
|
+
task = Rake::RemoteTask.remote_task(:flunk, :roles => :db) { fail "should not have run" }
|
263
|
+
lambda { task.execute nil }.should raise_error(Rake::RemoteTask::ConfigurationError,
|
264
|
+
"No target hosts specified on task flunk for roles [:db]")
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should not execute with no remote hosts for a given role" do
|
268
|
+
task = Rake::RemoteTask.remote_task(:flunk, :roles => :junk) { fail "should not have run" }
|
269
|
+
lambda { task.execute nil }.should raise_error(Rake::RemoteTask::ConfigurationError,
|
270
|
+
"No target hosts specified on task flunk for roles [:junk]")
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should execute on remote hosts with a given role" do
|
274
|
+
set_example_hosts
|
275
|
+
set :some_variable, 1
|
276
|
+
x = 5
|
277
|
+
task = Rake::RemoteTask.remote_task(:some_task, :roles => :db) { x += some_variable }
|
278
|
+
task.execute nil
|
279
|
+
task.some_variable.should eql(1)
|
280
|
+
x.should eql(6)
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should build rsync commands" do
|
284
|
+
task = create_example_task
|
285
|
+
task.rsync 'localfile', 'app.example.com:remotefile'
|
286
|
+
task.commands.size.should eql(1)
|
287
|
+
task.commands.first.should eql(%w[rsync -azP --delete localfile app.example.com:remotefile])
|
288
|
+
end
|
289
|
+
|
290
|
+
it "should error when an rsync command fails" do
|
291
|
+
task = create_example_task
|
292
|
+
task.action = lambda { false }
|
293
|
+
lambda { task.rsync 'local', 'app.example.com:remote' }.should raise_error(Rake::RemoteTask::CommandFailedError,
|
294
|
+
"execution failed: rsync -azP --delete local app.example.com:remote")
|
295
|
+
end
|
296
|
+
|
297
|
+
it "should build get commands" do
|
298
|
+
task = create_example_task
|
299
|
+
task.target_host = 'app.example.com'
|
300
|
+
lambda { task.get('tmp', 'remote1', 'remote2') }.should_not raise_error
|
301
|
+
task.commands.size.should eql(1)
|
302
|
+
task.commands.first.should eql(%w[rsync -azP --delete app.example.com:remote1 app.example.com:remote2 tmp])
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should build put commands" do
|
306
|
+
task = create_example_task
|
307
|
+
task.target_host = 'app.example.com'
|
308
|
+
lambda { task.put('dest') { 'whatever' } }.should_not raise_error
|
309
|
+
task.commands.size.should eql(1)
|
310
|
+
task.commands.first[3] = 'some_temp_file_name'
|
311
|
+
task.commands.first.should eql( %w[rsync -azP --delete some_temp_file_name app.example.com:dest])
|
312
|
+
end
|
313
|
+
|
314
|
+
it "should run remote commands" do
|
315
|
+
task = create_example_task
|
316
|
+
task.output << "file1\nfile2\n"
|
317
|
+
task.target_host = "app.example.com"
|
318
|
+
result = nil
|
319
|
+
|
320
|
+
out, err = capture_output do
|
321
|
+
result = task.run("ls")
|
322
|
+
end
|
323
|
+
|
324
|
+
task.commands.size.should eql(1)
|
325
|
+
task.commands.first.should eql(["ssh", "app.example.com", "ls"])
|
326
|
+
|
327
|
+
result.should eql("file1\nfile2\n")
|
328
|
+
out.read.should eql("file1\nfile2\n")
|
329
|
+
err.read.should eql('')
|
330
|
+
end
|
331
|
+
|
332
|
+
it "should error when a remote command fails" do
|
333
|
+
set_example_hosts
|
334
|
+
task = create_example_task
|
335
|
+
task.input = StringIO.new "file1\nfile2\n"
|
336
|
+
task.target_host = 'app.example.com'
|
337
|
+
task.action = lambda { 1 }
|
338
|
+
lambda { task.run("ls") }.should raise_error(Rake::RemoteTask::CommandFailedError,
|
339
|
+
"execution failed with status 1: ssh app.example.com ls")
|
340
|
+
task.commands.size.should eql(1)
|
341
|
+
end
|
342
|
+
|
343
|
+
it "should build remote sudo commands" do
|
344
|
+
task = create_example_task
|
345
|
+
task.target_host = "app.example.com"
|
346
|
+
task.sudo "ls"
|
347
|
+
task.commands.size.should eql(1)
|
348
|
+
task.commands.first.should eql(["ssh", "app.example.com", "sudo -p Password: ls"])
|
349
|
+
end
|
350
|
+
|
351
|
+
it "should run remote sudo commands" do
|
352
|
+
task = create_example_task
|
353
|
+
task.output << "file1\nfile2\n"
|
354
|
+
task.error << 'Password:'
|
355
|
+
task.target_host = "app.example.com"
|
356
|
+
def task.sudo_password() "my password" end # gets defined by set
|
357
|
+
result = nil
|
358
|
+
|
359
|
+
out, err = capture_output do
|
360
|
+
result = task.run("sudo ls")
|
361
|
+
end
|
362
|
+
|
363
|
+
task.commands.size.should eql(1)
|
364
|
+
task.commands.first.should eql(['ssh', 'app.example.com', 'sudo ls'])
|
365
|
+
task.input.string.should eql("my password\n")
|
366
|
+
|
367
|
+
# WARN: Technically incorrect, the password line should be
|
368
|
+
# first... this is an artifact of changes to the IO code in run
|
369
|
+
# and the fact that we have a very simplistic (non-blocking)
|
370
|
+
# testing model.
|
371
|
+
result.should eql("file1\nfile2\nPassword:\n")
|
372
|
+
out.read.should eql("file1\nfile2\n")
|
373
|
+
err.read.should eql("Password:\n")
|
374
|
+
end
|
375
|
+
|
376
|
+
it "should get an options hash for a single option" do
|
377
|
+
set :my_option, 10
|
378
|
+
options = Rake::RemoteTask.get_options_hash(:my_option)
|
379
|
+
options.should ==({ :my_option => 10 })
|
380
|
+
end
|
381
|
+
|
382
|
+
it "should get an options hash for multiple options" do
|
383
|
+
set :my_option, 10
|
384
|
+
set :my_other_option, 'my other option value'
|
385
|
+
options = Rake::RemoteTask.get_options_hash(:my_option, :my_other_option)
|
386
|
+
options.should ==({ :my_option => 10, :my_other_option => 'my other option value' })
|
387
|
+
end
|
388
|
+
|
389
|
+
it "should an empty options hash for an undefined option" do
|
390
|
+
options = Rake::RemoteTask.get_options_hash(:my_undefined_option)
|
391
|
+
options.should ==({})
|
392
|
+
end
|
393
|
+
|
394
|
+
end
|