rubber 2.4.2 → 2.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 22e517ff32f6b1a5ebb0bbc229d619493e377d1a
4
- data.tar.gz: 117569a34d40c27d17d0f62c587109b4aa32c1e9
3
+ metadata.gz: eea69e220cb373705e078eaa52e02f5e90a170d6
4
+ data.tar.gz: ff4b8c6ed5e32ce6bbbcc40987e11cf675d83af8
5
5
  SHA512:
6
- metadata.gz: 06b55aeb4476092dc3d9d6fab6d7bf8819228a086afed91c2a014970d196ce6970761961d74c3274192d0e0f80df42003f7f4d80eeccedf3d78b2f3cac50fd92
7
- data.tar.gz: e769eecb972f75a414f9bf3b04d670d335fa0822bd8ec2c3eae7578fff8ca5258a0940a3f5d2a46356aae3a6a82a2abb2863d5d5aa353cfa2a4b8c8aa8c641d4
6
+ metadata.gz: 0402e07cef45eb6e2d109161e7fee64fd1cf81375b4be06a804462855b15828a5236b26aabf8f35863a7bfd69f828f40067c134f902e476327a0c3f36213de3a
7
+ data.tar.gz: 57b6878e9a38472c947019b9d8283a773b59bf082ea3529ffa80dfb13fd5cda5a2a3b85dc83fb3c35dc71af93bd81f321099be9431f84085cc11babd835083af
data/CHANGELOG CHANGED
@@ -1,3 +1,12 @@
1
+ 2.5.0 (06/03/2013)
2
+ -----------------
3
+
4
+ New Features:
5
+ ============
6
+
7
+ [core] Added support for using Rubber as a Vagrant provisioner. Now you can run Rubber easily against local VMs.
8
+
9
+
1
10
  2.4.2 (06/01/2013)
2
11
  ------------------
3
12
 
@@ -76,6 +76,11 @@ require 'rubber/util'
76
76
  require 'rubber/cloud'
77
77
  require 'rubber/dns'
78
78
 
79
+ if defined?(::Vagrant)
80
+ require 'rubber/vagrant/plugin'
81
+ end
82
+
83
+
79
84
  if defined?(Rails::Railtie)
80
85
  module Rubber
81
86
  require 'rubber/railtie'
@@ -64,6 +64,10 @@ module Rubber
64
64
  'running'
65
65
  end
66
66
 
67
+ def stopped_state
68
+ 'stopped'
69
+ end
70
+
67
71
  def before_create_instance(instance_alias, role_names)
68
72
  setup_security_groups(instance_alias, role_names)
69
73
  end
@@ -83,7 +87,25 @@ module Rubber
83
87
  Rubber::Tag::update_instance_tags(instance.name)
84
88
  end
85
89
  end
86
-
90
+
91
+ def before_stop_instance(instance)
92
+ capistrano.fatal "Cannot stop spot instances!" if ! instance.spot_instance_request_id.nil?
93
+ capistrano.fatal "Cannot stop instances with instance-store root device!" if (instance.root_device_type != 'ebs')
94
+ end
95
+
96
+ def before_start_instance(instance)
97
+ capistrano.fatal "Cannot start spot instances!" if ! instance.spot_instance_request_id.nil?
98
+ capistrano.fatal "Cannot start instances with instance-store root device!" if (instance.root_device_type != 'ebs')
99
+ end
100
+
101
+ def after_start_instance(instance)
102
+ # Re-starting an instance will almost certainly give it a new set of IPs and DNS entries, so refresh the values.
103
+ capistrano.rubber.refresh_instance(instance.name)
104
+
105
+ # Static IPs, DNS, etc. need to be set up for the started instance.
106
+ capistrano.rubber.post_refresh
107
+ end
108
+
87
109
  def create_image(image_name)
88
110
 
89
111
  # validate all needed config set
@@ -26,6 +26,22 @@ module Rubber
26
26
  setup_security_groups(instance.name, instance.role_names)
27
27
  end
28
28
 
29
+ def before_stop_instance(instance)
30
+ # No-op by default.
31
+ end
32
+
33
+ def after_stop_instance(instance)
34
+ # No-op by default.
35
+ end
36
+
37
+ def before_start_instance(instance)
38
+ # No-op by default.
39
+ end
40
+
41
+ def after_start_instance(instance)
42
+ # No-op by default.
43
+ end
44
+
29
45
  def isolate_prefix
30
46
  "#{env.app_name}_#{Rubber.env}_"
31
47
  end
@@ -48,13 +48,13 @@ module Rubber
48
48
  response = @compute_provider.servers.get(instance_id).reboot()
49
49
  end
50
50
 
51
- def stop_instance(instance_id, force=false)
51
+ def stop_instance(instance, force=false)
52
52
  # Don't force the stop process. I.e., allow the instance to flush its file system operations.
53
- response = @compute_provider.servers.get(instance_id).stop(force)
53
+ response = @compute_provider.servers.get(instance.instance_id).stop(force)
54
54
  end
55
55
 
56
- def start_instance(instance_id)
57
- response = @compute_provider.servers.get(instance_id).start()
56
+ def start_instance(instance)
57
+ response = @compute_provider.servers.get(instance.instance_id).start()
58
58
  end
59
59
 
60
60
  def create_static_ip
@@ -45,7 +45,7 @@ module Rubber
45
45
  # Since there's no API to query for instance details, the best we can do is use what we have in memory from
46
46
  # the :create_instance operation or ask the user for the details again.
47
47
  unless Generic.instances
48
- create_instance(instance_id, nil, nil, nil, nil)
48
+ create_instance(instance_id, nil, nil, nil, nil, nil)
49
49
  end
50
50
 
51
51
  Generic.instances
@@ -0,0 +1,57 @@
1
+ require 'rubber/cloud/generic'
2
+
3
+ module Rubber
4
+ module Cloud
5
+ class Vagrant < Generic
6
+
7
+ def active_state
8
+ 'running'
9
+ end
10
+
11
+ def stopped_state
12
+ 'saved'
13
+ end
14
+
15
+ def before_create_instance(instance_alias, role_names)
16
+ unless ENV.has_key?('RUN_FROM_VAGRANT')
17
+ capistrano.fatal "Since you are using the 'vagrant' provider, you must create instances by running `vagrant up #{instance_alias}`."
18
+ end
19
+ end
20
+
21
+ def describe_instances(instance_id=nil)
22
+ output = `vagrant status #{instance_id}`
23
+
24
+ output =~ /#{instance_id}\s+(\w+)/m
25
+ state = $1
26
+
27
+ if Generic.instances
28
+ Generic.instances.each do |instance|
29
+ if instance[:id] == instance_id
30
+ instance[:state] = state
31
+ end
32
+ end
33
+
34
+ Generic.instances
35
+ else
36
+ instance = {}
37
+ instance[:id] = instance_id
38
+ instance[:state] = state
39
+
40
+ [instance]
41
+ end
42
+ end
43
+
44
+ def destroy_instance(instance_id)
45
+ system("vagrant destroy #{instance_id} --force")
46
+ end
47
+
48
+ def stop_instance(instance, force=false)
49
+ system("vagrant suspend #{instance.instance_id}")
50
+ end
51
+
52
+ def start_instance(instance)
53
+ system("vagrant resume #{instance.instance_id}")
54
+ end
55
+ end
56
+ end
57
+ end
@@ -65,7 +65,8 @@ namespace :rubber do
65
65
  # NOTE: for some reason Capistrano requires you to have both the public and
66
66
  # the private key in the same folder, the public key should have the
67
67
  # extension ".pub".
68
- ssh_options[:keys] = [cloud.env.key_file].flatten
68
+
69
+ ssh_options[:keys] = [ENV['RUBBER_SSH_KEY'] || cloud.env.key_file].flatten.compact
69
70
  ssh_options[:timeout] = fetch(:ssh_timeout, 5)
70
71
  end
71
72
 
@@ -220,7 +220,7 @@ namespace :rubber do
220
220
  value = Capistrano::CLI.ui.ask("You do not have a primary db role, should #{instance_alias} be it [y/n]?: ")
221
221
  roles << "db:primary=true" if value =~ /^y/
222
222
  end
223
-
223
+
224
224
  ir.concat roles.collect {|r| Rubber::Configuration::RoleItem.parse(r) }
225
225
 
226
226
  # Add in roles that the given set of roles depends on
@@ -255,7 +255,7 @@ namespace :rubber do
255
255
  post_refresh
256
256
  end
257
257
 
258
- set :mutex, Mutex.new
258
+ set :monitor, Monitor.new
259
259
 
260
260
  # Creates a new ec2 instance with the given alias and roles
261
261
  # Configures aliases (/etc/hosts) on local and remote machines
@@ -263,7 +263,7 @@ namespace :rubber do
263
263
  role_names = instance_roles.collect{|x| x.name}
264
264
  env = rubber_cfg.environment.bind(role_names, instance_alias)
265
265
 
266
- mutex.synchronize do
266
+ monitor.synchronize do
267
267
  cloud.before_create_instance(instance_alias, role_names)
268
268
  end
269
269
 
@@ -318,7 +318,7 @@ namespace :rubber do
318
318
  rubber_instances.add(instance_item)
319
319
  rubber_instances.save()
320
320
 
321
- mutex.synchronize do
321
+ monitor.synchronize do
322
322
  cloud.after_create_instance(instance_item)
323
323
  end
324
324
  end
@@ -350,7 +350,7 @@ namespace :rubber do
350
350
 
351
351
  instance = cloud.describe_instances(instance_item.instance_id).first
352
352
 
353
- mutex.synchronize do
353
+ monitor.synchronize do
354
354
  cloud.before_refresh_instance(instance_item)
355
355
  end
356
356
 
@@ -386,7 +386,7 @@ namespace :rubber do
386
386
  end
387
387
  end
388
388
 
389
- mutex.synchronize do
389
+ monitor.synchronize do
390
390
  cloud.after_refresh_instance(instance_item)
391
391
  end
392
392
 
@@ -499,11 +499,15 @@ namespace :rubber do
499
499
  instance_item = rubber_instances[instance_alias]
500
500
 
501
501
  fatal "Instance does not exist: #{instance_alias}" if ! instance_item
502
- fatal "Cannot stop spot instances!" if ! instance_item.spot_instance_request_id.nil?
503
- fatal "Cannot stop instances with instance-store root device!" if (instance_item.root_device_type != 'ebs')
504
502
 
505
503
  instance_item
506
504
  end
505
+
506
+ monitor.synchronize do
507
+ instance_items.each do |instance_item|
508
+ cloud.before_stop_instance(instance_item)
509
+ end
510
+ end
507
511
 
508
512
  # Get user confirmation
509
513
  human_instance_list = instance_items.collect{|instance_item| "#{instance_item.name} (#{instance_item.instance_id})"}.join(', ')
@@ -516,13 +520,13 @@ namespace :rubber do
516
520
  stop_threads << Thread.new do
517
521
  env = rubber_cfg.environment.bind(instance_item.role_names, instance_item.name)
518
522
 
519
- cloud.stop_instance(instance_item.instance_id)
523
+ cloud.stop_instance(instance_item)
520
524
 
521
525
  stopped = false
522
526
  while !stopped
523
527
  sleep 1
524
528
  instance = cloud.describe_instances(instance_item.instance_id).first rescue {}
525
- stopped = (instance[:state] == "stopped")
529
+ stopped = (instance[:state] == cloud.stopped_state)
526
530
  end
527
531
  end
528
532
  end
@@ -536,23 +540,33 @@ namespace :rubber do
536
540
  print "\n"
537
541
 
538
542
  stop_threads.each(&:join)
543
+
544
+ monitor.synchronize do
545
+ instance_items.each do |instance_item|
546
+ cloud.after_stop_instance(instance_item)
547
+ end
548
+ end
539
549
  end
540
550
 
541
551
  # Starts the given ec2 instances. Note that this operation only works for instances that use an EBS volume for the root
542
552
  # device, that are not spot instances, and that are already stopped.
543
553
  def start_instances(aliases)
544
554
  start_threads = []
545
- refresh_threads = []
555
+ describe_threads = []
546
556
 
547
557
  instance_items = aliases.collect do |instance_alias|
548
558
  instance_item = rubber_instances[instance_alias]
549
559
 
550
560
  fatal "Instance does not exist: #{instance_alias}" if ! instance_item
551
- fatal "Cannot start spot instances!" if ! instance_item.spot_instance_request_id.nil?
552
- fatal "Cannot start instances with instance-store root device!" if (instance_item.root_device_type != 'ebs')
553
561
 
554
562
  instance_item
555
563
  end
564
+
565
+ monitor.synchronize do
566
+ instance_items.each do |instance_item|
567
+ cloud.before_start_instance(instance_item)
568
+ end
569
+ end
556
570
 
557
571
  # Get user confirmation
558
572
  human_instance_list = instance_items.collect{|instance_item| "#{instance_item.name} (#{instance_item.instance_id})"}.join(', ')
@@ -565,12 +579,14 @@ namespace :rubber do
565
579
  start_threads << Thread.new do
566
580
  env = rubber_cfg.environment.bind(instance_item.role_names, instance_item.name)
567
581
 
568
- cloud.start_instance(instance_item.instance_id)
569
-
570
- # Re-starting an instance will almost certainly give it a new set of IPs and DNS entries, so refresh the values.
571
- refresh_threads << Thread.new do
572
- while ! refresh_instance(instance_item.name)
582
+ cloud.start_instance(instance_item)
583
+
584
+ describe_threads << Thread.new do
585
+ started = false
586
+ while ! started
573
587
  sleep 1
588
+ instance = cloud.describe_instances(instance_item.instance_id).first rescue {}
589
+ started = (instance[:state] == cloud.active_state)
574
590
  end
575
591
  end
576
592
  end
@@ -584,10 +600,13 @@ namespace :rubber do
584
600
  end
585
601
 
586
602
  start_threads.each(&:join)
587
- refresh_threads.each(&:join)
588
-
589
- # Static IPs, DNS, etc. need to be set up for the started instances
590
- post_refresh
603
+ describe_threads.each(&:join)
604
+
605
+ monitor.synchronize do
606
+ instance_items.each do |instance_item|
607
+ cloud.after_start_instance(instance_item)
608
+ end
609
+ end
591
610
  end
592
611
 
593
612
  # delete from ~/.ssh/known_hosts all lines that begin with ec2- or instance_alias
@@ -9,8 +9,8 @@ namespace :rubber do
9
9
  link_bash
10
10
  set_timezone
11
11
  enable_multiverse
12
- install_core_packages
13
12
  upgrade_packages
13
+ install_core_packages
14
14
  install_packages
15
15
  setup_volumes
16
16
  setup_gem_sources
@@ -26,7 +26,7 @@ namespace :rubber do
26
26
  # We special-case the 'ubuntu' user since Amazon doesn't since the Canonical AMIs on EC2 don't set the password for
27
27
  # this account, making any password prompt potentially confusing.
28
28
  orig_password = fetch(:password)
29
- set(:password, initial_ssh_user == 'ubuntu' ? nil : Capistrano::CLI.password_prompt("Password for #{initial_ssh_user} @ #{ip}: "))
29
+ set(:password, initial_ssh_user == 'ubuntu' || ENV.has_key?('RUN_FROM_VAGRANT') ? nil : Capistrano::CLI.password_prompt("Password for #{initial_ssh_user} @ #{ip}: "))
30
30
 
31
31
  task :_allow_root_ssh, :hosts => "#{initial_ssh_user}@#{ip}" do
32
32
  rsudo "mkdir -p /root/.ssh && cp /home/#{initial_ssh_user}/.ssh/authorized_keys /root/.ssh/"
@@ -0,0 +1,32 @@
1
+ module VagrantPlugins
2
+ module Rubber
3
+ class Config < Vagrant.plugin("2", :config)
4
+ attr_accessor :roles, :rubber_env
5
+
6
+ def initialize
7
+ @roles = UNSET_VALUE
8
+ @rubber_env = UNSET_VALUE
9
+ end
10
+
11
+ def finalize!
12
+ @rubber_env = 'vagrant' if @rubber_env == UNSET_VALUE
13
+
14
+ ::Rubber::initialize(Dir.pwd, @rubber_env)
15
+
16
+ @roles = ::Rubber.config['staging_roles'] if @roles == UNSET_VALUE
17
+ end
18
+
19
+ def validate(machine)
20
+ if @rubber_env.nil?
21
+ return { 'rubber' => ['rubber_env must be set to the Rubber environment to use for this cluster'] }
22
+ end
23
+
24
+ if @roles.nil?
25
+ return { 'rubber' => ['roles must be set to a list of roles to use for this machine'] }
26
+ end
27
+
28
+ {}
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,18 @@
1
+ module VagrantPlugins
2
+ module Rubber
3
+ class Plugin < Vagrant.plugin("2")
4
+ name 'rubber'
5
+ description 'Provides support for provisioning your virtual machines with Rubber.'
6
+
7
+ config(:rubber, :provisioner) do
8
+ require File.expand_path('../config', __FILE__)
9
+ Config
10
+ end
11
+
12
+ provisioner(:rubber) do
13
+ require File.expand_path('../provisioner', __FILE__)
14
+ Provisioner
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,59 @@
1
+ module VagrantPlugins
2
+ module Rubber
3
+ class Provisioner < Vagrant.plugin("2", :provisioner)
4
+ attr_reader :ssh_info, :private_ip
5
+
6
+ def configure(root_config)
7
+ root_config.vm.networks.each do |type, info|
8
+ if type == :private_network
9
+ @private_ip = info[:ip]
10
+ end
11
+ end
12
+
13
+ if @private_ip.nil?
14
+ $stderr.puts "Rubber requires a private network address to be configured in your Vagrantfile."
15
+ exit(-1)
16
+ end
17
+ end
18
+
19
+ def provision
20
+ @ssh_info = machine.ssh_info
21
+
22
+ create
23
+ bootstrap && deploy_migrations
24
+ end
25
+
26
+ private
27
+
28
+ def create
29
+ script = <<-ENDSCRIPT
30
+ unset GEM_HOME;
31
+ unset GEM_PATH;
32
+ PATH=#{ENV['PATH'].split(':')[1..-1].join(':')} RUN_FROM_VAGRANT=true RUBBER_ENV=#{config.rubber_env} ALIAS=#{machine.name} ROLES='#{config.roles}' EXTERNAL_IP=#{private_ip} INTERNAL_IP=#{private_ip} RUBBER_SSH_KEY=#{ssh_info[:private_key_path]} bash -c 'bundle exec cap rubber:create -S initial_ssh_user=#{ssh_info[:username]}'
33
+ ENDSCRIPT
34
+
35
+ system(script)
36
+ end
37
+
38
+ def bootstrap
39
+ script = <<-ENDSCRIPT
40
+ unset GEM_HOME;
41
+ unset GEM_PATH;
42
+ PATH=#{ENV['PATH'].split(':')[1..-1].join(':')} RUN_FROM_VAGRANT=true RUBBER_ENV=#{config.rubber_env} RUBBER_SSH_KEY=#{ssh_info[:private_key_path]} FILTER=#{machine.name} bash -c 'bundle exec cap rubber:bootstrap'
43
+ ENDSCRIPT
44
+
45
+ system(script)
46
+ end
47
+
48
+ def deploy_migrations
49
+ script = <<-ENDSCRIPT
50
+ unset GEM_HOME;
51
+ unset GEM_PATH;
52
+ PATH=#{ENV['PATH'].split(':')[1..-1].join(':')} RUN_FROM_VAGRANT=true RUBBER_ENV=#{config.rubber_env} RUBBER_SSH_KEY=#{ssh_info[:private_key_path]} FILTER=#{machine.name} bash -c 'bundle exec cap deploy:migrations'
53
+ ENDSCRIPT
54
+
55
+ system(script)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,3 +1,3 @@
1
1
  module Rubber
2
- VERSION = "2.4.2"
2
+ VERSION = "2.5.0"
3
3
  end
@@ -0,0 +1,7 @@
1
+ cloud_provider: vagrant
2
+
3
+ cloud_providers:
4
+ vagrant:
5
+ # Rubber assumes every cloud provider has configuration. Vagrant really doesn't need anything, but until the core
6
+ # of Rubber handles that, just set a dummy value.
7
+ dummy: true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubber
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.2
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Conway
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-01 00:00:00.000000000 Z
12
+ date: 2013-06-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: capistrano
@@ -215,6 +215,7 @@ files:
215
215
  - lib/rubber/cloud/fog.rb
216
216
  - lib/rubber/cloud/fog_storage.rb
217
217
  - lib/rubber/cloud/generic.rb
218
+ - lib/rubber/cloud/vagrant.rb
218
219
  - lib/rubber/commands/config.rb
219
220
  - lib/rubber/commands/cron.rb
220
221
  - lib/rubber/commands/util.rb
@@ -246,6 +247,9 @@ files:
246
247
  - lib/rubber/tag.rb
247
248
  - lib/rubber/thread_safe_proxy.rb
248
249
  - lib/rubber/util.rb
250
+ - lib/rubber/vagrant/config.rb
251
+ - lib/rubber/vagrant/plugin.rb
252
+ - lib/rubber/vagrant/provisioner.rb
249
253
  - lib/rubber/version.rb
250
254
  - rails/init.rb
251
255
  - rubber.gemspec
@@ -273,6 +277,7 @@ files:
273
277
  - templates/base/config/rubber/deploy-util.rb
274
278
  - templates/base/config/rubber/rubber-dns.yml
275
279
  - templates/base/config/rubber/rubber-ruby.yml
280
+ - templates/base/config/rubber/rubber-vagrant-env.yml
276
281
  - templates/base/config/rubber/rubber.yml
277
282
  - templates/base/script/rubber
278
283
  - templates/base/templates.rb