vagrant-vultr 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.projections.json +4 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +9 -0
- data/LICENSE.md +20 -0
- data/README.md +90 -0
- data/Rakefile +17 -0
- data/box/vultr.box +0 -0
- data/features/support/env.rb +11 -0
- data/features/vagrant-vultr.feature +78 -0
- data/lib/vagrant-vultr.rb +12 -0
- data/lib/vagrant-vultr/action.rb +132 -0
- data/lib/vagrant-vultr/action/check_state.rb +20 -0
- data/lib/vagrant-vultr/action/create.rb +53 -0
- data/lib/vagrant-vultr/action/destroy.rb +30 -0
- data/lib/vagrant-vultr/action/power_off.rb +25 -0
- data/lib/vagrant-vultr/action/power_on.rb +32 -0
- data/lib/vagrant-vultr/action/reload.rb +32 -0
- data/lib/vagrant-vultr/action/setup_ssh_key.rb +32 -0
- data/lib/vagrant-vultr/config.rb +54 -0
- data/lib/vagrant-vultr/helpers/client.rb +153 -0
- data/lib/vagrant-vultr/plugin.rb +18 -0
- data/lib/vagrant-vultr/provider.rb +48 -0
- data/vagrant-vultr.gemspec +23 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
data/.projections.json
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
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,90 @@
|
|
1
|
+
vagrant-vultr [](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.
|
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,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,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
|