rubber 1.11.0 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
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)