vagrant-digitalocean 0.0.4 → 0.1.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.
Files changed (55) hide show
  1. data/.gitignore +1 -1
  2. data/Gemfile +1 -4
  3. data/LICENSE.txt +2 -1
  4. data/README.md +114 -96
  5. data/Rakefile +8 -10
  6. data/box/digital_ocean.box +0 -0
  7. data/lib/vagrant-digitalocean.rb +12 -4
  8. data/lib/vagrant-digitalocean/actions.rb +159 -0
  9. data/lib/vagrant-digitalocean/actions/check_state.rb +19 -0
  10. data/lib/vagrant-digitalocean/actions/create.rb +36 -21
  11. data/lib/vagrant-digitalocean/actions/destroy.rb +10 -8
  12. data/lib/vagrant-digitalocean/actions/modify_provision_path.rb +15 -17
  13. data/lib/vagrant-digitalocean/actions/power_off.rb +33 -0
  14. data/lib/vagrant-digitalocean/actions/power_on.rb +34 -0
  15. data/lib/vagrant-digitalocean/actions/rebuild.rb +9 -9
  16. data/lib/vagrant-digitalocean/actions/reload.rb +31 -0
  17. data/lib/vagrant-digitalocean/actions/setup_key.rb +56 -0
  18. data/lib/vagrant-digitalocean/actions/setup_provisioner.rb +26 -15
  19. data/lib/vagrant-digitalocean/actions/setup_sudo.rb +19 -12
  20. data/lib/vagrant-digitalocean/actions/setup_user.rb +25 -27
  21. data/lib/vagrant-digitalocean/actions/sync_folders.rb +18 -17
  22. data/lib/vagrant-digitalocean/commands/rebuild.rb +2 -3
  23. data/lib/vagrant-digitalocean/config.rb +30 -33
  24. data/lib/vagrant-digitalocean/errors.rb +0 -2
  25. data/lib/vagrant-digitalocean/helpers/client.rb +13 -15
  26. data/lib/vagrant-digitalocean/plugin.rb +5 -14
  27. data/lib/vagrant-digitalocean/provider.rb +48 -34
  28. data/lib/vagrant-digitalocean/version.rb +1 -1
  29. data/locales/en.yml +32 -40
  30. data/test/Vagrantfile +37 -0
  31. data/test/cookbooks/test/recipes/default.rb +1 -1
  32. data/test/scripts/provision.sh +3 -0
  33. data/test/test.sh +14 -0
  34. metadata +15 -27
  35. data/bin/build.sh +0 -39
  36. data/bin/test_run.sh +0 -15
  37. data/box/Vagrantfile +0 -20
  38. data/box/cookbooks/foo/recipes/default.rb +0 -1
  39. data/lib/vagrant-digitalocean/action.rb +0 -105
  40. data/lib/vagrant-digitalocean/actions/check_ssh_user.rb +0 -46
  41. data/lib/vagrant-digitalocean/actions/is_active.rb +0 -16
  42. data/lib/vagrant-digitalocean/actions/message_is_active.rb +0 -18
  43. data/lib/vagrant-digitalocean/actions/read_state.rb +0 -33
  44. data/lib/vagrant-digitalocean/actions/setup_ssh_key.rb +0 -60
  45. data/lib/vagrant-digitalocean/helpers/file.rb +0 -41
  46. data/lib/vagrant-digitalocean/helpers/translator.rb +0 -20
  47. data/scripts/chef/debian.sh +0 -5
  48. data/scripts/chef/redhat.sh +0 -5
  49. data/scripts/nfs/debian.sh +0 -4
  50. data/scripts/nfs/redhat.sh +0 -11
  51. data/scripts/sudo/redhat.sh +0 -2
  52. data/test/Vagrantfile.centos +0 -19
  53. data/test/Vagrantfile.ubuntu +0 -21
  54. data/test/provision.sh +0 -3
  55. data/test/scripts/setup_user.sh +0 -18
@@ -0,0 +1,19 @@
1
+ module VagrantPlugins
2
+ module DigitalOcean
3
+ module Actions
4
+ class CheckState
5
+ def initialize(app, env)
6
+ @app = app
7
+ @machine = env[:machine]
8
+ @logger = Log4r::Logger.new('vagrant::digitalocean::check_state')
9
+ end
10
+
11
+ def call(env)
12
+ env[:machine_state] = @machine.state.id
13
+ @logger.info "Machine state is '#{@machine.state.id}'"
14
+ @app.call(env)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,49 +1,64 @@
1
- require "vagrant-digitalocean/helpers/client"
1
+ require 'vagrant-digitalocean/helpers/client'
2
2
 
3
3
  module VagrantPlugins
4
4
  module DigitalOcean
5
5
  module Actions
6
6
  class Create
7
- include Vagrant::Util::Retryable
8
7
  include Helpers::Client
8
+ include Vagrant::Util::Retryable
9
9
 
10
10
  def initialize(app, env)
11
- @app, @env = app, env
11
+ @app = app
12
+ @machine = env[:machine]
12
13
  @client = client
13
- @translator = Helpers::Translator.new("actions.create")
14
+ @logger = Log4r::Logger.new('vagrant::digitalocean::create')
14
15
  end
15
16
 
16
17
  def call(env)
17
18
  ssh_key_id = env[:ssh_key_id]
18
19
 
19
20
  size_id = @client
20
- .request("/sizes")
21
- .find_id(:sizes, :name => env[:machine].provider_config.size)
21
+ .request('/sizes')
22
+ .find_id(:sizes, :name => @machine.provider_config.size)
22
23
 
23
24
  image_id = @client
24
- .request("/images", { :filter => "global" })
25
- .find_id(:images, :name => env[:machine].provider_config.image)
25
+ .request('/images', { :filter => 'global' })
26
+ .find_id(:images, :name => @machine.provider_config.image)
26
27
 
27
28
  region_id = @client
28
- .request("/regions")
29
- .find_id(:regions, :name => env[:machine].provider_config.region)
29
+ .request('/regions')
30
+ .find_id(:regions, :name => @machine.provider_config.region)
30
31
 
31
- env[:ui].info @translator.t("create_droplet")
32
-
33
- result = @client.request("/droplets/new", {
32
+ # submit new droplet request
33
+ result = @client.request('/droplets/new', {
34
34
  :size_id => size_id,
35
35
  :region_id => region_id,
36
36
  :image_id => image_id,
37
- # TODO use the current directory name as a post fix
38
- :name => "vagrant",
37
+ :name => @machine.config.vm.hostname || @machine.name,
39
38
  :ssh_key_ids => ssh_key_id
40
39
  })
41
40
 
42
- env[:ui].info @translator.t("wait_active")
43
- @client.wait_for_event(result["droplet"]["event_id"])
41
+ # wait for request to complete
42
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.creating')
43
+ @client.wait_for_event(env, result['droplet']['event_id'])
44
44
 
45
45
  # assign the machine id for reference in other commands
46
- env[:machine].id = result["droplet"]["id"].to_s
46
+ @machine.id = result['droplet']['id'].to_s
47
+
48
+ # refresh droplet state with provider and output ip address
49
+ droplet = Provider.droplet(@machine, :refresh => true)
50
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.droplet_ip', {
51
+ :ip => droplet['ip_address']
52
+ })
53
+
54
+ # wait for ssh to be ready using the root user account
55
+ user = @machine.config.ssh.username
56
+ @machine.config.ssh.username = 'root'
57
+ retryable(:tries => 30, :sleep => 10) do
58
+ next if env[:interrupted]
59
+ raise 'not ready' if !@machine.communicate.ready?
60
+ end
61
+ @machine.config.ssh.username = user
47
62
 
48
63
  @app.call(env)
49
64
  end
@@ -51,9 +66,9 @@ module VagrantPlugins
51
66
  # Both the recover and terminate are stolen almost verbatim from
52
67
  # the Vagrant AWS provider up action
53
68
  def recover(env)
54
- return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
69
+ return if env['vagrant.error'].is_a?(Vagrant::Errors::VagrantError)
55
70
 
56
- if env[:machine].state.id != :not_created
71
+ if @machine.state.id != :not_created
57
72
  terminate(env)
58
73
  end
59
74
  end
@@ -63,7 +78,7 @@ module VagrantPlugins
63
78
  destroy_env.delete(:interrupted)
64
79
  destroy_env[:config_validate] = false
65
80
  destroy_env[:force_confirm_destroy] = true
66
- env[:action_runner].run(Action.new.destroy, destroy_env)
81
+ env[:action_runner].run(Actions.destroy, destroy_env)
67
82
  end
68
83
  end
69
84
  end
@@ -1,26 +1,28 @@
1
- require "vagrant-digitalocean/helpers/client"
1
+ require 'vagrant-digitalocean/helpers/client'
2
2
 
3
3
  module VagrantPlugins
4
4
  module DigitalOcean
5
5
  module Actions
6
6
  class Destroy
7
- include Vagrant::Util::Retryable
8
7
  include Helpers::Client
9
8
 
10
9
  def initialize(app, env)
11
- @app, @env = app, env
10
+ @app = app
11
+ @machine = env[:machine]
12
12
  @client = client
13
- @translator = Helpers::Translator.new("actions.destroy")
13
+ @logger = Log4r::Logger.new('vagrant::digitalocean::destroy')
14
14
  end
15
15
 
16
16
  def call(env)
17
17
  # submit destroy droplet request
18
- env[:ui].info @translator.t("destroying")
19
- result = @client.request("/droplets/#{env[:machine].id}/destroy")
18
+ result = @client.request("/droplets/#{@machine.id}/destroy")
20
19
 
21
20
  # wait for request to complete
22
- env[:ui].info @translator.t("wait_off")
23
- @client.wait_for_event(result["event_id"])
21
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.destroying')
22
+ @client.wait_for_event(env, result['event_id'])
23
+
24
+ # set the machine id to nil to cleanup local vagrant state
25
+ @machine.id = nil
24
26
 
25
27
  @app.call(env)
26
28
  end
@@ -2,34 +2,32 @@ module VagrantPlugins
2
2
  module DigitalOcean
3
3
  module Actions
4
4
  class ModifyProvisionPath
5
- include Vagrant::Util::Counter
6
-
7
5
  def initialize(app, env)
8
6
  @app = app
9
7
  @machine = env[:machine]
10
- @translator =
11
- Helpers::Translator.new("actions.modify_provision_path")
8
+ @logger =
9
+ Log4r::Logger.new('vagrant::digitalocean::modify_provision_path')
12
10
  end
13
11
 
14
12
  def call(env)
13
+ # check if provisioning is enabled
14
+ enabled = true
15
+ enabled = env[:provision_enabled] if env.has_key?(:provision_enabled)
16
+ return @app.call(env) if !enabled
17
+
15
18
  username = @machine.ssh_info()[:username]
16
- env[:ui].info @translator.t("modify", { :user => username })
17
19
 
18
- # modify provisioning paths to enable different users to
19
- # provision the same machine
20
+ # change ownership of the provisioning path recursively to the
21
+ # ssh user
20
22
  #
21
23
  # TODO submit patch to vagrant to set appropriate permissions
22
24
  # based on ssh username
23
- @machine.communicate.execute("mkdir -p /home/#{username}/tmp")
24
- env[:global_config].vm.provisioners.each do |prov|
25
- if prov.name == :shell
26
- prov.config.upload_path =
27
- prov.config.upload_path.prepend("/home/#{username}")
28
- else
29
- counter = get_and_update_counter(:provisioning_path)
30
- path = "/home/#{username}/tmp/vagrant-chef-#{counter}"
31
- prov.config.provisioning_path = path
32
- end
25
+ @machine.config.vm.provisioners.each do |provisioner|
26
+ cfg = provisioner.config
27
+ path = cfg.upload_path if cfg.respond_to? :upload_path
28
+ path = cfg.provisioning_path if cfg.respond_to? :provisioning_path
29
+ @machine.communicate.sudo("chown -R #{username} #{path}",
30
+ :error_check => false)
33
31
  end
34
32
 
35
33
  @app.call(env)
@@ -0,0 +1,33 @@
1
+ require 'vagrant-digitalocean/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module DigitalOcean
5
+ module Actions
6
+ class PowerOff
7
+ include Helpers::Client
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @machine = env[:machine]
12
+ @client = client
13
+ @logger = Log4r::Logger.new('vagrant::digitalocean::power_off')
14
+ end
15
+
16
+ def call(env)
17
+ # submit power off droplet request
18
+ result = @client.request("/droplets/#{@machine.id}/power_off")
19
+
20
+ # wait for request to complete
21
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.powering_off')
22
+ @client.wait_for_event(env, result['event_id'])
23
+
24
+ # refresh droplet state with provider
25
+ Provider.droplet(@machine, :refresh => true)
26
+
27
+ @app.call(env)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+
@@ -0,0 +1,34 @@
1
+ require 'vagrant-digitalocean/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module DigitalOcean
5
+ module Actions
6
+ class PowerOn
7
+ include Helpers::Client
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @machine = env[:machine]
12
+ @client = client
13
+ @logger = Log4r::Logger.new('vagrant::digitalocean::power_on')
14
+ end
15
+
16
+ def call(env)
17
+ # submit power on droplet request
18
+ result = @client.request("/droplets/#{@machine.id}/power_on")
19
+
20
+ # wait for request to complete
21
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.powering_on')
22
+ @client.wait_for_event(env, result['event_id'])
23
+
24
+ # refresh droplet state with provider
25
+ Provider.droplet(@machine, :refresh => true)
26
+
27
+ @app.call(env)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+
@@ -1,4 +1,4 @@
1
- require "vagrant-digitalocean/helpers/client"
1
+ require 'vagrant-digitalocean/helpers/client'
2
2
 
3
3
  module VagrantPlugins
4
4
  module DigitalOcean
@@ -7,26 +7,26 @@ module VagrantPlugins
7
7
  include Helpers::Client
8
8
 
9
9
  def initialize(app, env)
10
- @app, @env = app, env
10
+ @app = app
11
+ @machine = env[:machine]
11
12
  @client = client
12
- @translator = Helpers::Translator.new("actions.rebuild")
13
+ @logger = Log4r::Logger.new('vagrant::digitalocean::rebuild')
13
14
  end
14
15
 
15
16
  def call(env)
16
17
  # look up image id
17
18
  image_id = @client
18
- .request("/images", { :filter => "global" })
19
- .find_id(:images, :name => env[:machine].provider_config.image)
19
+ .request('/images', { :filter => 'global' })
20
+ .find_id(:images, :name => @machine.provider_config.image)
20
21
 
21
22
  # submit rebuild request
22
- env[:ui].info @translator.t("rebuild")
23
- result = @client.request("/droplets/#{env[:machine].id}/rebuild", {
23
+ result = @client.request("/droplets/#{@machine.id}/rebuild", {
24
24
  :image_id => image_id
25
25
  })
26
26
 
27
27
  # wait for request to complete
28
- env[:ui].info @translator.t("wait")
29
- @client.wait_for_event(result["event_id"])
28
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.rebuilding')
29
+ @client.wait_for_event(env, result['event_id'])
30
30
 
31
31
  @app.call(env)
32
32
  end
@@ -0,0 +1,31 @@
1
+ require 'vagrant-digitalocean/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module DigitalOcean
5
+ module Actions
6
+ class Reload
7
+ include Helpers::Client
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @machine = env[:machine]
12
+ @client = client
13
+ @logger = Log4r::Logger.new('vagrant::digitalocean::reload')
14
+ end
15
+
16
+ def call(env)
17
+ # submit reboot droplet request
18
+ result = @client.request("/droplets/#{@machine.id}/reboot")
19
+
20
+ # wait for request to complete
21
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.reloading')
22
+ @client.wait_for_event(env, result['event_id'])
23
+
24
+ @app.call(env)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+
@@ -0,0 +1,56 @@
1
+ require 'vagrant-digitalocean/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module DigitalOcean
5
+ module Actions
6
+ class SetupKey
7
+ include Helpers::Client
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @machine = env[:machine]
12
+ @client = client
13
+ @logger = Log4r::Logger.new('vagrant::digitalocean::setup_key')
14
+ end
15
+
16
+ # TODO check the content of the key to see if it has changed
17
+ def call(env)
18
+ ssh_key_name = @machine.provider_config.ssh_key_name
19
+
20
+ begin
21
+ # assigns existing ssh key id to env for use by other commands
22
+ env[:ssh_key_id] = @client
23
+ .request('/ssh_keys/')
24
+ .find_id(:ssh_keys, :name => ssh_key_name)
25
+
26
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.using_key', {
27
+ :name => ssh_key_name
28
+ })
29
+ rescue Errors::ResultMatchError
30
+ env[:ssh_key_id] = create_ssh_key(ssh_key_name, env)
31
+ end
32
+
33
+ @app.call(env)
34
+ end
35
+
36
+ private
37
+
38
+ def create_ssh_key(name, env)
39
+ # assumes public key exists on the same path as private key with .pub ext
40
+ private_key_path = @machine.config.ssh.private_key_path
41
+ pub_key = DigitalOcean.public_key(private_key_path)
42
+
43
+ env[:ui].info I18n.t('vagrant_digital_ocean.info.creating_key', {
44
+ :name => name
45
+ })
46
+
47
+ result = @client.request('/ssh_keys/new', {
48
+ :name => name,
49
+ :ssh_pub_key => pub_key
50
+ })
51
+ result['ssh_key']['id']
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -1,28 +1,39 @@
1
- require "vagrant-digitalocean/helpers/file"
2
-
3
1
  module VagrantPlugins
4
2
  module DigitalOcean
5
3
  module Actions
6
4
  class SetupProvisioner
7
- include Helpers::File
8
-
9
5
  def initialize(app, env)
10
- @app, @env = app, env
11
- @translator = Helpers::Translator.new("actions.setup_provisioner")
6
+ @app = app
7
+ @machine = env[:machine]
8
+ @logger =
9
+ Log4r::Logger.new('vagrant::digitalocean::setup_provisioner')
12
10
  end
13
11
 
14
12
  def call(env)
15
- # TODO prevent setup when no chef provisioner declared
16
- # TODO catch ssh failure and report back on install issues
17
- # TODO first check to see if it's installed and then skip the info
18
- env[:ui].info @translator.t("install", :provisioner => "chef-solo")
19
- env[:machine].communicate.execute(chef_install(env[:machine].guest))
13
+ # check if provisioning is enabled
14
+ enabled = true
15
+ enabled = env[:provision_enabled] if env.has_key?(:provision_enabled)
16
+ return @app.call(env) if !enabled
20
17
 
21
- @app.call(env)
22
- end
18
+ # check if a chef provisioner is configured
19
+ provisioners = @machine.config.vm.provisioners
20
+ configured = provisioners.reduce(false) do |c, provisioner|
21
+ provisioner.name =~ /chef/
22
+ end
23
+ return @app.call(env) if !configured
23
24
 
24
- def chef_install(guest)
25
- read_script("chef", guest)
25
+ # check if chef is already installed
26
+ command = 'which chef-solo'
27
+ code = @machine.communicate.execute(command, :error_check => false)
28
+ return @app.call(env) if code == 0
29
+
30
+ # install chef
31
+ key = 'vagrant_digital_ocean.info.installing_provisioner'
32
+ env[:ui].info I18n.t(key, { :provisioner => 'chef' })
33
+ command = 'wget -O - http://www.opscode.com/chef/install.sh | bash'
34
+ @machine.communicate.sudo(command)
35
+
36
+ @app.call(env)
26
37
  end
27
38
  end
28
39
  end