vagrant-vultr 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: eb4c76ac7a5ec05267841f449a00c958cd11fcb0
4
+ data.tar.gz: 742381010d35a6157a70ad864945bf13470da194
5
+ SHA512:
6
+ metadata.gz: 4451dddfd960394856e4156fe3c43a196a23ce54c66b2fe3d114941411285f79bd64a7bf7ff6196f8c6ec3fbbce1932a16122c9e7769593ee3fb60bb94d42400
7
+ data.tar.gz: 0bbaeb9f6e546aefe957d0a655051f8969dfb42caa49fc1ac72e38ccc790e669a48cb8db2dbcff5d59c1097eb8dac7c621bdacf3928a6d0bb3e1e88541017da3
@@ -0,0 +1,8 @@
1
+ pkg/
2
+ tmp/
3
+ .bundle/
4
+ vendor/bundle/
5
+ .vagrant/
6
+ Gemfile.lock
7
+ .envrc
8
+ .ruby-version
@@ -0,0 +1,4 @@
1
+ {
2
+ "lib/vagrant-vultr/action.rb": {"type": "action"},
3
+ "lib/vagrant-vultr/action/*.rb": {"type": "action"}
4
+ }
@@ -0,0 +1,3 @@
1
+ ## 0.1.0 (unreleased)
2
+
3
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'http://rubygems.org'
2
+
3
+ group :development do
4
+ gem 'vagrant', github: 'mitchellh/vagrant'
5
+ end
6
+
7
+ group :plugins do
8
+ gemspec
9
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2015 Alex Rodionov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,90 @@
1
+ vagrant-vultr [![Gem Version](https://badge.fury.io/rb/vagrant-vultr.svg)](http://badge.fury.io/rb/vagrant-vultr)
2
+ ============
3
+
4
+ Vagrant plugin that allows to use [Vultr](https://vultr.com/) as provider.
5
+
6
+ For now, basic operations like vagrant up/halt/reload/destroy/provision are supported.
7
+
8
+ Installation
9
+ ------------
10
+
11
+ ```bash
12
+ $ vagrant plugin install vagrant-vultr
13
+ ```
14
+
15
+ Usage
16
+ -----
17
+
18
+ Create simple Vagrantfile:
19
+
20
+ ```ruby
21
+ Vagrant.configure(2) do |config|
22
+ config.vm.provider :vultr do |vultr, override|
23
+ override.ssh.private_key_path = '~/.ssh/id_rsa'
24
+ override.vm.box = 'vultr'
25
+ override.vm.box_url = 'https://github.com/p0deje/vagrant-vultr/raw/master/box/vultr.box'
26
+
27
+ vultr.token = 'YOUR_TOKEN' # You can also use VULTR_TOKEN environment variable
28
+ vultr.region = 'Seattle'
29
+ vultr.plan = '768 MB RAM,15 GB SSD,1.00 TB BW'
30
+
31
+ # Use either OS name or Snapshot identifier
32
+ vultr.os = 'Ubuntu 14.04 x64'
33
+ vultr.snapshot = '524557af2439b'
34
+ end
35
+ end
36
+ ```
37
+
38
+ Now start vagrant box:
39
+
40
+ ```bash
41
+ $ vagrant up --provider=vultr
42
+ ```
43
+
44
+ Notes
45
+ -----
46
+
47
+ 1. You have to specify `override.ssh.private_key_path`. Public key will be uploaded to Vultr as "vagrant" SSH key and will be used when servers are created.
48
+ 2. Currently, servers are created with "root" user.
49
+
50
+ Testing
51
+ -------
52
+
53
+ First of all, add the box that is used for testing:
54
+
55
+ ```bash
56
+ $ bundle exec rake box:add
57
+ ```
58
+
59
+ Since the tests involve actual calls to Vultr, you have to provide a valid API token:
60
+
61
+ ```bash
62
+ $ export VULTR_TOKEN="token"
63
+ ```
64
+
65
+ Now you can run tests:
66
+
67
+ ```bash
68
+ $ bundle exec rake cucumber
69
+ ```
70
+
71
+ Note that Vultr is not very stable, so tests sometimes may fail due to timeout or 404 API requests.
72
+
73
+ In the end, remove the box:
74
+
75
+ ```bash
76
+ $ bundle exec rake box:remove
77
+ ```
78
+
79
+ Contributing
80
+ ------------
81
+
82
+ * Fork the project.
83
+ * Make your feature addition or bug fix.
84
+ * Commit, do not mess with Rakefile, version, or history. If you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull.
85
+ * Send me a pull request. Bonus points for topic branches.
86
+
87
+ Copyright
88
+ ---------
89
+
90
+ Copyright (c) 2015 Alex Rodionov. See LICENSE.md for details.
@@ -0,0 +1,17 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ namespace :box do
5
+ desc 'Adds test vagrant box.'
6
+ task :add do
7
+ sh 'bundle exec vagrant box add --name vultr ./box/vultr.box'
8
+ end
9
+
10
+ desc 'Removes testing vagrant box.'
11
+ task :remove do
12
+ sh 'bundle exec vagrant box remove vultr'
13
+ end
14
+ end
15
+
16
+ require 'cucumber/rake/task'
17
+ Cucumber::Rake::Task.new
Binary file
@@ -0,0 +1,11 @@
1
+ require 'aruba/cucumber'
2
+
3
+ Before do
4
+ # VM start takes a long time
5
+ @aruba_timeout_seconds = 600
6
+ end
7
+
8
+ After do
9
+ # halt VM
10
+ system 'cd tmp/aruba; bundle exec vagrant halt &> /dev/null'
11
+ end
@@ -0,0 +1,78 @@
1
+ @announce
2
+ @no-clobber
3
+ Feature: vagrant-vultr
4
+ In order to use Vultr
5
+ As a Vagrant provider
6
+ I want to use plugin for that
7
+
8
+ Background:
9
+ Given I write to "Vagrantfile" with:
10
+ """
11
+ Vagrant.configure(2) do |config|
12
+ config.vm.box = 'vultr'
13
+ config.vm.synced_folder '.', '/vagrant', type: 'rsync'
14
+ config.ssh.private_key_path = '~/.ssh/id_rsa'
15
+
16
+ config.vm.provision 'shell',
17
+ inline: 'echo "it works" > /tmp/vultr-provision',
18
+ privileged: false
19
+ end
20
+ """
21
+
22
+ Scenario: creates server on up
23
+ When I run `bundle exec vagrant up --provider=vultr`
24
+ Then the exit status should be 0
25
+ And the output should contain "Machine is booted and ready to use!"
26
+ When I run `bundle exec vagrant status`
27
+ Then the output should contain "active (vultr)"
28
+
29
+ Scenario: starts created server on up
30
+ When I run `bundle exec vagrant up --provider=vultr`
31
+ And I run `bundle exec vagrant halt`
32
+ And I run `bundle exec vagrant up --provider=vultr`
33
+ Then the exit status should be 0
34
+ And the output should contain "Machine is booted and ready to use!"
35
+ When I run `bundle exec vagrant status`
36
+ Then the output should contain "active (vultr)"
37
+
38
+ Scenario: syncs folders
39
+ When I run `bundle exec vagrant up --provider=vultr`
40
+ And I run `bundle exec vagrant ssh -c "test -d /vagrant"`
41
+ Then the exit status should be 0
42
+
43
+ Scenario: provisions server
44
+ When I run `bundle exec vagrant up --provider=vultr`
45
+ And I run `bundle exec vagrant ssh -c "cat /tmp/vultr-provision"`
46
+ Then the exit status should be 0
47
+ And the output should contain "it works"
48
+
49
+ Scenario: executes SSH to created server
50
+ When I run `bundle exec vagrant up --provider=vultr`
51
+ And I run `bundle exec vagrant ssh` interactively
52
+ And I type "uname -a"
53
+ And I close the stdin stream
54
+ Then the output should contain "vultr.guest"
55
+
56
+ Scenario: reboots server on reload
57
+ When I run `bundle exec vagrant up --provider=vultr`
58
+ And I run `bundle exec vagrant reload`
59
+ Then the exit status should be 0
60
+ And the output should contain "Machine is booted and ready to use!"
61
+ When I run `bundle exec vagrant status`
62
+ Then the output should contain "active (vultr)"
63
+
64
+ Scenario: shutdowns server on halt
65
+ When I run `bundle exec vagrant up --provider=vultr`
66
+ And I run `bundle exec vagrant halt`
67
+ Then the exit status should be 0
68
+ And the output should contain "Machine is stopped."
69
+ When I run `bundle exec vagrant status`
70
+ Then the output should contain "off (vultr)"
71
+
72
+ Scenario: removes server on destroy
73
+ When I run `bundle exec vagrant up --provider=vultr`
74
+ And I run `bundle exec vagrant destroy --force`
75
+ Then the exit status should be 0
76
+ And the output should contain "Machine is destroyed."
77
+ When I run `bundle exec vagrant status`
78
+ Then the output should contain "not created"
@@ -0,0 +1,12 @@
1
+ require 'vagrant'
2
+
3
+ require 'vagrant-vultr/action'
4
+ require 'vagrant-vultr/plugin'
5
+
6
+ module VagrantPlugins
7
+ module Vultr
8
+ def self.source_root
9
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,132 @@
1
+ require 'vagrant-vultr/action/check_state'
2
+ require 'vagrant-vultr/action/create'
3
+ require 'vagrant-vultr/action/destroy'
4
+ require 'vagrant-vultr/action/power_off'
5
+ require 'vagrant-vultr/action/power_on'
6
+ require 'vagrant-vultr/action/reload'
7
+ require 'vagrant-vultr/action/setup_ssh_key'
8
+
9
+ module VagrantPlugins
10
+ module Vultr
11
+ module Action
12
+ include Vagrant::Action::Builtin
13
+
14
+ def self.up
15
+ Vagrant::Action::Builder.new.tap do |b|
16
+ b.use ConfigValidate
17
+ b.use Call, CheckState do |env, b2|
18
+ case env[:machine_state]
19
+ when :active
20
+ env[:ui].info 'Machine is already booted.'
21
+ when :off
22
+ b2.use PowerOn
23
+ b2.use Provision
24
+ b2.use SyncedFolders
25
+ when :not_created
26
+ b2.use SetupSSHKey
27
+ b2.use Create
28
+ b2.use Provision
29
+ b2.use SyncedFolders
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def self.halt
36
+ Vagrant::Action::Builder.new.tap do |b|
37
+ b.use ConfigValidate
38
+ b.use Call, CheckState do |env, b2|
39
+ case env[:machine_state]
40
+ when :active
41
+ b2.use PowerOff
42
+ when :off
43
+ env[:ui].info 'Machine is not booted.'
44
+ when :not_created
45
+ env[:ui].info 'Machine is not created.'
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ def self.reload
52
+ Vagrant::Action::Builder.new.tap do |b|
53
+ b.use ConfigValidate
54
+ b.use Call, CheckState do |env, b2|
55
+ case env[:machine_state]
56
+ when :active
57
+ b2.use Reload
58
+ b2.use Provision
59
+ b2.use SyncedFolders
60
+ when :off
61
+ env[:ui].info 'Machine is not booted.'
62
+ when :not_created
63
+ env[:ui].info 'Machine is not created.'
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ def self.destroy
70
+ Vagrant::Action::Builder.new.tap do |b|
71
+ b.use ConfigValidate
72
+ b.use Call, CheckState do |env, b2|
73
+ case env[:machine_state]
74
+ when :active, :off
75
+ b2.use Destroy
76
+ when :not_created
77
+ env[:ui].info 'Machine is not created.'
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ def self.provision
84
+ Vagrant::Action::Builder.new.tap do |b|
85
+ b.use ConfigValidate
86
+ b.use Call, CheckState do |env, b2|
87
+ case env[:machine_state]
88
+ when :active
89
+ b2.use Provision
90
+ when :off
91
+ env[:ui].info 'Machine is not booted.'
92
+ when :not_created
93
+ env[:ui].info 'Machine is not created.'
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ def self.ssh
100
+ Vagrant::Action::Builder.new.tap do |b|
101
+ b.use ConfigValidate
102
+ b.use Call, CheckState do |env, b2|
103
+ case env[:machine_state]
104
+ when :active
105
+ b2.use SSHExec
106
+ when :off
107
+ env[:ui].info 'Machine is not booted.'
108
+ when :not_created
109
+ env[:ui].info 'Machine is not created.'
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ def self.ssh_run
116
+ Vagrant::Action::Builder.new.tap do |b|
117
+ b.use ConfigValidate
118
+ b.use Call, CheckState do |env, b2|
119
+ case env[:machine_state]
120
+ when :active
121
+ b2.use SSHRun
122
+ when :off
123
+ env[:ui].info 'Machine is not booted.'
124
+ when :not_created
125
+ env[:ui].info 'Machine is not created.'
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,20 @@
1
+ module VagrantPlugins
2
+ module Vultr
3
+ module Action
4
+ class CheckState
5
+ def initialize(app, env)
6
+ @app = app
7
+ @machine = env[:machine]
8
+ @logger = Log4r::Logger.new('vagrant::vultr::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
+
15
+ @app.call(env)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,53 @@
1
+ require 'vagrant-vultr/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module Vultr
5
+ module Action
6
+ class Create
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::vultr::create')
14
+ end
15
+
16
+ def call(env)
17
+ region = env[:machine].provider_config.region
18
+ plan = env[:machine].provider_config.plan
19
+ os = env[:machine].provider_config.os
20
+ snapshot = env[:machine].provider_config.snapshot
21
+
22
+ @logger.info "Creating server with:"
23
+ @logger.info " -- Region: #{region}"
24
+ @logger.info " -- OS: #{os}"
25
+ @logger.info " -- Plan: #{plan}"
26
+ @logger.info " -- Snapshot: #{snapshot}"
27
+
28
+ attributes = {
29
+ region: region,
30
+ os: os,
31
+ plan: plan,
32
+ snapshot: snapshot,
33
+ ssh_key_name: Action::SetupSSHKey::NAME
34
+ }
35
+ @machine.id = @client.create_server(attributes)
36
+
37
+ env[:ui].info 'Waiting for subcription to become active...'
38
+ @client.wait_to_activate(@machine.id)
39
+
40
+ env[:ui].info 'Waiting for server to start...'
41
+ @client.wait_to_power_on(@machine.id)
42
+
43
+ env[:ui].info 'Waiting for SSH to become active...'
44
+ @client.wait_for_ssh(@machine)
45
+
46
+ env[:ui].info 'Machine is booted and ready to use!'
47
+
48
+ @app.call(env)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,30 @@
1
+ require 'vagrant-vultr/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module Vultr
5
+ module Action
6
+ class Destroy
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::vultr::destroy')
14
+ end
15
+
16
+ def call(env)
17
+ @client.destroy_server(@machine.id)
18
+
19
+ env[:ui].info 'Waiting for server to be destroyed...'
20
+ @client.wait_to_destroy(@machine.id)
21
+
22
+ env[:ui].info 'Machine is destroyed.'
23
+ @machine.id = nil
24
+
25
+ @app.call(env)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,25 @@
1
+ require 'vagrant-vultr/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module Vultr
5
+ module Action
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::vultr::power_off')
14
+ end
15
+
16
+ def call(env)
17
+ @client.stop_server(@machine.id)
18
+ env[:ui].info 'Machine is stopped.'
19
+
20
+ @app.call(env)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ require 'vagrant-vultr/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module Vultr
5
+ module Action
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::vultr::power_on')
14
+ end
15
+
16
+ def call(env)
17
+ @client.start_server(@machine.id)
18
+
19
+ env[:ui].info 'Waiting for server to start...'
20
+ @client.wait_to_power_on(@machine.id)
21
+
22
+ env[:ui].info 'Waiting for SSH to become active...'
23
+ @client.wait_for_ssh(@machine)
24
+
25
+ env[:ui].info 'Machine is booted and ready to use!'
26
+
27
+ @app.call(env)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ require 'vagrant-vultr/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module Vultr
5
+ module Action
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::vultr::reload')
14
+ end
15
+
16
+ def call(env)
17
+ @client.reboot_server(@machine.id)
18
+ env[:ui].info 'Machine is stopped.'
19
+
20
+ env[:ui].info 'Waiting for server to start...'
21
+ @client.wait_to_power_on(@machine.id)
22
+ env[:ui].info 'Waiting for SSH to become active...'
23
+ @client.wait_for_ssh(@machine)
24
+
25
+ env[:ui].info 'Machine is booted and ready to use!'
26
+
27
+ @app.call(env)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ require 'vagrant-vultr/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module Vultr
5
+ module Action
6
+ class SetupSSHKey
7
+ include Helpers::Client
8
+
9
+ NAME = 'vagrant'.freeze
10
+
11
+ def initialize(app, env)
12
+ @app = app
13
+ @machine = env[:machine]
14
+ @client = client
15
+ @logger = Log4r::Logger.new('vagrant::vultr::setup_ssh_key')
16
+ end
17
+
18
+ def call(env)
19
+ ssh_key_id = @client.ssh_key_id(NAME)
20
+ unless ssh_key_id
21
+ @logger.info 'SSH key does not exist. Creating new one...'
22
+ key_path = File.expand_path("#{env[:machine].config.ssh.private_key_path.first}.pub")
23
+ ssh_key_id = @client.create_ssh_key(NAME, File.read(key_path))
24
+ end
25
+ @logger.info "Using SSH key: #{ssh_key_id}."
26
+
27
+ @app.call(env)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,54 @@
1
+ module VagrantPlugins
2
+ module Vultr
3
+ class Config < Vagrant.plugin(2, :config)
4
+ attr_accessor :token
5
+ attr_accessor :region
6
+ attr_accessor :os
7
+ attr_accessor :snapshot
8
+ attr_accessor :plan
9
+
10
+ # @api private
11
+ attr_accessor :ssh_key_id
12
+
13
+ def initialize
14
+ @token = UNSET_VALUE
15
+ @region = UNSET_VALUE
16
+ @os = UNSET_VALUE
17
+ @snapshot = UNSET_VALUE
18
+ @plan = UNSET_VALUE
19
+ end
20
+
21
+ def finalize!
22
+ @token = ENV['VULTR_TOKEN'] if @token == UNSET_VALUE
23
+ @region = 'Seattle' if @region == UNSET_VALUE
24
+ @os = 'Ubuntu 14.04 x64' if @os == UNSET_VALUE && @snapshot == UNSET_VALUE
25
+ @plan = '768 MB RAM,15 GB SSD,1.00 TB BW' if @plan == UNSET_VALUE
26
+ @snapshot = nil if @snapshot == UNSET_VALUE
27
+ end
28
+
29
+ def validate(machine)
30
+ errors = []
31
+
32
+ key = machine.config.ssh.private_key_path
33
+ key = key.first if key.is_a?(Array)
34
+ if !key
35
+ errors << 'You have to specify config.ssh.private_key_path.'
36
+ elsif !File.file?(File.expand_path("#{key}.pub", machine.env.root_path))
37
+ errors << "Cannot find SSH public key: #{key}.pub."
38
+ end
39
+
40
+ if both_os_and_snapshot_provided?
41
+ errors << 'You have to specify one of provider.os or provider.snapshot.'
42
+ end
43
+
44
+ {'vultr' => errors}
45
+ end
46
+
47
+ private
48
+
49
+ def both_os_and_snapshot_provided?
50
+ @os != UNSET_VALUE && @snapshot
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,153 @@
1
+ require 'vultr'
2
+ require 'vagrant/util/retryable'
3
+
4
+ module VagrantPlugins
5
+ module Vultr
6
+ module Helpers
7
+ module Client
8
+ def client
9
+ @client ||= ApiClient.new(@machine.provider_config.token)
10
+ end
11
+ end
12
+
13
+
14
+ class ApiClient
15
+ include Vagrant::Util::Retryable
16
+
17
+ TimeoutError = Class.new(StandardError)
18
+
19
+ TIMEOUT = 300
20
+
21
+ def initialize(token)
22
+ ::Vultr.api_key = token
23
+ end
24
+
25
+ def servers
26
+ servers = request { ::Vultr::Server.list }
27
+ servers = servers.values if servers.any?
28
+
29
+ servers
30
+ end
31
+
32
+ def server(sub_id)
33
+ servers.find { |server| server['SUBID'] == sub_id }
34
+ end
35
+
36
+ def create_server(attributes)
37
+ params = {
38
+ DCID: region_id(attributes[:region]),
39
+ VPSPLANID: vps_plan_id(attributes[:plan]),
40
+ SSHKEYID: ssh_key_id(attributes[:ssh_key_name])
41
+ }
42
+
43
+ if attributes[:snapshot]
44
+ params.merge!(OSID: os_id('Snapshot'), SNAPSHOTID: attributes[:snapshot])
45
+ else
46
+ params.merge!(OSID: os_id(attributes[:os]))
47
+ end
48
+
49
+ request { ::Vultr::Server.create(params) }['SUBID']
50
+ end
51
+
52
+ def start_server(sub_id)
53
+ request { ::Vultr::Server.start(SUBID: sub_id) }
54
+ end
55
+
56
+ def reboot_server(sub_id)
57
+ request { ::Vultr::Server.reboot(SUBID: sub_id) }
58
+ end
59
+
60
+ def stop_server(sub_id)
61
+ request { ::Vultr::Server.halt(SUBID: sub_id) }
62
+ end
63
+
64
+ def destroy_server(sub_id)
65
+ request { ::Vultr::Server.destroy(SUBID: sub_id) }
66
+ end
67
+
68
+ def oses
69
+ request { ::Vultr::OS.list }.values
70
+ end
71
+
72
+ def os_id(os)
73
+ oses.find { |o| o['name'] == os }['OSID']
74
+ end
75
+
76
+ def regions
77
+ request { ::Vultr::Region.list }.values
78
+ end
79
+
80
+ def region_id(region)
81
+ regions.find { |r| r['name'] == region }['DCID']
82
+ end
83
+
84
+ def vps_plan_id(plan)
85
+ plans = request { ::Vultr::Plan.list }
86
+ plans.values.find { |p| p['name'] = plan }['VPSPLANID']
87
+ end
88
+
89
+ def ssh_keys
90
+ ssh_keys = request { ::Vultr::SSHKey.list }
91
+ ssh_keys = ssh_keys.values if ssh_keys.any?
92
+
93
+ ssh_keys
94
+ end
95
+
96
+ def ssh_key_id(ssh_key_name)
97
+ key = ssh_keys.find { |s| s['name'] == ssh_key_name }
98
+ key['SSHKEYID'] if key
99
+ end
100
+
101
+ def create_ssh_key(name, key)
102
+ request { ::Vultr::SSHKey.create(name: name, ssh_key: key) }['SSHKEYID']
103
+ end
104
+
105
+ def wait_to_activate(sub_id)
106
+ wait_until do
107
+ # it might be not shown in API for some reason
108
+ server = server(sub_id)
109
+ server && server['status'] == 'active'
110
+ end
111
+ end
112
+
113
+ def wait_to_power_on(sub_id)
114
+ wait_until do
115
+ # it might be not shown in API for some reason
116
+ server = server(sub_id)
117
+ server && server['power_status'] == 'running'
118
+ end
119
+ end
120
+
121
+ def wait_to_destroy(sub_id)
122
+ wait_until { !server(sub_id) }
123
+ end
124
+
125
+ # @todo Fix the case when SSH key is not ready so it asks for password
126
+ # @todo Extract away from client?
127
+ def wait_for_ssh(machine)
128
+ # SSH may be unreachable after server is started
129
+ wait_until(Errno::ENETUNREACH) do
130
+ machine.communicate.wait_for_ready(Helpers::ApiClient::TIMEOUT)
131
+ end
132
+ end
133
+
134
+ private
135
+
136
+ def request
137
+ response = yield
138
+ if response[:status] != 200
139
+ raise "API request failed: #{response[:result]}."
140
+ else
141
+ response[:result]
142
+ end
143
+ end
144
+
145
+ def wait_until(exception = TimeoutError)
146
+ retryable(tries: TIMEOUT, sleep: 1, on: exception) do
147
+ yield or raise exception
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,18 @@
1
+ module VagrantPlugins
2
+ module Vultr
3
+ class Plugin < Vagrant.plugin(2)
4
+ name 'vagrant-vultr'
5
+ description 'Plugin allows to use Vultr as provider'
6
+
7
+ config(:vultr, :provider) do
8
+ require_relative 'config'
9
+ Config
10
+ end
11
+
12
+ provider(:vultr) do
13
+ require_relative 'provider'
14
+ Provider
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,48 @@
1
+ require 'vagrant-vultr/helpers/client'
2
+
3
+ module VagrantPlugins
4
+ module Vultr
5
+ class Provider < Vagrant.plugin(2, :provider)
6
+ include Helpers::Client
7
+
8
+ def initialize(machine)
9
+ @machine = machine
10
+ @client = client
11
+ end
12
+
13
+ def action(name)
14
+ return unless Action.respond_to?(name)
15
+ Action.__send__(name)
16
+ end
17
+
18
+ def state
19
+ server = @client.server(@machine.id)
20
+
21
+ if server
22
+ if server['status'] == 'active' && server['power_status'] == 'running'
23
+ state = :active
24
+ else
25
+ state = :off
26
+ end
27
+ else
28
+ state = :not_created
29
+ end
30
+
31
+ long = short = state.to_s
32
+ Vagrant::MachineState.new(state, short, long)
33
+ end
34
+
35
+ def ssh_info
36
+ server = @client.server(@machine.id)
37
+ return if server['status'] != 'active' && server['power_status'] != 'running'
38
+
39
+ {
40
+ host: server['main_ip'],
41
+ port: '22',
42
+ username: 'root',
43
+ PasswordAuthentication: 'no'
44
+ }
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'vagrant-vultr'
5
+ spec.version = '0.1.0'
6
+ spec.author = 'Alex Rodionov'
7
+ spec.email = 'p0deje@gmail.com'
8
+ spec.homepage = 'http://github.com/p0deje/vagrant-vultr'
9
+ spec.summary = 'Vultr provider for Vagrant'
10
+ spec.description = 'Vagrant plugin to use Vultr as provider'
11
+ spec.license = 'MIT'
12
+
13
+ spec.files = `git ls-files`.split("\n")
14
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ spec.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
16
+ spec.require_paths = %w[lib]
17
+
18
+ spec.add_dependency 'vultr'
19
+
20
+ spec.add_development_dependency 'aruba'
21
+ spec.add_development_dependency 'pry'
22
+ spec.add_development_dependency 'rake'
23
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-vultr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alex Rodionov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: vultr
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aruba
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Vagrant plugin to use Vultr as provider
70
+ email: p0deje@gmail.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - .gitignore
76
+ - .projections.json
77
+ - CHANGELOG.md
78
+ - Gemfile
79
+ - LICENSE.md
80
+ - README.md
81
+ - Rakefile
82
+ - box/vultr.box
83
+ - features/support/env.rb
84
+ - features/vagrant-vultr.feature
85
+ - lib/vagrant-vultr.rb
86
+ - lib/vagrant-vultr/action.rb
87
+ - lib/vagrant-vultr/action/check_state.rb
88
+ - lib/vagrant-vultr/action/create.rb
89
+ - lib/vagrant-vultr/action/destroy.rb
90
+ - lib/vagrant-vultr/action/power_off.rb
91
+ - lib/vagrant-vultr/action/power_on.rb
92
+ - lib/vagrant-vultr/action/reload.rb
93
+ - lib/vagrant-vultr/action/setup_ssh_key.rb
94
+ - lib/vagrant-vultr/config.rb
95
+ - lib/vagrant-vultr/helpers/client.rb
96
+ - lib/vagrant-vultr/plugin.rb
97
+ - lib/vagrant-vultr/provider.rb
98
+ - vagrant-vultr.gemspec
99
+ homepage: http://github.com/p0deje/vagrant-vultr
100
+ licenses:
101
+ - MIT
102
+ metadata: {}
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 2.0.14
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: Vultr provider for Vagrant
123
+ test_files:
124
+ - features/support/env.rb
125
+ - features/vagrant-vultr.feature