rubber 1.11.0 → 1.12.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/CHANGELOG +20 -0
- data/VERSION +1 -1
- data/generators/vulcanize/templates/passenger/config/rubber/deploy-passenger.rb +7 -1
- data/lib/generators/vulcanize/templates/passenger/config/rubber/deploy-passenger.rb +7 -1
- data/lib/rubber.rb +1 -0
- data/lib/rubber/instance.rb +25 -6
- data/lib/rubber/recipes/rubber.rb +5 -2
- data/lib/rubber/recipes/rubber/instances.rb +148 -62
- data/lib/rubber/thread_safe_proxy.rb +21 -0
- data/lib/rubber/util.rb +16 -0
- data/test/instance_test.rb +42 -0
- metadata +4 -30
data/CHANGELOG
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
1.11.0
|
2
|
+
-----
|
3
|
+
|
4
|
+
Regenerate gemspec for version 1.11.0 <1358116> [Kevin Menard]
|
5
|
+
We've been using RVM for a while now, so time to kill that warning message. <1d29137> [Kevin Menard]
|
6
|
+
Make the generated Rakefile play nicer with bundler and rubber transformation. <90f6702> [Kevin Menard]
|
7
|
+
Truly make the DBPASS field optional. <ba0aa56> [Kevin Menard]
|
8
|
+
Allow creation of LVM volumes over ephemeral devices. <319e80b> [Kevin Menard]
|
9
|
+
Bumped passenger version. <d4b4950> [Kevin Menard]
|
10
|
+
add detach volume <9daa912> [Matt Conway]
|
11
|
+
fix passing of passwd to mysqldump <143d467> [Matt Conway]
|
12
|
+
Added new feature to lock down the version of RubyGems installed on a cluster by RVM. <652f908> [Kevin Menard]
|
13
|
+
Bumped the version of RVM so we can get the latest security fix releases of Ruby. <9fb2383> [Kevin Menard]
|
14
|
+
Merge branch 'master' of github.com:wr0ngway/rubber <58d3209> [Kevin Menard]
|
15
|
+
Upgraded redis to 2.2.1. <aa0aa31> [Kevin Menard]
|
16
|
+
Bumped Passenger to version 3.0.3. <cad658a> [Kevin Menard]
|
17
|
+
sphinx default port has changed to 9312 <eee2bd0> [Nick Plante]
|
18
|
+
Merge branch 'master' of https://github.com/wr0ngway/rubber <2ff0188> [Nick Plante]
|
19
|
+
fix file write for db restoration <15fe2e0> [Nick Plante]
|
20
|
+
|
1
21
|
1.10.2
|
2
22
|
-----
|
3
23
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.12.0
|
@@ -9,8 +9,14 @@ namespace :rubber do
|
|
9
9
|
|
10
10
|
task :custom_install, :roles => :passenger do
|
11
11
|
rubber.sudo_script 'install_passenger', <<-ENDSCRIPT
|
12
|
-
|
12
|
+
# can't use passenger_lib from rubber here as it only evaluates correctly
|
13
|
+
# when variable interpolation of rvm_gem_home is run remotely, and since we
|
14
|
+
# are in cap, we run the interpolation locally
|
15
|
+
#
|
16
|
+
passenger_lib=$(find /usr/local/rvm -path "*/passenger-#{rubber_env.passenger_version}/*/mod_passenger.so" 2> /dev/null)
|
17
|
+
if [[ -z $passenger_lib ]]; then
|
13
18
|
echo -en "\n\n\n\n" | passenger-install-apache2-module
|
19
|
+
rvm #{rubber_env.rvm_ruby} --passenger
|
14
20
|
fi
|
15
21
|
ENDSCRIPT
|
16
22
|
end
|
@@ -9,8 +9,14 @@ namespace :rubber do
|
|
9
9
|
|
10
10
|
task :custom_install, :roles => :passenger do
|
11
11
|
rubber.sudo_script 'install_passenger', <<-ENDSCRIPT
|
12
|
-
|
12
|
+
# can't use passenger_lib from rubber here as it only evaluates correctly
|
13
|
+
# when variable interpolation of rvm_gem_home is run remotely, and since we
|
14
|
+
# are in cap, we run the interpolation locally
|
15
|
+
#
|
16
|
+
passenger_lib=$(find /usr/local/rvm -path "*/passenger-#{rubber_env.passenger_version}/*/mod_passenger.so" 2> /dev/null)
|
17
|
+
if [[ -z $passenger_lib ]]; then
|
13
18
|
echo -en "\n\n\n\n" | passenger-install-apache2-module
|
19
|
+
rvm #{rubber_env.rvm_ruby} --passenger
|
14
20
|
fi
|
15
21
|
ENDSCRIPT
|
16
22
|
end
|
data/lib/rubber.rb
CHANGED
data/lib/rubber/instance.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'yaml'
|
2
|
+
require 'monitor'
|
2
3
|
|
3
4
|
module Rubber
|
4
5
|
module Configuration
|
@@ -8,18 +9,20 @@ module Rubber
|
|
8
9
|
class Instance
|
9
10
|
attr_reader :file, :artifacts
|
10
11
|
include Enumerable
|
12
|
+
include MonitorMixin
|
11
13
|
|
12
14
|
def initialize(file)
|
15
|
+
super
|
13
16
|
Rubber.logger.debug{"Reading rubber instances from #{file}"}
|
14
17
|
@file = file
|
15
18
|
@items = {}
|
16
19
|
@artifacts = {'volumes' => {}, 'static_ips' => {}}
|
17
20
|
|
18
|
-
@filters = ENV['FILTER']
|
21
|
+
@filters = Rubber::Util::parse_aliases(ENV['FILTER'])
|
19
22
|
@filters, @filters_negated = @filters.partition {|f| f !~ /^-/ }
|
20
23
|
@filters_negated = @filters_negated.collect {|f| f[1..-1] }
|
21
24
|
|
22
|
-
@filter_roles = ENV['FILTER_ROLES']
|
25
|
+
@filter_roles = Rubber::Util::parse_aliases(ENV['FILTER_ROLES'])
|
23
26
|
@filter_roles, @filter_roles_negated = @filter_roles.partition {|f| f !~ /^-/ }
|
24
27
|
@filter_roles_negated = @filter_roles_negated.collect {|f| f[1..-1] }
|
25
28
|
|
@@ -38,10 +41,12 @@ module Rubber
|
|
38
41
|
end
|
39
42
|
|
40
43
|
def save()
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
44
|
+
synchronize do
|
45
|
+
data = []
|
46
|
+
data.push(*@items.values)
|
47
|
+
data.push(@artifacts)
|
48
|
+
File.open(@file, "w") { |f| f.write(YAML.dump(data)) }
|
49
|
+
end
|
45
50
|
end
|
46
51
|
|
47
52
|
def [](name)
|
@@ -57,6 +62,8 @@ module Rubber
|
|
57
62
|
def filtered()
|
58
63
|
filtered_results = []
|
59
64
|
|
65
|
+
validate_filters()
|
66
|
+
|
60
67
|
if @filters.size == 0 && @filter_roles.size == 0
|
61
68
|
filtered_results.concat(@items.values)
|
62
69
|
else
|
@@ -72,6 +79,18 @@ module Rubber
|
|
72
79
|
return filtered_results
|
73
80
|
end
|
74
81
|
|
82
|
+
def validate_filters()
|
83
|
+
aliases = @items.values.collect{|ic| ic.name}
|
84
|
+
[@filters, @filters_negated].flatten.each do |f|
|
85
|
+
raise "Filter doesn't match any hosts: #{f}" if ! aliases.include?(f)
|
86
|
+
end
|
87
|
+
|
88
|
+
roles = all_roles
|
89
|
+
[@filter_roles, @filter_roles_negated].flatten.each do |f|
|
90
|
+
raise "Filter doesn't match any roles: #{f}" if ! roles.include?(f)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
75
94
|
def all_roles()
|
76
95
|
@items.collect {|n, i| i.role_names}.flatten.uniq
|
77
96
|
end
|
@@ -53,9 +53,12 @@ namespace :rubber do
|
|
53
53
|
# Disable connecting to any Windows instance.
|
54
54
|
# pass -l to bash in :shell to that run also gets full env
|
55
55
|
# use a pty so we don't get "stdin: is not a tty" error output
|
56
|
-
|
56
|
+
default_run_options[:pty] = true
|
57
|
+
default_run_options[:shell] = "/bin/bash -l"
|
58
|
+
default_run_options[:except] = { :platform => 'windows' }
|
57
59
|
|
58
|
-
|
60
|
+
# sharing a Net::HTTP instance across threads doesn't work, so create a new instance per thread
|
61
|
+
set :cloud, Rubber::ThreadSafeProxy.new { Rubber::Cloud::get_provider(rubber_env.cloud_provider || "aws", rubber_env, self) }
|
59
62
|
|
60
63
|
load_roles() unless rubber_env.disable_auto_roles
|
61
64
|
# NOTE: for some reason Capistrano requires you to have both the public and
|
@@ -4,13 +4,21 @@ namespace :rubber do
|
|
4
4
|
Create a new EC2 instance with the given ALIAS and ROLES
|
5
5
|
DESC
|
6
6
|
required_task :create do
|
7
|
-
|
7
|
+
instance_aliases = get_env('ALIAS', "Instance alias (e.g. web01 or web01~web05,web09)", true)
|
8
|
+
|
9
|
+
aliases = Rubber::Util::parse_aliases(instance_aliases)
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
if aliases.size > 1
|
12
|
+
default_roles = "roles for instance in *.yml"
|
13
|
+
r = get_env("ROLES", "Instance roles (e.g. web,app,db:primary=true)", false, default_roles)
|
14
|
+
r = "" if r == default_roles
|
15
|
+
else
|
16
|
+
env = rubber_cfg.environment.bind(nil, aliases.first)
|
17
|
+
default_roles = env.instance_roles
|
18
|
+
r = get_env("ROLES", "Instance roles (e.g. web,app,db:primary=true)", true, default_roles)
|
19
|
+
end
|
12
20
|
|
13
|
-
create_spot_instance = ENV.delete("SPOT_INSTANCE")
|
21
|
+
create_spot_instance = ENV.delete("SPOT_INSTANCE")
|
14
22
|
|
15
23
|
if r == '*'
|
16
24
|
instance_roles = rubber_cfg.environment.known_roles
|
@@ -18,24 +26,8 @@ namespace :rubber do
|
|
18
26
|
else
|
19
27
|
instance_roles = r.split(",")
|
20
28
|
end
|
21
|
-
|
22
|
-
|
23
|
-
instance_roles.each do |r|
|
24
|
-
role = Rubber::Configuration::RoleItem.parse(r)
|
25
|
-
|
26
|
-
# If user doesn't setup a primary db, then be nice and do it
|
27
|
-
if role.name == "db" && role.options["primary"] == nil && rubber_instances.for_role("db").size == 0
|
28
|
-
value = Capistrano::CLI.ui.ask("You do not have a primary db role, should #{instance_alias} be it [y/n]?: ")
|
29
|
-
role.options["primary"] = true if value =~ /^y/
|
30
|
-
end
|
31
|
-
|
32
|
-
ir << role
|
33
|
-
end
|
34
|
-
|
35
|
-
# Add in roles that the given set of roles depends on
|
36
|
-
ir = Rubber::Configuration::RoleItem.expand_role_dependencies(ir, get_role_dependencies)
|
37
|
-
|
38
|
-
create_instance(instance_alias, ir, create_spot_instance)
|
29
|
+
|
30
|
+
create_instances(aliases, instance_roles, create_spot_instance)
|
39
31
|
end
|
40
32
|
|
41
33
|
desc <<-DESC
|
@@ -43,18 +35,25 @@ namespace :rubber do
|
|
43
35
|
This is useful to run when rubber:create fails after instance creation
|
44
36
|
DESC
|
45
37
|
required_task :refresh do
|
46
|
-
|
38
|
+
instance_aliases = get_env('ALIAS', "Instance alias (e.g. web01 or web01~web05,web09)", true)
|
39
|
+
|
40
|
+
aliases = Rubber::Util::parse_aliases(instance_aliases)
|
41
|
+
|
47
42
|
ENV.delete('ROLES') # so we don't get an error if people leave ROLES in env from :create CLI
|
48
|
-
|
43
|
+
|
44
|
+
refresh_instances(aliases)
|
49
45
|
end
|
50
46
|
|
51
47
|
desc <<-DESC
|
52
48
|
Destroy the EC2 instance for the given ALIAS
|
53
49
|
DESC
|
54
50
|
required_task :destroy do
|
55
|
-
|
51
|
+
instance_aliases = get_env('ALIAS', "Instance alias (e.g. web01 or web01~web05,web09)", true)
|
52
|
+
|
53
|
+
aliases = Rubber::Util::parse_aliases(instance_aliases)
|
54
|
+
|
56
55
|
ENV.delete('ROLES') # so we don't get an error if people leave ROLES in env from :create CLI
|
57
|
-
|
56
|
+
destroy_instances(aliases, ENV['FORCE'] == 'true')
|
58
57
|
end
|
59
58
|
|
60
59
|
desc <<-DESC
|
@@ -178,25 +177,88 @@ namespace :rubber do
|
|
178
177
|
results.each {|r| logger.info r}
|
179
178
|
end
|
180
179
|
|
181
|
-
|
182
180
|
set :print_ip_command, "ifconfig eth0 | awk 'NR==2 {print $2}' | awk -F: '{print $2}'"
|
183
181
|
|
182
|
+
# Creates the set of new instancea after figuring out the roles for each
|
183
|
+
def create_instances(instance_aliases, instance_roles, create_spot_instance=false)
|
184
|
+
creation_threads = []
|
185
|
+
refresh_threads = []
|
186
|
+
|
187
|
+
instance_aliases.each do |instance_alias|
|
188
|
+
fatal "Instance already exists: #{instance_alias}" if rubber_instances[instance_alias]
|
189
|
+
|
190
|
+
ir = []
|
191
|
+
|
192
|
+
roles = instance_roles
|
193
|
+
if roles.size == 0
|
194
|
+
env = rubber_cfg.environment.bind(nil, instance_alias)
|
195
|
+
roles = env.instance_roles.split(",") rescue []
|
196
|
+
end
|
197
|
+
|
198
|
+
roles.each do |r|
|
199
|
+
role = Rubber::Configuration::RoleItem.parse(r)
|
200
|
+
|
201
|
+
# If user doesn't setup a primary db, then be nice and do it
|
202
|
+
if role.name == "db" && role.options["primary"] == nil && rubber_instances.for_role("db").size == 0
|
203
|
+
value = Capistrano::CLI.ui.ask("You do not have a primary db role, should #{instance_alias} be it [y/n]?: ")
|
204
|
+
role.options["primary"] = true if value =~ /^y/
|
205
|
+
end
|
206
|
+
|
207
|
+
ir << role
|
208
|
+
end
|
209
|
+
|
210
|
+
# Add in roles that the given set of roles depends on
|
211
|
+
ir = Rubber::Configuration::RoleItem.expand_role_dependencies(ir, get_role_dependencies)
|
212
|
+
|
213
|
+
creation_threads << Thread.new do
|
214
|
+
create_instance(instance_alias, ir, create_spot_instance)
|
215
|
+
|
216
|
+
refresh_threads << Thread.new do
|
217
|
+
while ! refresh_instance(instance_alias)
|
218
|
+
sleep 1
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
sleep 2
|
224
|
+
end
|
225
|
+
|
226
|
+
creation_threads.each {|t| t.join }
|
227
|
+
|
228
|
+
print "Waiting for instances to start"
|
229
|
+
|
230
|
+
while true do
|
231
|
+
print "."
|
232
|
+
sleep 2
|
233
|
+
|
234
|
+
break if refresh_threads.all? {|t| ! t.alive? }
|
235
|
+
end
|
236
|
+
|
237
|
+
refresh_threads.each {|t| t.join }
|
238
|
+
|
239
|
+
post_refresh
|
240
|
+
end
|
241
|
+
|
242
|
+
set :mutex, Mutex.new
|
243
|
+
|
184
244
|
# Creates a new ec2 instance with the given alias and roles
|
185
245
|
# Configures aliases (/etc/hosts) on local and remote machines
|
186
|
-
def create_instance(instance_alias, instance_roles, create_spot_instance
|
187
|
-
fatal "Instance already exists: #{instance_alias}" if rubber_instances[instance_alias]
|
188
|
-
|
246
|
+
def create_instance(instance_alias, instance_roles, create_spot_instance)
|
189
247
|
role_names = instance_roles.collect{|x| x.name}
|
190
248
|
env = rubber_cfg.environment.bind(role_names, instance_alias)
|
191
249
|
|
192
250
|
# We need to use security_groups during create, so create them up front
|
193
|
-
|
251
|
+
mutex.synchronize do
|
252
|
+
setup_security_groups(instance_alias, role_names)
|
253
|
+
end
|
194
254
|
security_groups = get_assigned_security_groups(instance_alias, role_names)
|
195
255
|
|
196
256
|
ami = env.cloud_providers[env.cloud_provider].image_id
|
197
257
|
ami_type = env.cloud_providers[env.cloud_provider].image_type
|
198
258
|
availability_zone = env.availability_zone
|
199
259
|
|
260
|
+
create_spot_instance ||= env.cloud_providers[env.cloud_provider].spot_instance
|
261
|
+
|
200
262
|
if create_spot_instance
|
201
263
|
spot_price = env.cloud_providers[env.cloud_provider].spot_price.to_s
|
202
264
|
|
@@ -231,7 +293,7 @@ namespace :rubber do
|
|
231
293
|
instance_id = cloud.create_instance(ami, ami_type, security_groups, availability_zone)
|
232
294
|
end
|
233
295
|
|
234
|
-
logger.info "Instance #{
|
296
|
+
logger.info "Instance #{instance_alias} created: #{instance_id}"
|
235
297
|
|
236
298
|
instance_item = Rubber::Configuration::InstanceItem.new(instance_alias, env.domain, instance_roles, instance_id, security_groups)
|
237
299
|
instance_item.spot_instance_request_id = request_id if create_spot_instance
|
@@ -246,14 +308,22 @@ namespace :rubber do
|
|
246
308
|
sleep 0.5
|
247
309
|
retry
|
248
310
|
end
|
311
|
+
end
|
249
312
|
|
250
|
-
|
251
|
-
|
252
|
-
print "."
|
253
|
-
sleep 2
|
313
|
+
def refresh_instances(instance_aliases)
|
314
|
+
refresh_threads = []
|
254
315
|
|
255
|
-
|
316
|
+
instance_aliases.each do |instance_alias|
|
317
|
+
refresh_threads << Thread.new do
|
318
|
+
while ! refresh_instance(instance_alias)
|
319
|
+
sleep 1
|
320
|
+
end
|
321
|
+
end
|
256
322
|
end
|
323
|
+
|
324
|
+
refresh_threads.each {|t| t.join }
|
325
|
+
|
326
|
+
post_refresh
|
257
327
|
end
|
258
328
|
|
259
329
|
# Refreshes a ec2 instance with the given alias
|
@@ -296,46 +366,57 @@ namespace :rubber do
|
|
296
366
|
end
|
297
367
|
end
|
298
368
|
|
299
|
-
|
300
|
-
|
369
|
+
return true
|
370
|
+
end
|
371
|
+
return false
|
372
|
+
end
|
301
373
|
|
302
|
-
|
303
|
-
|
304
|
-
setup_local_aliases
|
374
|
+
def post_refresh
|
375
|
+
env = rubber_cfg.environment.bind(nil, nil)
|
305
376
|
|
306
|
-
|
307
|
-
|
377
|
+
# setup amazon elastic ips if configured to do so
|
378
|
+
setup_static_ips
|
308
379
|
|
309
|
-
|
380
|
+
# Need to setup aliases so ssh doesn't give us errors when we
|
381
|
+
# later try to connect to same ip but using alias
|
382
|
+
setup_local_aliases
|
310
383
|
|
311
|
-
|
312
|
-
|
313
|
-
|
384
|
+
# re-load the roles since we may have just defined new ones
|
385
|
+
load_roles() unless env.disable_auto_roles
|
386
|
+
|
387
|
+
rubber_instances.save()
|
314
388
|
|
315
|
-
|
316
|
-
|
317
|
-
|
389
|
+
# Add the aliases for this instance to all other hosts
|
390
|
+
setup_remote_aliases
|
391
|
+
setup_dns_aliases
|
318
392
|
end
|
319
393
|
|
394
|
+
def destroy_instances(instance_aliases, force=false)
|
395
|
+
instance_aliases.each do |instance_alias|
|
396
|
+
destroy_instance(instance_alias, force)
|
397
|
+
end
|
398
|
+
|
399
|
+
post_destroy
|
400
|
+
end
|
320
401
|
|
321
402
|
# Destroys the given ec2 instance
|
322
|
-
def destroy_instance(instance_alias)
|
403
|
+
def destroy_instance(instance_alias, force=false)
|
323
404
|
instance_item = rubber_instances[instance_alias]
|
324
405
|
fatal "Instance does not exist: #{instance_alias}" if ! instance_item
|
325
406
|
|
326
407
|
env = rubber_cfg.environment.bind(instance_item.role_names, instance_item.name)
|
327
408
|
|
328
|
-
value = Capistrano::CLI.ui.ask("About to DESTROY #{instance_alias} (#{instance_item.instance_id}) in mode #{RUBBER_ENV}. Are you SURE [yes/NO]?: ")
|
329
|
-
fatal("Exiting", 0) if value != "yes"
|
409
|
+
value = Capistrano::CLI.ui.ask("About to DESTROY #{instance_alias} (#{instance_item.instance_id}) in mode #{RUBBER_ENV}. Are you SURE [yes/NO]?: ") unless force
|
410
|
+
fatal("Exiting", 0) if value != "yes" && ! force
|
330
411
|
|
331
412
|
if instance_item.static_ip
|
332
|
-
value = Capistrano::CLI.ui.ask("Instance has a static ip, do you want to release it? [y/N]?: ")
|
333
|
-
destroy_static_ip(instance_item.static_ip) if value =~ /^y/
|
413
|
+
value = Capistrano::CLI.ui.ask("Instance has a static ip, do you want to release it? [y/N]?: ") unless force
|
414
|
+
destroy_static_ip(instance_item.static_ip) if value =~ /^y/ || force
|
334
415
|
end
|
335
416
|
|
336
417
|
if instance_item.volumes
|
337
|
-
value = Capistrano::CLI.ui.ask("Instance has persistent volumes, do you want to destroy them? [y/N]?: ")
|
338
|
-
if value =~ /^y/
|
418
|
+
value = Capistrano::CLI.ui.ask("Instance has persistent volumes, do you want to destroy them? [y/N]?: ") unless force
|
419
|
+
if value =~ /^y/ || force
|
339
420
|
instance_item.volumes.clone.each do |volume_id|
|
340
421
|
destroy_volume(volume_id)
|
341
422
|
end
|
@@ -349,15 +430,20 @@ namespace :rubber do
|
|
349
430
|
rubber_instances.remove(instance_alias)
|
350
431
|
rubber_instances.save()
|
351
432
|
|
433
|
+
destroy_dyndns(instance_item)
|
434
|
+
cleanup_known_hosts(instance_item) unless env.disable_known_hosts_cleanup
|
435
|
+
end
|
436
|
+
|
437
|
+
def post_destroy
|
438
|
+
env = rubber_cfg.environment.bind(nil, nil)
|
439
|
+
|
352
440
|
# re-load the roles since we just removed some and setup_remote_aliases
|
353
441
|
# shouldn't hit removed ones
|
354
442
|
load_roles() unless env.disable_auto_roles
|
355
443
|
|
356
444
|
setup_aliases
|
357
|
-
destroy_dyndns(instance_item)
|
358
|
-
cleanup_known_hosts(instance_item) unless env.disable_known_hosts_cleanup
|
359
445
|
end
|
360
|
-
|
446
|
+
|
361
447
|
# Reboots the given ec2 instance
|
362
448
|
def reboot_instance(instance_alias)
|
363
449
|
instance_item = rubber_instances[instance_alias]
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
module Rubber
|
3
|
+
class ThreadSafeProxy
|
4
|
+
instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }
|
5
|
+
|
6
|
+
def initialize(&block)
|
7
|
+
@target_block = block
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def method_missing(name, *args, &block)
|
13
|
+
target.send(name, *args, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def target
|
17
|
+
Thread.current["thread_safe_proxy_target_#{object_id}"] ||= @target_block.call
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/rubber/util.rb
CHANGED
@@ -24,6 +24,22 @@ module Rubber
|
|
24
24
|
|
25
25
|
end
|
26
26
|
|
27
|
+
def self.parse_aliases(instance_aliases)
|
28
|
+
aliases = []
|
29
|
+
alias_patterns = instance_aliases.to_s.strip.split(/\s*,\s*/)
|
30
|
+
alias_patterns.each do |a|
|
31
|
+
if a =~ /~/
|
32
|
+
range = a.split(/~/)
|
33
|
+
range_items = (range.first..range.last).to_a
|
34
|
+
raise "Invalid range, '#{a}', sequence generated no items" if range_items.size == 0
|
35
|
+
aliases.concat(range_items)
|
36
|
+
else
|
37
|
+
aliases << a
|
38
|
+
end
|
39
|
+
end
|
40
|
+
return aliases
|
41
|
+
end
|
42
|
+
|
27
43
|
# Opens the file for writing by root
|
28
44
|
def self.sudo_open(path, perms, &block)
|
29
45
|
open("|sudo tee #{path} > /dev/null", perms, &block)
|
data/test/instance_test.rb
CHANGED
@@ -51,6 +51,14 @@ class InstanceTest < Test::Unit::TestCase
|
|
51
51
|
setup
|
52
52
|
assert_equal [@i1], @instance.filtered(), 'should not have negated hosts'
|
53
53
|
|
54
|
+
ENV['FILTER'] = 'host1~host3'
|
55
|
+
setup
|
56
|
+
assert_equal [@i1, @i2, @i3], @instance.filtered(), 'should allow range in filter'
|
57
|
+
|
58
|
+
ENV['FILTER'] = '-host1~-host3'
|
59
|
+
setup
|
60
|
+
assert_equal [@i4], @instance.filtered(), 'should allow negative range in filter'
|
61
|
+
|
54
62
|
ENV['FILTER'] = '-host1'
|
55
63
|
ENV['FILTER_ROLES'] = 'role1'
|
56
64
|
setup
|
@@ -70,6 +78,40 @@ class InstanceTest < Test::Unit::TestCase
|
|
70
78
|
ENV['FILTER_ROLES'] = '-role1'
|
71
79
|
setup
|
72
80
|
assert_equal [@i3, @i4], @instance.filtered(), 'should not have negated roles'
|
81
|
+
|
82
|
+
ENV['FILTER_ROLES'] = 'role1~role2'
|
83
|
+
setup
|
84
|
+
assert_equal [@i1, @i2, @i3, @i4], @instance.filtered(), 'should allow range in filter'
|
85
|
+
|
86
|
+
ENV['FILTER_ROLES'] = '-role1~-role2'
|
87
|
+
setup
|
88
|
+
assert_equal [], @instance.filtered(), 'should allow negative range in filter'
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_validate_filters
|
92
|
+
ENV['FILTER'] = "nohost"
|
93
|
+
setup
|
94
|
+
assert_raises do
|
95
|
+
@instance.filtered()
|
96
|
+
end
|
97
|
+
|
98
|
+
ENV['FILTER'] = "-nohost"
|
99
|
+
setup
|
100
|
+
assert_raises do
|
101
|
+
@instance.filtered()
|
102
|
+
end
|
103
|
+
|
104
|
+
ENV['FILTER_ROLES'] = "norole"
|
105
|
+
setup
|
106
|
+
assert_raises do
|
107
|
+
@instance.filtered()
|
108
|
+
end
|
109
|
+
|
110
|
+
ENV['FILTER_ROLES'] = "-norole"
|
111
|
+
setup
|
112
|
+
assert_raises do
|
113
|
+
@instance.filtered()
|
114
|
+
end
|
73
115
|
end
|
74
116
|
|
75
117
|
def test_equality
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 59
|
5
4
|
prerelease:
|
6
|
-
|
7
|
-
- 1
|
8
|
-
- 11
|
9
|
-
- 0
|
10
|
-
version: 1.11.0
|
5
|
+
version: 1.12.0
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Matt Conway
|
@@ -15,7 +10,7 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2011-03-
|
13
|
+
date: 2011-03-18 00:00:00 -04:00
|
19
14
|
default_executable: vulcanize
|
20
15
|
dependencies:
|
21
16
|
- !ruby/object:Gem::Dependency
|
@@ -26,11 +21,6 @@ dependencies:
|
|
26
21
|
requirements:
|
27
22
|
- - ">="
|
28
23
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 31
|
30
|
-
segments:
|
31
|
-
- 2
|
32
|
-
- 4
|
33
|
-
- 0
|
34
24
|
version: 2.4.0
|
35
25
|
type: :runtime
|
36
26
|
version_requirements: *id001
|
@@ -42,11 +32,6 @@ dependencies:
|
|
42
32
|
requirements:
|
43
33
|
- - ">="
|
44
34
|
- !ruby/object:Gem::Version
|
45
|
-
hash: 25
|
46
|
-
segments:
|
47
|
-
- 0
|
48
|
-
- 9
|
49
|
-
- 17
|
50
35
|
version: 0.9.17
|
51
36
|
type: :runtime
|
52
37
|
version_requirements: *id002
|
@@ -58,9 +43,6 @@ dependencies:
|
|
58
43
|
requirements:
|
59
44
|
- - ">="
|
60
45
|
- !ruby/object:Gem::Version
|
61
|
-
hash: 3
|
62
|
-
segments:
|
63
|
-
- 0
|
64
46
|
version: "0"
|
65
47
|
type: :runtime
|
66
48
|
version_requirements: *id003
|
@@ -72,9 +54,6 @@ dependencies:
|
|
72
54
|
requirements:
|
73
55
|
- - ">="
|
74
56
|
- !ruby/object:Gem::Version
|
75
|
-
hash: 3
|
76
|
-
segments:
|
77
|
-
- 0
|
78
57
|
version: "0"
|
79
58
|
type: :runtime
|
80
59
|
version_requirements: *id004
|
@@ -474,6 +453,7 @@ files:
|
|
474
453
|
- lib/rubber/recipes/rubber/volumes.rb
|
475
454
|
- lib/rubber/tag.rb
|
476
455
|
- lib/rubber/tasks/rubber.rb
|
456
|
+
- lib/rubber/thread_safe_proxy.rb
|
477
457
|
- lib/rubber/util.rb
|
478
458
|
- rails/init.rb
|
479
459
|
- test/environment_test.rb
|
@@ -496,23 +476,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
496
476
|
requirements:
|
497
477
|
- - ">="
|
498
478
|
- !ruby/object:Gem::Version
|
499
|
-
hash: 3
|
500
|
-
segments:
|
501
|
-
- 0
|
502
479
|
version: "0"
|
503
480
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
504
481
|
none: false
|
505
482
|
requirements:
|
506
483
|
- - ">="
|
507
484
|
- !ruby/object:Gem::Version
|
508
|
-
hash: 3
|
509
|
-
segments:
|
510
|
-
- 0
|
511
485
|
version: "0"
|
512
486
|
requirements: []
|
513
487
|
|
514
488
|
rubyforge_project: rubber
|
515
|
-
rubygems_version: 1.
|
489
|
+
rubygems_version: 1.6.1
|
516
490
|
signing_key:
|
517
491
|
specification_version: 3
|
518
492
|
summary: A capistrano plugin for managing multi-instance deployments to the cloud (ec2)
|