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 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.11.0
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
- if [[ -z `ls #{rubber_env.passenger_lib} 2> /dev/null` ]]; then
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
- if [[ -z `ls #{rubber_env.passenger_lib} 2> /dev/null` ]]; then
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
@@ -61,6 +61,7 @@ module Rubber
61
61
  end
62
62
 
63
63
 
64
+ require 'rubber/thread_safe_proxy'
64
65
  require 'rubber/configuration'
65
66
  require 'rubber/environment'
66
67
  require 'rubber/generator'
@@ -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'].split(/\s*,\s*/) rescue []
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'].split(/\s*,\s*/) rescue []
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
- data = []
42
- data.push(*@items.values)
43
- data.push(@artifacts)
44
- File.open(@file, "w") { |f| f.write(YAML.dump(data)) }
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
- set :default_run_options, :pty => true, :shell => "/bin/bash -l", :except => { :platform => 'windows' }
56
+ default_run_options[:pty] = true
57
+ default_run_options[:shell] = "/bin/bash -l"
58
+ default_run_options[:except] = { :platform => 'windows' }
57
59
 
58
- set :cloud, Rubber::Cloud::get_provider(rubber_env.cloud_provider || "aws", rubber_env, self)
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
- instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
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
- env = rubber_cfg.environment.bind(nil, instance_alias)
10
- default_roles = env.instance_roles
11
- r = get_env("ROLES", "Instance roles (e.g. web,app,db:primary=true)", true, default_roles)
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") || env.cloud_providers[env.cloud_provider].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
- ir = []
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
- instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
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
- refresh_instance(instance_alias)
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
- instance_alias = get_env('ALIAS', "Instance alias (e.g. web01)", true)
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
- destroy_instance(instance_alias)
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=false)
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
- setup_security_groups(instance_alias, role_names)
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 #{instance_id} created"
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
- print "Waiting for instance to start"
251
- while true do
252
- print "."
253
- sleep 2
313
+ def refresh_instances(instance_aliases)
314
+ refresh_threads = []
254
315
 
255
- break if refresh_instance(instance_alias)
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
- # setup amazon elastic ips if configured to do so
300
- setup_static_ips
369
+ return true
370
+ end
371
+ return false
372
+ end
301
373
 
302
- # Need to setup aliases so ssh doesn't give us errors when we
303
- # later try to connect to same ip but using alias
304
- setup_local_aliases
374
+ def post_refresh
375
+ env = rubber_cfg.environment.bind(nil, nil)
305
376
 
306
- # re-load the roles since we may have just defined new ones
307
- load_roles() unless env.disable_auto_roles
377
+ # setup amazon elastic ips if configured to do so
378
+ setup_static_ips
308
379
 
309
- rubber_instances.save()
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
- # Add the aliases for this instance to all other hosts
312
- setup_remote_aliases
313
- setup_dns_aliases
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
- return true
316
- end
317
- return false
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
@@ -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)
@@ -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
- segments:
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-04 00:00:00 -05:00
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.5.3
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)