vagrant-simplecloud 0.0.1

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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/CHANGELOG.md +6 -0
  4. data/Gemfile +11 -0
  5. data/LICENSE.txt +23 -0
  6. data/README.md +143 -0
  7. data/Rakefile +22 -0
  8. data/box/metadata.json +3 -0
  9. data/box/simple_cloud.box +0 -0
  10. data/lib/vagrant-simplecloud.rb +20 -0
  11. data/lib/vagrant-simplecloud/actions.rb +165 -0
  12. data/lib/vagrant-simplecloud/actions/check_state.rb +19 -0
  13. data/lib/vagrant-simplecloud/actions/create.rb +84 -0
  14. data/lib/vagrant-simplecloud/actions/destroy.rb +32 -0
  15. data/lib/vagrant-simplecloud/actions/modify_provision_path.rb +38 -0
  16. data/lib/vagrant-simplecloud/actions/power_off.rb +33 -0
  17. data/lib/vagrant-simplecloud/actions/power_on.rb +36 -0
  18. data/lib/vagrant-simplecloud/actions/rebuild.rb +56 -0
  19. data/lib/vagrant-simplecloud/actions/reload.rb +33 -0
  20. data/lib/vagrant-simplecloud/actions/setup_key.rb +53 -0
  21. data/lib/vagrant-simplecloud/actions/setup_sudo.rb +48 -0
  22. data/lib/vagrant-simplecloud/actions/setup_user.rb +66 -0
  23. data/lib/vagrant-simplecloud/actions/shut_down.rb +34 -0
  24. data/lib/vagrant-simplecloud/actions/sync_folders.rb +89 -0
  25. data/lib/vagrant-simplecloud/commands/list.rb +89 -0
  26. data/lib/vagrant-simplecloud/commands/rebuild.rb +29 -0
  27. data/lib/vagrant-simplecloud/config.rb +64 -0
  28. data/lib/vagrant-simplecloud/errors.rb +37 -0
  29. data/lib/vagrant-simplecloud/helpers/client.rb +151 -0
  30. data/lib/vagrant-simplecloud/helpers/result.rb +40 -0
  31. data/lib/vagrant-simplecloud/plugin.rb +31 -0
  32. data/lib/vagrant-simplecloud/provider.rb +102 -0
  33. data/lib/vagrant-simplecloud/version.rb +5 -0
  34. data/locales/en.yml +90 -0
  35. data/test/Vagrantfile +41 -0
  36. data/test/cookbooks/test/recipes/default.rb +1 -0
  37. data/test/scripts/provision.sh +3 -0
  38. data/test/test.sh +14 -0
  39. data/test/test_id_rsa +27 -0
  40. data/test/test_id_rsa.pub +1 -0
  41. data/testkit.rb +40 -0
  42. data/vagrant-simplecloud.gemspec +22 -0
  43. metadata +146 -0
@@ -0,0 +1,32 @@
1
+ require 'vagrant-simplecloud/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module SimpleCloud
5
+ module Actions
6
+ class Destroy
7
+ include Helpers::Client
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @machine = env[:machine]
12
+ @client = client
13
+ @simple_client = simple_client
14
+ @logger = Log4r::Logger.new('vagrant::simplecloud::destroy')
15
+ end
16
+
17
+ def call(env)
18
+ # submit destroy droplet request
19
+ @simple_client.droplets.delete(id: @machine.id)
20
+ #@client.delete("/v2/droplets/#{@machine.id}")
21
+
22
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.destroying')
23
+
24
+ # set the machine id to nil to cleanup local vagrant state
25
+ @machine.id = nil
26
+
27
+ @app.call(env)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,38 @@
1
+ module VagrantPlugins
2
+ module SimpleCloud
3
+ module Actions
4
+ class ModifyProvisionPath
5
+ def initialize(app, env)
6
+ @app = app
7
+ @machine = env[:machine]
8
+ @logger =
9
+ Log4r::Logger.new('vagrant::simplecloud::modify_provision_path')
10
+ end
11
+
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
+
18
+ username = @machine.ssh_info()[:username]
19
+
20
+ # change ownership of the provisioning path recursively to the
21
+ # ssh user
22
+ #
23
+ # TODO submit patch to vagrant to set appropriate permissions
24
+ # based on ssh username
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)
31
+ end
32
+
33
+ @app.call(env)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
1
+ require 'vagrant-simplecloud/helpers/client'
2
+ #TODO: --force
3
+ module VagrantPlugins
4
+ module SimpleCloud
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
+ @simple_client = simple_client
14
+ @logger = Log4r::Logger.new('vagrant::simplecloud::power_off')
15
+ end
16
+
17
+ def call(env)
18
+ # submit power off droplet request
19
+ result = @simple_client.post("/v2/droplets/#{@machine.id}/actions", {:type => 'power_off'})
20
+
21
+ # wait for request to complete
22
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.powering_off')
23
+ @client.wait_for_event(env, result['action']['id'])
24
+
25
+ # refresh droplet state with provider
26
+ Provider.droplet(@machine, :refresh => true)
27
+
28
+ @app.call(env)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,36 @@
1
+ require 'vagrant-simplecloud/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module SimpleCloud
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
+ @simple_client = simple_client
14
+ @logger = Log4r::Logger.new('vagrant::simplecloud::power_on')
15
+ end
16
+
17
+ def call(env)
18
+ # submit power on droplet request
19
+ result = JSON.parse(@simple_client.droplet_actions.power_on(droplet_id: @machine.id.to_s))
20
+ #result = @client.post("/v2/droplets/#{@machine.id}/actions", {
21
+ #:type => 'power_on'
22
+ #})
23
+
24
+ # wait for request to complete
25
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.powering_on')
26
+ @client.wait_for_event(env, result['action']['id'])
27
+
28
+ # refresh droplet state with provider
29
+ Provider.droplet(@machine, :refresh => true)
30
+
31
+ @app.call(env)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,56 @@
1
+ require 'vagrant-simplecloud/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module SimpleCloud
5
+ module Actions
6
+ class Rebuild
7
+ include Helpers::Client
8
+ include Vagrant::Util::Retryable
9
+
10
+ def initialize(app, env)
11
+ @app = app
12
+ @machine = env[:machine]
13
+ @client = client
14
+ @simple_client = simple_client
15
+ @logger = Log4r::Logger.new('vagrant::simplecloud::rebuild')
16
+ end
17
+
18
+ def call(env)
19
+ # look up image id
20
+ image_id = @simple_client.images.find(id: @machine.provider_config.image).id
21
+
22
+ # submit rebuild request
23
+ result = @simple_client.post("/v2/droplets/#{@machine.id}/actions", {
24
+ :type => 'rebuild',
25
+ :image => image_id
26
+ })
27
+ # simple cloud api has not return region_slug in response
28
+ #image_id = @simple_client.images.find(id: @machine.provider_config.image).id
29
+ #env[:ui].info "#{@machine.id.to_s}, #{image_id}"
30
+ #result = JSON.parse(@simple_client.droplet_actions.rebuild(droplet_id: @machine.id, image: image_id))
31
+
32
+ # wait for request to complete
33
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.rebuilding')
34
+ @client.wait_for_event(env, result['action']['id'])
35
+
36
+ # refresh droplet state with provider
37
+ Provider.droplet(@machine, :refresh => true)
38
+
39
+ # wait for ssh to be ready
40
+ switch_user = @machine.provider_config.setup?
41
+ user = @machine.config.ssh.username
42
+ @machine.config.ssh.username = 'root' if switch_user
43
+
44
+ retryable(:tries => 120, :sleep => 10) do
45
+ next if env[:interrupted]
46
+ raise 'not ready' if !@machine.communicate.ready?
47
+ end
48
+
49
+ @machine.config.ssh.username = user
50
+
51
+ @app.call(env)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,33 @@
1
+ require 'vagrant-simplecloud/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module SimpleCloud
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::simplecloud::reload')
14
+ end
15
+
16
+ def call(env)
17
+ # submit reboot droplet request
18
+ result = @client.post("/v2/droplets/#{@machine.id}/actions", {
19
+ :type => 'reboot'
20
+ })
21
+
22
+ # wait for request to complete
23
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.reloading')
24
+ @client.wait_for_event(env, result['action']['id'])
25
+
26
+ @app.call(env)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+
@@ -0,0 +1,53 @@
1
+ require 'vagrant-simplecloud/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module SimpleCloud
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
+ @simple_client = simple_client
14
+ @logger = Log4r::Logger.new('vagrant::simplecloud::setup_key')
15
+ end
16
+
17
+ # TODO check the content of the key to see if it has changed
18
+ def call(env)
19
+ ssh_key_name = @machine.provider_config.ssh_key_name
20
+ # assigns existing ssh key id to env for use by other commands
21
+ @simple_client.ssh_keys.all().each do |key|
22
+ if key["name"] == ssh_key_name
23
+ env[:ssh_key_id] = key["id"]
24
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.using_key', {
25
+ :name => ssh_key_name
26
+ })
27
+ @app.call(env)
28
+ return
29
+ end
30
+ end
31
+ env[:ssh_key_id] = create_ssh_key(ssh_key_name, env)
32
+ @app.call(env)
33
+ end
34
+
35
+ private
36
+
37
+ def create_ssh_key(name, env)
38
+ # assumes public key exists on the same path as private key with .pub ext
39
+ path = @machine.config.ssh.private_key_path
40
+ path = path[0] if path.is_a?(Array)
41
+ path = File.expand_path(path, @machine.env.root_path)
42
+ pub_key = SimpleCloud.public_key(path)
43
+ ssh_key = DropletKit::SSHKey.new(name: name, public_key: pub_key)
44
+ result = @simple_client.ssh_keys.create(ssh_key)
45
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.creating_key', {
46
+ :name => name
47
+ })
48
+ result.id
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,48 @@
1
+ module VagrantPlugins
2
+ module SimpleCloud
3
+ module Actions
4
+ class SetupSudo
5
+ def initialize(app, env)
6
+ @app = app
7
+ @machine = env[:machine]
8
+ @logger = Log4r::Logger.new('vagrant::simplecloud::setup_sudo')
9
+ end
10
+
11
+ def call(env)
12
+ # check if setup is enabled
13
+ return @app.call(env) unless @machine.provider_config.setup?
14
+
15
+ # override ssh username to root
16
+ user = @machine.config.ssh.username
17
+ @machine.config.ssh.username = 'root'
18
+
19
+ # check for guest name available in Vagrant 1.2 first
20
+ guest_name = @machine.guest.name if @machine.guest.respond_to?(:name)
21
+ guest_name ||= @machine.guest.to_s.downcase
22
+
23
+ case guest_name
24
+ when /redhat/
25
+ @machine.communicate.execute('yum install sudo')
26
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.modifying_sudo')
27
+ # disable tty requirement for sudo
28
+ @machine.communicate.execute(<<-'BASH')
29
+ sed -i'.bk' -e 's/\(Defaults\s\+requiretty\)/# \1/' /etc/sudoers
30
+ BASH
31
+ when /debian/
32
+ @machine.communicate.execute('apt-get install sudo')
33
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.modifying_sudo')
34
+ # disable tty requirement for sudo
35
+ @machine.communicate.execute(<<-'BASH')
36
+ sed -i'.bk' -e 's/\(Defaults\s\+requiretty\)/# \1/' /etc/sudoers
37
+ BASH
38
+ end
39
+
40
+ # reset ssh username
41
+ @machine.config.ssh.username = user
42
+
43
+ @app.call(env)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,66 @@
1
+ module VagrantPlugins
2
+ module SimpleCloud
3
+ module Actions
4
+ class SetupUser
5
+ def initialize(app, env)
6
+ @app = app
7
+ @machine = env[:machine]
8
+ @logger = Log4r::Logger.new('vagrant::simplecloud::setup_user')
9
+ end
10
+
11
+ def call(env)
12
+ # check if setup is enabled
13
+ return @app.call(env) unless @machine.provider_config.setup?
14
+
15
+ # check if a username has been specified
16
+ return @app.call(env) unless @machine.config.ssh.username
17
+
18
+ # override ssh username to root temporarily
19
+ user = @machine.config.ssh.username
20
+ @machine.config.ssh.username = 'root'
21
+
22
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.creating_user', {
23
+ :user => user
24
+ })
25
+
26
+ # create user account
27
+ @machine.communicate.execute(<<-BASH)
28
+ if ! (grep ^#{user}: /etc/passwd); then
29
+ useradd -m -s /bin/bash #{user};
30
+ fi
31
+ BASH
32
+
33
+ # grant user sudo access with no password requirement
34
+ @machine.communicate.execute(<<-BASH)
35
+ if ! (grep #{user} /etc/sudoers); then
36
+ echo "#{user} ALL=(ALL:ALL) NOPASSWD: ALL" >> /etc/sudoers;
37
+ else
38
+ sed -i -e "/#{user}/ s/=.*/=(ALL:ALL) NOPASSWD: ALL/" /etc/sudoers;
39
+ fi
40
+ BASH
41
+
42
+ # create the .ssh directory in the users home
43
+ @machine.communicate.execute("su #{user} -c 'mkdir -p ~/.ssh'")
44
+
45
+ # add the specified key to the authorized keys file
46
+ path = @machine.config.ssh.private_key_path
47
+ path = path[0] if path.is_a?(Array)
48
+ path = File.expand_path(path, @machine.env.root_path)
49
+ pub_key = SimpleCloud.public_key(path)
50
+ @machine.communicate.execute(<<-BASH)
51
+ if ! grep '#{pub_key}' /home/#{user}/.ssh/authorized_keys; then
52
+ echo '#{pub_key}' >> /home/#{user}/.ssh/authorized_keys;
53
+ fi
54
+
55
+ chown -R #{user} /home/#{user}/.ssh;
56
+ BASH
57
+
58
+ # reset username
59
+ @machine.config.ssh.username = user
60
+
61
+ @app.call(env)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,34 @@
1
+ require 'vagrant-simplecloud/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module SimpleCloud
5
+ module Actions
6
+ class ShutDown
7
+ include Helpers::Client
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @machine = env[:machine]
12
+ @client = client
13
+ @simple_client = simple_client
14
+ @logger = Log4r::Logger.new('vagrant::simplecloud::shut_down')
15
+ end
16
+
17
+ def call(env)
18
+ # submit shutdown droplet request
19
+ result = @simple_client.post("/v2/droplets/#{@machine.id}/actions", {:type => 'shutdown'})
20
+
21
+ # wait for request to complete
22
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.shutting_down')
23
+ #@client.wait_for_event(env, result['droplet']['event_id'])
24
+ @client.wait_for_event(env, result['action']['id'])
25
+
26
+ # refresh droplet state with provider
27
+ Provider.droplet(@machine, :refresh => true)
28
+
29
+ @app.call(env)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,89 @@
1
+ require 'vagrant/util/subprocess'
2
+ require 'vagrant/util/which'
3
+
4
+ module VagrantPlugins
5
+ module SimpleCloud
6
+ module Actions
7
+ class SyncFolders
8
+ def initialize(app, env)
9
+ @app = app
10
+ @machine = env[:machine]
11
+ @logger = Log4r::Logger.new('vagrant::simplecloud::sync_folders')
12
+ end
13
+
14
+ def call(env)
15
+ ssh_info = @machine.ssh_info
16
+
17
+ @machine.config.vm.synced_folders.each do |id, data|
18
+ next if data[:disabled]
19
+
20
+ if @machine.guest.capability?(:rsync_installed)
21
+ installed = @machine.guest.capability(:rsync_installed)
22
+ if !installed
23
+ can_install = @machine.guest.capability?(:rsync_install)
24
+ raise Vagrant::Errors::RSyncNotInstalledInGuest if !can_install
25
+ @machine.ui.info I18n.t("vagrant.rsync_installing")
26
+ @machine.guest.capability(:rsync_install)
27
+ end
28
+ end
29
+
30
+ hostpath = File.expand_path(data[:hostpath], env[:root_path])
31
+ guestpath = data[:guestpath]
32
+
33
+ # make sure there is a trailing slash on the host path to
34
+ # avoid creating an additional directory with rsync
35
+ hostpath = "#{hostpath}/" if hostpath !~ /\/$/
36
+
37
+ # on windows rsync.exe requires cygdrive-style paths
38
+ if Vagrant::Util::Platform.windows?
39
+ hostpath = hostpath.gsub(/^(\w):/) { "/cygdrive/#{$1}" }
40
+ end
41
+
42
+ env[:ui].info I18n.t('vagrant_simple_cloud.info.rsyncing', {
43
+ :hostpath => hostpath,
44
+ :guestpath => guestpath
45
+ })
46
+
47
+ # create the guest path
48
+ @machine.communicate.sudo("mkdir -p #{guestpath}")
49
+ @machine.communicate.sudo(
50
+ "chown -R #{ssh_info[:username]} #{guestpath}")
51
+
52
+ key = ssh_info[:private_key_path]
53
+ key = key[0] if key.is_a?(Array)
54
+
55
+ # attach to vagrant's default rsync opetions
56
+ # http://docs.vagrantup.com/v2/synced-folders/rsync.html
57
+ args = ["--verbose", "--archive", "--delete", "-z", "--copy-links", *Array(data[:rsync__args])]
58
+ exclude = [".vagrant/", *Array(data[:rsync__exclude])]
59
+
60
+ # rsync over to the guest path using the ssh info
61
+ command = [
62
+ "rsync",
63
+ *args.map{|e|[e]}.flatten,
64
+ *exclude.map{|e|["--exclude", e]}.flatten,
65
+ "-e", "ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no -i '#{key}'",
66
+ hostpath,
67
+ "#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
68
+
69
+ # we need to fix permissions when using rsync.exe on windows, see
70
+ # http://stackoverflow.com/questions/5798807/rsync-permission-denied-created-directories-have-no-permissions
71
+ if Vagrant::Util::Platform.windows?
72
+ command.insert(1, "--chmod", "ugo=rwX")
73
+ end
74
+
75
+ r = Vagrant::Util::Subprocess.execute(*command)
76
+ if r.exit_code != 0
77
+ raise Errors::RsyncError,
78
+ :guestpath => guestpath,
79
+ :hostpath => hostpath,
80
+ :stderr => r.stderr
81
+ end
82
+ end
83
+
84
+ @app.call(env)
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end