vagrant-simplecloud 0.0.1

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