vagrant-vultr2 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2ba1192c25d006d33f5d4a7b9316339619e3a5ca
4
+ data.tar.gz: 5fdeb95ba2093e709c64a22a6443c48c6841752d
5
+ SHA512:
6
+ metadata.gz: 75bd0ae30a0c4ae5a6eafa03ab02f7c8f64c0332a70065738de76516bdb42947bbd7afb2492de183a394d389a49dd2c039c1817fc91e7b520e383aad0fd53c2b
7
+ data.tar.gz: 2f0c14a155a27b141a5d1483d9fe09a6a384f29b808da37e37f3d72833472a5fb47252d3af8c6f3dcb1ce1f03caaf25fc6e550b43700c4a4070b7b4614227923
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ pkg/
2
+ tmp/
3
+ .bundle/
4
+ vendor/bundle/
5
+ .vagrant/
6
+ Gemfile.lock
7
+ .envrc
8
+ .ruby-version
data/.projections.json ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "lib/vagrant-vultr/action.rb": {"type": "action"},
3
+ "lib/vagrant-vultr/action/*.rb": {"type": "action"}
4
+ }
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ ## 0.1.2
2
+
3
+ * Fixed issues with renamed Vultr API (#4, #5)
4
+
5
+ ## 0.1.1
6
+
7
+ * Fix issue with plan selection (#1)
8
+
9
+ ## 0.1.0
10
+
11
+ * 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
data/LICENSE.md ADDED
@@ -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.
data/README.md ADDED
@@ -0,0 +1,91 @@
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
+ 3. If you hit API rate limit, you can set `VULTR_RATE_LIMIT_INTERVAL_MS` environment variable to introduce delay between API requests.
50
+
51
+ Testing
52
+ -------
53
+
54
+ First of all, add the box that is used for testing:
55
+
56
+ ```bash
57
+ $ bundle exec rake box:add
58
+ ```
59
+
60
+ Since the tests involve actual calls to Vultr, you have to provide a valid API token:
61
+
62
+ ```bash
63
+ $ export VULTR_TOKEN="token"
64
+ ```
65
+
66
+ Now you can run tests:
67
+
68
+ ```bash
69
+ $ bundle exec rake cucumber
70
+ ```
71
+
72
+ Note that Vultr is not very stable, so tests sometimes may fail due to timeout or 404 API requests.
73
+
74
+ In the end, remove the box:
75
+
76
+ ```bash
77
+ $ bundle exec rake box:remove
78
+ ```
79
+
80
+ Contributing
81
+ ------------
82
+
83
+ * Fork the project.
84
+ * Make your feature addition or bug fix.
85
+ * 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.
86
+ * Send me a pull request. Bonus points for topic branches.
87
+
88
+ Copyright
89
+ ---------
90
+
91
+ Copyright (c) 2015 Alex Rodionov. See LICENSE.md for details.
data/Rakefile ADDED
@@ -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
data/box/vultr.box ADDED
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,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,59 @@
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
+ enable_ipv6 = env[:machine].provider_config.enable_ipv6
22
+ enable_private_network = env[:machine].provider_config.enable_private_network
23
+
24
+ @logger.info "Creating server with:"
25
+ @logger.info " -- Region: #{region}"
26
+ @logger.info " -- OS: #{os}"
27
+ @logger.info " -- Plan: #{plan}"
28
+ @logger.info " -- Snapshot: #{snapshot}"
29
+ @logger.info " -- Enable IPv6: #{enable_ipv6}"
30
+ @logger.info " -- Enable Private Network: #{enable_private_network}"
31
+
32
+ attributes = {
33
+ region: region,
34
+ os: os,
35
+ plan: plan,
36
+ snapshot: snapshot,
37
+ enable_ipv6: enable_ipv6,
38
+ enable_private_network: enable_private_network,
39
+ ssh_key_name: Action::SetupSSHKey::NAME
40
+ }
41
+ @machine.id = @client.create_server(attributes)
42
+
43
+ env[:ui].info 'Waiting for subcription to become active...'
44
+ @client.wait_to_activate(@machine.id)
45
+
46
+ env[:ui].info 'Waiting for server to start...'
47
+ @client.wait_to_power_on(@machine.id)
48
+
49
+ env[:ui].info 'Waiting for SSH to become active...'
50
+ @client.wait_for_ssh(@machine)
51
+
52
+ env[:ui].info 'Machine is booted and ready to use!'
53
+
54
+ @app.call(env)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ 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,60 @@
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
+ attr_accessor :enable_ipv6
10
+ attr_accessor :enable_private_network
11
+
12
+ # @api private
13
+ attr_accessor :ssh_key_id
14
+
15
+ def initialize
16
+ @token = UNSET_VALUE
17
+ @region = UNSET_VALUE
18
+ @os = UNSET_VALUE
19
+ @snapshot = UNSET_VALUE
20
+ @plan = UNSET_VALUE
21
+ @enable_ipv6 = UNSET_VALUE
22
+ @enable_private_network = UNSET_VALUE
23
+ end
24
+
25
+ def finalize!
26
+ @token = ENV['VULTR_TOKEN'] if @token == UNSET_VALUE
27
+ @region = 'Seattle' if @region == UNSET_VALUE
28
+ @os = 'Ubuntu 14.04 x64' if @os == UNSET_VALUE && @snapshot == UNSET_VALUE
29
+ @plan = '768 MB RAM,15 GB SSD,1.00 TB BW' if @plan == UNSET_VALUE
30
+ @snapshot = nil if @snapshot == UNSET_VALUE
31
+ @enable_ipv6 = 'no' if @enable_ipv6 == UNSET_VALUE
32
+ @enable_private_network = 'no' if @enable_private_network == UNSET_VALUE
33
+ end
34
+
35
+ def validate(machine)
36
+ errors = []
37
+
38
+ key = machine.config.ssh.private_key_path
39
+ key = key.first if key.is_a?(Array)
40
+ if !key
41
+ errors << 'You have to specify config.ssh.private_key_path.'
42
+ elsif !File.file?(File.expand_path("#{key}.pub", machine.env.root_path))
43
+ errors << "Cannot find SSH public key: #{key}.pub."
44
+ end
45
+
46
+ if both_os_and_snapshot_provided?
47
+ errors << 'You have to specify one of provider.os or provider.snapshot.'
48
+ end
49
+
50
+ {'vultr' => errors}
51
+ end
52
+
53
+ private
54
+
55
+ def both_os_and_snapshot_provided?
56
+ @os != UNSET_VALUE && @snapshot
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,159 @@
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
+ enable_ipv6: attributes[:enable_ipv6],
42
+ enable_private_network: attributes[:enable_private_network]
43
+ }
44
+
45
+ if attributes[:snapshot]
46
+ params.merge!(OSID: os_id('Snapshot'), SNAPSHOTID: attributes[:snapshot])
47
+ else
48
+ params.merge!(OSID: os_id(attributes[:os]))
49
+ end
50
+
51
+ request { ::Vultr::Server.create(params) }['SUBID']
52
+ end
53
+
54
+ def start_server(sub_id)
55
+ request { ::Vultr::Server.start(SUBID: sub_id) }
56
+ end
57
+
58
+ def reboot_server(sub_id)
59
+ request { ::Vultr::Server.reboot(SUBID: sub_id) }
60
+ end
61
+
62
+ def stop_server(sub_id)
63
+ request { ::Vultr::Server.halt(SUBID: sub_id) }
64
+ end
65
+
66
+ def destroy_server(sub_id)
67
+ request { ::Vultr::Server.destroy(SUBID: sub_id) }
68
+ end
69
+
70
+ def oses
71
+ request { ::Vultr::OS.list }.values
72
+ end
73
+
74
+ def os_id(os)
75
+ oses.find { |o| o['name'] == os }['OSID']
76
+ end
77
+
78
+ def regions
79
+ request { ::Vultr::Regions.list }.values
80
+ end
81
+
82
+ def region_id(region)
83
+ regions.find { |r| r['name'] == region }['DCID']
84
+ end
85
+
86
+ def vps_plan_id(plan)
87
+ plans = request { ::Vultr::Plans.list }
88
+ plans.values.find { |p| p['name'] == plan }['VPSPLANID']
89
+ end
90
+
91
+ def ssh_keys
92
+ ssh_keys = request { ::Vultr::SSHKey.list }
93
+ ssh_keys = ssh_keys.values if ssh_keys.any?
94
+
95
+ ssh_keys
96
+ end
97
+
98
+ def ssh_key_id(ssh_key_name)
99
+ key = ssh_keys.find { |s| s['name'] == ssh_key_name }
100
+ key['SSHKEYID'] if key
101
+ end
102
+
103
+ def create_ssh_key(name, key)
104
+ request { ::Vultr::SSHKey.create(name: name, ssh_key: key) }['SSHKEYID']
105
+ end
106
+
107
+ def wait_to_activate(sub_id)
108
+ wait_until do
109
+ # it might be not shown in API for some reason
110
+ server = server(sub_id)
111
+ server && server['status'] == 'active'
112
+ end
113
+ end
114
+
115
+ def wait_to_power_on(sub_id)
116
+ wait_until do
117
+ # it might be not shown in API for some reason
118
+ server = server(sub_id)
119
+ server && server['power_status'] == 'running'
120
+ end
121
+ end
122
+
123
+ def wait_to_destroy(sub_id)
124
+ wait_until { !server(sub_id) }
125
+ end
126
+
127
+ # @todo Fix the case when SSH key is not ready so it asks for password
128
+ # @todo Extract away from client?
129
+ def wait_for_ssh(machine)
130
+ # SSH may be unreachable after server is started
131
+ wait_until(Errno::ENETUNREACH) do
132
+ machine.communicate.wait_for_ready(Helpers::ApiClient::TIMEOUT)
133
+ end
134
+ end
135
+
136
+ private
137
+
138
+ def request
139
+ if interval = ENV['VULTR_RATE_LIMIT_INTERVAL_MS']
140
+ sleep interval.to_f / 1000
141
+ end
142
+
143
+ response = yield
144
+ if response[:status] != 200
145
+ raise "API request failed: #{response[:result]}."
146
+ else
147
+ response[:result]
148
+ end
149
+ end
150
+
151
+ def wait_until(exception = TimeoutError)
152
+ retryable(tries: TIMEOUT, sleep: 1, on: exception) do
153
+ yield or raise exception
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+ 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,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,23 @@
1
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'vagrant-vultr2'
5
+ spec.version = '0.1.4'
6
+ spec.author = 'Alex Rodionov'
7
+ spec.email = 'p0deje@gmail.com'
8
+ spec.homepage = 'http://github.com/artemave/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-vultr2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4
5
+ platform: ruby
6
+ authors:
7
+ - Alex Rodionov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-03-15 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/action.rb
86
+ - lib/vagrant-vultr/action/check_state.rb
87
+ - lib/vagrant-vultr/action/create.rb
88
+ - lib/vagrant-vultr/action/destroy.rb
89
+ - lib/vagrant-vultr/action/power_off.rb
90
+ - lib/vagrant-vultr/action/power_on.rb
91
+ - lib/vagrant-vultr/action/reload.rb
92
+ - lib/vagrant-vultr/action/setup_ssh_key.rb
93
+ - lib/vagrant-vultr/config.rb
94
+ - lib/vagrant-vultr/helpers/client.rb
95
+ - lib/vagrant-vultr/plugin.rb
96
+ - lib/vagrant-vultr/provider.rb
97
+ - lib/vagrant-vultr2.rb
98
+ - vagrant-vultr2.gemspec
99
+ homepage: http://github.com/artemave/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.6.8
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