gabrielg-vlad 1.2.0
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/History.txt +69 -0
- data/Manifest.txt +28 -0
- data/README.txt +77 -0
- data/Rakefile +59 -0
- data/considerations.txt +91 -0
- data/doco/faq.txt +81 -0
- data/doco/getting_started.txt +41 -0
- data/doco/migration.txt +43 -0
- data/doco/perforce.txt +5 -0
- data/doco/variables.txt +78 -0
- data/lib/rake_remote_task.rb +595 -0
- data/lib/vlad.rb +91 -0
- data/lib/vlad/apache.rb +37 -0
- data/lib/vlad/core.rb +181 -0
- data/lib/vlad/git.rb +54 -0
- data/lib/vlad/lighttpd.rb +85 -0
- data/lib/vlad/mercurial.rb +37 -0
- data/lib/vlad/mongrel.rb +61 -0
- data/lib/vlad/perforce.rb +117 -0
- data/lib/vlad/subversion.rb +34 -0
- data/test/test_rake_remote_task.rb +188 -0
- data/test/test_vlad.rb +210 -0
- data/test/test_vlad_git.rb +78 -0
- data/test/test_vlad_mercurial.rb +31 -0
- data/test/test_vlad_perforce.rb +37 -0
- data/test/test_vlad_subversion.rb +27 -0
- data/test/vlad_test_case.rb +75 -0
- data/vladdemo.sh +64 -0
- metadata +136 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
class Vlad::Mercurial
|
2
|
+
|
3
|
+
set :source, Vlad::Mercurial.new
|
4
|
+
|
5
|
+
##
|
6
|
+
# Returns the command that will check out +revision+ from the repository
|
7
|
+
# into directory +destination+
|
8
|
+
|
9
|
+
def checkout(revision, destination)
|
10
|
+
revision = 'tip' if revision =~ /^head$/i
|
11
|
+
|
12
|
+
[ "if [ ! -d #{destination}/.hg ]; then hg init -R #{destination}; fi",
|
13
|
+
"hg pull -r #{revision} -R #{destination} #{repository}"
|
14
|
+
].join(' && ')
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Returns the command that will export +revision+ from the repository into
|
19
|
+
# the directory +destination+.
|
20
|
+
|
21
|
+
def export(revision_or_source, destination)
|
22
|
+
revision_or_source = 'tip' if revision_or_source =~ /^head$/i
|
23
|
+
if revision_or_source =~ /^(\d+|tip)$/i then
|
24
|
+
"hg archive -r #{revision_or_source} -R #{repository} #{destination}"
|
25
|
+
else
|
26
|
+
"hg archive -R #{revision_or_source} #{destination}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Returns a command that maps human-friendly revision identifier +revision+
|
32
|
+
# into a subversion revision specification.
|
33
|
+
|
34
|
+
def revision(revision)
|
35
|
+
"`hg identify -R #{repository} | cut -f1 -d\\ `"
|
36
|
+
end
|
37
|
+
end
|
data/lib/vlad/mongrel.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'vlad'
|
2
|
+
|
3
|
+
namespace :vlad do
|
4
|
+
##
|
5
|
+
# Mongrel app server
|
6
|
+
|
7
|
+
set :mongrel_address, "127.0.0.1"
|
8
|
+
set :mongrel_clean, false
|
9
|
+
set :mongrel_command, 'mongrel_rails'
|
10
|
+
set(:mongrel_conf) { "#{shared_path}/mongrel_cluster.conf" }
|
11
|
+
set :mongrel_config_script, nil
|
12
|
+
set :mongrel_environment, "production"
|
13
|
+
set :mongrel_group, nil
|
14
|
+
set :mongrel_log_file, nil
|
15
|
+
set :mongrel_pid_file, nil
|
16
|
+
set :mongrel_port, 8000
|
17
|
+
set :mongrel_prefix, nil
|
18
|
+
set :mongrel_servers, 2
|
19
|
+
set :mongrel_user, nil
|
20
|
+
|
21
|
+
desc "Prepares application servers for deployment. Mongrel
|
22
|
+
configuration is set via the mongrel_* variables.".cleanup
|
23
|
+
|
24
|
+
remote_task :setup_app, :roles => :app do
|
25
|
+
cmd = [
|
26
|
+
"#{mongrel_command} cluster::configure",
|
27
|
+
"-N #{mongrel_servers}",
|
28
|
+
"-p #{mongrel_port}",
|
29
|
+
"-e #{mongrel_environment}",
|
30
|
+
"-a #{mongrel_address}",
|
31
|
+
"-c #{current_path}",
|
32
|
+
"-C #{mongrel_conf}",
|
33
|
+
("-P #{mongrel_pid_file}" if mongrel_pid_file),
|
34
|
+
("-l #{mongrel_log_file}" if mongrel_log_file),
|
35
|
+
("--user #{mongrel_user}" if mongrel_user),
|
36
|
+
("--group #{mongrel_group}" if mongrel_group),
|
37
|
+
("--prefix #{mongrel_prefix}" if mongrel_prefix),
|
38
|
+
("-S #{mongrel_config_script}" if mongrel_config_script),
|
39
|
+
].compact.join ' '
|
40
|
+
|
41
|
+
run cmd
|
42
|
+
end
|
43
|
+
|
44
|
+
def mongrel(cmd) # :nodoc:
|
45
|
+
cmd = "#{mongrel_command} #{cmd} -C #{mongrel_conf}"
|
46
|
+
cmd << ' --clean' if mongrel_clean
|
47
|
+
cmd
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "Restart the app servers"
|
51
|
+
|
52
|
+
remote_task :start_app, :roles => :app do
|
53
|
+
run mongrel("cluster::restart")
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "Stop the app servers"
|
57
|
+
|
58
|
+
remote_task :stop_app, :roles => :app do
|
59
|
+
run mongrel("cluster::stop")
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
class Vlad::Perforce
|
2
|
+
|
3
|
+
set :p4_cmd, "p4"
|
4
|
+
set :source, Vlad::Perforce.new
|
5
|
+
|
6
|
+
##
|
7
|
+
# Returns the p4 command that will checkout +revision+ into the directory
|
8
|
+
# +destination+.
|
9
|
+
|
10
|
+
def checkout(revision, destination)
|
11
|
+
"#{p4_cmd} sync ...#{rev_no(revision)}"
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Returns the p4 command that will export +revision+ into the directory
|
16
|
+
# +directory+.
|
17
|
+
|
18
|
+
def export(revision_or_source, destination)
|
19
|
+
if revision_or_source =~ /^(\d+|head)$/i then
|
20
|
+
"(cd #{destination} && #{p4_cmd} sync ...#{rev_no(revision_or_source)})"
|
21
|
+
else
|
22
|
+
"cp -r #{revision_or_source} #{destination}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Returns a command that maps human-friendly revision identifier +revision+
|
28
|
+
# into a Perforce revision specification.
|
29
|
+
|
30
|
+
def revision(revision)
|
31
|
+
"`#{p4_cmd} changes -s submitted -m 1 ...#{rev_no(revision)} | cut -f 2 -d\\ `"
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Maps revision +revision+ into a Perforce revision.
|
36
|
+
|
37
|
+
def rev_no(revision)
|
38
|
+
case revision.to_s
|
39
|
+
when /head/i then
|
40
|
+
"#head"
|
41
|
+
when /^\d+$/ then
|
42
|
+
"@#{revision}"
|
43
|
+
else
|
44
|
+
revision
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
namespace :vlad do
|
50
|
+
remote_task :setup_app, :roles => :app do
|
51
|
+
p4data = p4port = p4user = p4passwd = nil
|
52
|
+
|
53
|
+
if ENV['P4CONFIG'] then
|
54
|
+
p4config_name = ENV['P4CONFIG']
|
55
|
+
p4config = nil
|
56
|
+
orig_dir = Dir.pwd.split File::SEPARATOR
|
57
|
+
|
58
|
+
until orig_dir.length == 1 do
|
59
|
+
p4config = orig_dir + [p4config_name]
|
60
|
+
p4config = File.join p4config
|
61
|
+
break if File.exist? p4config
|
62
|
+
orig_dir.pop
|
63
|
+
end
|
64
|
+
|
65
|
+
raise "couldn't find .p4config" unless File.exist? p4config
|
66
|
+
|
67
|
+
p4data = File.readlines(p4config).map { |line| line.strip.split '=', 2 }
|
68
|
+
p4data = Hash[*p4data.flatten]
|
69
|
+
else
|
70
|
+
p4data = ENV
|
71
|
+
end
|
72
|
+
|
73
|
+
p4port = p4data['P4PORT']
|
74
|
+
p4user = p4data['P4USER']
|
75
|
+
p4passwd = p4data['P4PASSWD']
|
76
|
+
|
77
|
+
raise "couldn't get P4PORT" if p4port.nil?
|
78
|
+
raise "couldn't get P4USER" if p4user.nil?
|
79
|
+
raise "couldn't get P4PASSWD" if p4passwd.nil?
|
80
|
+
|
81
|
+
p4client = [p4user, target_host, application].join '-'
|
82
|
+
|
83
|
+
require 'tmpdir'
|
84
|
+
require 'tempfile'
|
85
|
+
|
86
|
+
put File.join(scm_path, '.p4config'), 'vlad.p4config' do
|
87
|
+
[ "P4PORT=#{p4port}",
|
88
|
+
"P4USER=#{p4user}",
|
89
|
+
"P4PASSWD=#{p4passwd}",
|
90
|
+
"P4CLIENT=#{p4client}" ].join("\n")
|
91
|
+
end
|
92
|
+
|
93
|
+
p4client_path = File.join deploy_to, 'p4client.tmp'
|
94
|
+
|
95
|
+
put p4client_path, 'vlad.p4client' do
|
96
|
+
conf = <<-"CLIENT"
|
97
|
+
Client: #{p4client}
|
98
|
+
|
99
|
+
Owner: #{p4user}
|
100
|
+
|
101
|
+
Root: #{scm_path}
|
102
|
+
|
103
|
+
View:
|
104
|
+
#{repository}/... //#{p4client}/...
|
105
|
+
CLIENT
|
106
|
+
end
|
107
|
+
|
108
|
+
cmds = [
|
109
|
+
"cd #{scm_path}",
|
110
|
+
"p4 client -i < #{p4client_path}",
|
111
|
+
"rm #{p4client_path}",
|
112
|
+
]
|
113
|
+
|
114
|
+
run cmds.join(' && ')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Vlad::Subversion
|
2
|
+
|
3
|
+
set :source, Vlad::Subversion.new
|
4
|
+
set :svn_cmd, "svn"
|
5
|
+
|
6
|
+
##
|
7
|
+
# Returns the command that will check out +revision+ from the repository
|
8
|
+
# into directory +destination+
|
9
|
+
|
10
|
+
def checkout(revision, destination)
|
11
|
+
"#{svn_cmd} co -r #{revision} #{repository} #{destination}"
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Returns the command that will export +revision+ from the repository into
|
16
|
+
# the directory +destination+.
|
17
|
+
|
18
|
+
def export(revision_or_source, destination)
|
19
|
+
if revision_or_source =~ /^(\d+|head)$/i then
|
20
|
+
"#{svn_cmd} export -r #{revision_or_source} #{repository} #{destination}"
|
21
|
+
else
|
22
|
+
"#{svn_cmd} export #{revision_or_source} #{destination}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Returns a command that maps human-friendly revision identifier +revision+
|
28
|
+
# into a subversion revision specification.
|
29
|
+
|
30
|
+
def revision(revision)
|
31
|
+
"`#{svn_cmd} info #{repository} | grep 'Revision:' | cut -f2 -d\\ `"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'test/vlad_test_case'
|
2
|
+
require 'vlad'
|
3
|
+
|
4
|
+
class TestRakeRemoteTask < VladTestCase
|
5
|
+
def test_enhance
|
6
|
+
util_set_hosts
|
7
|
+
body = Proc.new { 5 }
|
8
|
+
task = @vlad.remote_task(:some_task => :foo, &body)
|
9
|
+
action = Rake::RemoteTask::Action.new(task, body)
|
10
|
+
assert_equal [action], task.remote_actions
|
11
|
+
assert_equal task, action.task
|
12
|
+
assert_equal ["foo"], task.prerequisites
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_enhance_with_no_task_body
|
16
|
+
util_set_hosts
|
17
|
+
util_setup_task
|
18
|
+
assert_equal [], @task.remote_actions
|
19
|
+
assert_equal [], @task.prerequisites
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_execute
|
23
|
+
util_set_hosts
|
24
|
+
set :some_variable, 1
|
25
|
+
x = 5
|
26
|
+
task = @vlad.remote_task(:some_task) { x += some_variable }
|
27
|
+
task.execute nil
|
28
|
+
assert_equal 1, task.some_variable
|
29
|
+
assert_equal 2, task.remote_actions.first.workers.size
|
30
|
+
assert_equal 7, x
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_execute_exposes_target_host
|
34
|
+
host "app.example.com", :app
|
35
|
+
task = remote_task(:target_task) { set(:test_target_host, target_host) }
|
36
|
+
task.execute nil
|
37
|
+
assert_equal "app.example.com", Rake::RemoteTask.fetch(:test_target_host)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_execute_with_no_hosts
|
41
|
+
@vlad.host "app.example.com", :app
|
42
|
+
t = @vlad.remote_task(:flunk, :roles => :db) { flunk "should not have run" }
|
43
|
+
e = assert_raise(Vlad::ConfigurationError) { t.execute nil }
|
44
|
+
assert_equal "No target hosts specified on task flunk for roles [:db]",
|
45
|
+
e.message
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_execute_with_no_roles
|
49
|
+
t = @vlad.remote_task(:flunk, :roles => :junk) { flunk "should not have run" }
|
50
|
+
e = assert_raise(Vlad::ConfigurationError) { t.execute nil }
|
51
|
+
assert_equal "No target hosts specified on task flunk for roles [:junk]",
|
52
|
+
e.message
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_execute_with_roles
|
56
|
+
util_set_hosts
|
57
|
+
set :some_variable, 1
|
58
|
+
x = 5
|
59
|
+
task = @vlad.remote_task(:some_task, :roles => :db) { x += some_variable }
|
60
|
+
task.execute nil
|
61
|
+
assert_equal 1, task.some_variable
|
62
|
+
assert_equal 6, x
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_rsync
|
66
|
+
util_setup_task
|
67
|
+
@task.target_host = "app.example.com"
|
68
|
+
|
69
|
+
@task.rsync 'localfile', 'remotefile'
|
70
|
+
|
71
|
+
commands = @task.commands
|
72
|
+
|
73
|
+
assert_equal 1, commands.size, 'not enough commands'
|
74
|
+
assert_equal %w[rsync -azP --delete localfile app.example.com:remotefile],
|
75
|
+
commands.first, 'rsync'
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_rsync_fail
|
79
|
+
util_setup_task
|
80
|
+
@task.target_host = "app.example.com"
|
81
|
+
@task.action = lambda { false }
|
82
|
+
|
83
|
+
e = assert_raise(Vlad::CommandFailedError) { @task.rsync 'local', 'remote' }
|
84
|
+
assert_equal "execution failed: rsync -azP --delete local app.example.com:remote", e.message
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_run
|
88
|
+
util_setup_task
|
89
|
+
@task.output << "file1\nfile2\n"
|
90
|
+
@task.target_host = "app.example.com"
|
91
|
+
result = nil
|
92
|
+
|
93
|
+
out, err = util_capture do
|
94
|
+
result = @task.run("ls")
|
95
|
+
end
|
96
|
+
|
97
|
+
commands = @task.commands
|
98
|
+
|
99
|
+
assert_equal 1, commands.size, 'not enough commands'
|
100
|
+
assert_equal ["ssh", "app.example.com", "ls"],
|
101
|
+
commands.first, 'app'
|
102
|
+
assert_equal "file1\nfile2\n", result
|
103
|
+
|
104
|
+
assert_equal "file1\nfile2\n", out.read
|
105
|
+
assert_equal '', err.read
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_run_failing_command
|
109
|
+
util_set_hosts
|
110
|
+
util_setup_task
|
111
|
+
@task.input = StringIO.new "file1\nfile2\n"
|
112
|
+
@task.target_host = 'app.example.com'
|
113
|
+
@task.action = lambda { 1 }
|
114
|
+
|
115
|
+
e = assert_raise(Vlad::CommandFailedError) { @task.run("ls") }
|
116
|
+
assert_equal "execution failed with status 1: ssh app.example.com ls", e.message
|
117
|
+
|
118
|
+
assert_equal 1, @task.commands.size
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_run_sudo
|
122
|
+
util_setup_task
|
123
|
+
@task.output << "file1\nfile2\n"
|
124
|
+
@task.error << 'Password:'
|
125
|
+
@task.target_host = "app.example.com"
|
126
|
+
def @task.sudo_password() "my password" end # gets defined by set
|
127
|
+
result = nil
|
128
|
+
|
129
|
+
out, err = util_capture do
|
130
|
+
result = @task.run("sudo ls")
|
131
|
+
end
|
132
|
+
|
133
|
+
commands = @task.commands
|
134
|
+
|
135
|
+
assert_equal 1, commands.size, 'not enough commands'
|
136
|
+
assert_equal ['ssh', 'app.example.com', 'sudo ls'],
|
137
|
+
commands.first
|
138
|
+
|
139
|
+
assert_equal "my password\n", @task.input.string
|
140
|
+
|
141
|
+
# WARN: Technically incorrect, the password line should be
|
142
|
+
# first... this is an artifact of changes to the IO code in run
|
143
|
+
# and the fact that we have a very simplistic (non-blocking)
|
144
|
+
# testing model.
|
145
|
+
assert_equal "file1\nfile2\nPassword:\n", result
|
146
|
+
|
147
|
+
assert_equal "file1\nfile2\n", out.read
|
148
|
+
assert_equal "Password:\n", err.read
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_sudo
|
152
|
+
util_setup_task
|
153
|
+
@task.target_host = "app.example.com"
|
154
|
+
@task.sudo "ls"
|
155
|
+
|
156
|
+
commands = @task.commands
|
157
|
+
|
158
|
+
assert_equal 1, commands.size, 'wrong number of commands'
|
159
|
+
assert_equal ["ssh", "app.example.com", "sudo ls"],
|
160
|
+
commands.first, 'app'
|
161
|
+
end
|
162
|
+
|
163
|
+
def util_capture
|
164
|
+
require 'stringio'
|
165
|
+
orig_stdout = $stdout.dup
|
166
|
+
orig_stderr = $stderr.dup
|
167
|
+
captured_stdout = StringIO.new
|
168
|
+
captured_stderr = StringIO.new
|
169
|
+
$stdout = captured_stdout
|
170
|
+
$stderr = captured_stderr
|
171
|
+
yield
|
172
|
+
captured_stdout.rewind
|
173
|
+
captured_stderr.rewind
|
174
|
+
return captured_stdout, captured_stderr
|
175
|
+
ensure
|
176
|
+
$stdout = orig_stdout
|
177
|
+
$stderr = orig_stderr
|
178
|
+
end
|
179
|
+
|
180
|
+
def util_setup_task(options = {})
|
181
|
+
@task = @vlad.remote_task :test_task, options
|
182
|
+
@task.commands = []
|
183
|
+
@task.output = []
|
184
|
+
@task.error = []
|
185
|
+
@task.action = nil
|
186
|
+
@task
|
187
|
+
end
|
188
|
+
end
|
data/test/test_vlad.rb
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
require 'test/vlad_test_case'
|
2
|
+
require 'vlad'
|
3
|
+
|
4
|
+
$TESTING = true
|
5
|
+
|
6
|
+
class TestVlad < VladTestCase
|
7
|
+
def test_all_hosts
|
8
|
+
util_set_hosts
|
9
|
+
assert_equal %w[app.example.com db.example.com], @vlad.all_hosts
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_fetch
|
13
|
+
set :foo, 5
|
14
|
+
assert_equal 5, @vlad.fetch(:foo)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_fetch_with_default
|
18
|
+
assert_equal 5, @vlad.fetch(:not_here, 5)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_host
|
22
|
+
@vlad.host "test.example.com", :app, :db
|
23
|
+
expected = {"test.example.com" => {}}
|
24
|
+
assert_equal expected, @vlad.roles[:app]
|
25
|
+
assert_equal expected, @vlad.roles[:db]
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_host_invalid
|
29
|
+
assert_raise(ArgumentError) { @vlad.host nil, :web }
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_host_multiple_hosts
|
33
|
+
@vlad.host "test.example.com", :app, :db
|
34
|
+
@vlad.host "yarr.example.com", :app, :db, :no_release => true
|
35
|
+
|
36
|
+
expected = {
|
37
|
+
"test.example.com" => {},
|
38
|
+
"yarr.example.com" => {:no_release => true}
|
39
|
+
}
|
40
|
+
|
41
|
+
assert_equal expected, @vlad.roles[:app]
|
42
|
+
assert_equal expected, @vlad.roles[:db]
|
43
|
+
assert_not_equal(@vlad.roles[:db]["test.example.com"].object_id,
|
44
|
+
@vlad.roles[:app]["test.example.com"].object_id)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_hosts_for_array_of_roles
|
48
|
+
util_set_hosts
|
49
|
+
assert_equal %w[app.example.com db.example.com], @vlad.hosts_for([:app, :db])
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_hosts_for_one_role
|
53
|
+
util_set_hosts
|
54
|
+
@vlad.host "app2.example.com", :app
|
55
|
+
assert_equal %w[app.example.com app2.example.com], @vlad.hosts_for(:app)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_hosts_for_multiple_roles
|
59
|
+
util_set_hosts
|
60
|
+
assert_equal %w[app.example.com db.example.com], @vlad.hosts_for(:app, :db)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_hosts_for_unique
|
64
|
+
util_set_hosts
|
65
|
+
@vlad.host "app.example.com", :web
|
66
|
+
assert_equal %w[app.example.com db.example.com], @vlad.hosts_for(:app, :db, :web)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_initialize
|
70
|
+
@vlad.set_defaults # ensure these three are virginal
|
71
|
+
assert_raise(Vlad::ConfigurationError) { @vlad.repository }
|
72
|
+
assert_raise(Vlad::ConfigurationError) { @vlad.deploy_to }
|
73
|
+
assert_raise(Vlad::ConfigurationError) { @vlad.domain }
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_role
|
77
|
+
@vlad.role :app, "test.example.com"
|
78
|
+
expected = {"test.example.com" => {}}
|
79
|
+
assert_equal expected, @vlad.roles[:app]
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_role_multiple_hosts
|
83
|
+
@vlad.role :app, "test.example.com"
|
84
|
+
@vlad.role :app, "yarr.example.com", :no_release => true
|
85
|
+
expected = {
|
86
|
+
"test.example.com" => {},
|
87
|
+
"yarr.example.com" => {:no_release => true}
|
88
|
+
}
|
89
|
+
assert_equal expected, @vlad.roles[:app]
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_role_multiple_roles
|
93
|
+
@vlad.role :app, "test.example.com", :primary => true
|
94
|
+
@vlad.role :db, "yarr.example.com", :no_release => true
|
95
|
+
expected_db = { "yarr.example.com" => {:no_release => true} }
|
96
|
+
assert_equal expected_db, @vlad.roles[:db]
|
97
|
+
expected_app = { "test.example.com" => {:primary => true} }
|
98
|
+
assert_equal expected_app, @vlad.roles[:app]
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_remote_task
|
102
|
+
t = @vlad.remote_task(:test_task) { 5 }
|
103
|
+
assert_equal @task_count + 1, Rake.application.tasks.size
|
104
|
+
assert_equal({ :roles => [] }, t.options)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_remote_task_all_hosts_by_default
|
108
|
+
util_set_hosts
|
109
|
+
t = @vlad.remote_task(:test_task) { 5 }
|
110
|
+
assert_equal %w[app.example.com db.example.com], t.target_hosts
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_remote_task_environment_override
|
114
|
+
old_env_hosts = ENV["HOSTS"]
|
115
|
+
ENV["HOSTS"] = 'other1.example.com, other2.example.com'
|
116
|
+
util_set_hosts
|
117
|
+
t = @vlad.remote_task(:test_task) { 5 }
|
118
|
+
assert_equal %w[other1.example.com other2.example.com], t.target_hosts
|
119
|
+
ensure
|
120
|
+
ENV["HOSTS"] = old_env_hosts
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_remote_task_body_set
|
124
|
+
set(:some_variable, 5)
|
125
|
+
@vlad.host 'www.example.com', :app
|
126
|
+
@vlad.remote_task(:some_task) do $some_task_result = some_variable end
|
127
|
+
|
128
|
+
Rake::Task['some_task'].execute nil
|
129
|
+
assert_equal @vlad.fetch(:some_variable), $some_task_result
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_remote_task_with_options
|
133
|
+
t = @vlad.remote_task :test_task, :roles => [:app, :db] do
|
134
|
+
fail "should not run"
|
135
|
+
end
|
136
|
+
assert_equal({:roles => [:app, :db]}, t.options)
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_remote_task_before_host_declaration
|
140
|
+
t = @vlad.remote_task :test_task, :roles => :web do 5 end
|
141
|
+
@vlad.host 'www.example.com', :web
|
142
|
+
assert_equal %w[www.example.com], t.target_hosts
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_remote_task_role_override
|
146
|
+
host "db1", :db
|
147
|
+
host "db2", :db
|
148
|
+
host "db3", :db
|
149
|
+
host "master", :master_db
|
150
|
+
|
151
|
+
remote_task(:migrate_the_db, :roles => [:db]) { flunk "bad!" }
|
152
|
+
task = Rake::Task["migrate_the_db"]
|
153
|
+
assert_equal %w[db1 db2 db3], task.target_hosts
|
154
|
+
|
155
|
+
task.options[:roles] = :master_db
|
156
|
+
assert_equal %w[master], task.target_hosts
|
157
|
+
|
158
|
+
task.options[:roles] = [:master_db]
|
159
|
+
assert_equal %w[master], task.target_hosts
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_set
|
163
|
+
set :test, 5
|
164
|
+
assert_equal 5, @vlad.test
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_set_lazy_block_evaluation
|
168
|
+
set(:test) { fail "lose" }
|
169
|
+
assert_raise(RuntimeError) { @vlad.test }
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_set_with_block
|
173
|
+
x = 1
|
174
|
+
set(:test) { x += 2 }
|
175
|
+
|
176
|
+
assert_equal 3, @vlad.test
|
177
|
+
assert_equal 3, @vlad.test
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_set_with_reference
|
181
|
+
@vlad.instance_eval do
|
182
|
+
set(:var_one) { var_two }
|
183
|
+
set(:var_two) { var_three }
|
184
|
+
set(:var_three) { 5 }
|
185
|
+
end
|
186
|
+
|
187
|
+
assert_equal 5, @vlad.var_one
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_set_with_block_and_value
|
191
|
+
e = assert_raise(ArgumentError) do
|
192
|
+
set(:test, 5) { 6 }
|
193
|
+
end
|
194
|
+
assert_equal "cannot provide both a value and a block", e.message
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_set_with_nil
|
198
|
+
set(:test, nil)
|
199
|
+
assert_equal nil, @vlad.test
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_set_with_reserved_name
|
203
|
+
$TESTING = false
|
204
|
+
e = assert_raise(ArgumentError) { set(:all_hosts, []) }
|
205
|
+
assert_equal "cannot set reserved name: 'all_hosts'", e.message
|
206
|
+
ensure
|
207
|
+
$TESTING = true
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|