vagrant-vultr_pro 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.projections.json +4 -0
- data/CHANGELOG.md +23 -0
- data/Gemfile +9 -0
- data/LICENSE.md +20 -0
- data/README.md +116 -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/action/check_state.rb +20 -0
- data/lib/vagrant-vultr/action/create.rb +73 -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 +31 -0
- data/lib/vagrant-vultr/action.rb +132 -0
- data/lib/vagrant-vultr/config.rb +76 -0
- data/lib/vagrant-vultr/helpers/client.rb +156 -0
- data/lib/vagrant-vultr/plugin.rb +18 -0
- data/lib/vagrant-vultr/provider.rb +48 -0
- data/lib/vagrant-vultr_pro.rb +12 -0
- data/lib/vultr/version.rb +10 -0
- data/lib/vultr/vultr.rb +888 -0
- data/vagrant-vultr_pro.gemspec +24 -0
- metadata +152 -0
@@ -0,0 +1,76 @@
|
|
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
|
+
attr_accessor :label
|
12
|
+
attr_accessor :tag
|
13
|
+
attr_accessor :hostname
|
14
|
+
attr_accessor :timeout
|
15
|
+
attr_accessor :ssh_key
|
16
|
+
attr_accessor :startup_script
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@token = UNSET_VALUE
|
20
|
+
@region = UNSET_VALUE
|
21
|
+
@os = UNSET_VALUE
|
22
|
+
@snapshot = UNSET_VALUE
|
23
|
+
@plan = UNSET_VALUE
|
24
|
+
@enable_ipv6 = UNSET_VALUE
|
25
|
+
@enable_private_network = UNSET_VALUE
|
26
|
+
@label = UNSET_VALUE
|
27
|
+
@tag = UNSET_VALUE
|
28
|
+
@hostname = UNSET_VALUE
|
29
|
+
@timeout = UNSET_VALUE
|
30
|
+
@ssh_key = UNSET_VALUE
|
31
|
+
@startup_script = UNSET_VALUE
|
32
|
+
end
|
33
|
+
|
34
|
+
def finalize!
|
35
|
+
@token = ENV['VULTR_TOKEN'] if @token == UNSET_VALUE
|
36
|
+
@region = 'Seattle' if @region == UNSET_VALUE
|
37
|
+
@os = 'Ubuntu 14.04 x64' if @os == UNSET_VALUE && @snapshot == UNSET_VALUE
|
38
|
+
@plan = '768 MB RAM,15 GB SSD,1.00 TB BW' if @plan == UNSET_VALUE
|
39
|
+
@snapshot = nil if @snapshot == UNSET_VALUE
|
40
|
+
@enable_ipv6 = 'no' if @enable_ipv6 == UNSET_VALUE
|
41
|
+
@enable_private_network = 'no' if @enable_private_network == UNSET_VALUE
|
42
|
+
@label = '' if @label == UNSET_VALUE
|
43
|
+
@tag = '' if @tag == UNSET_VALUE
|
44
|
+
@hostname = '' if @hostname == UNSET_VALUE
|
45
|
+
@script = '' if @script == UNSET_VALUE
|
46
|
+
@timeout = 300 if @timeout == UNSET_VALUE
|
47
|
+
@ssh_key = 'vagrant' if @ssh_key == UNSET_VALUE
|
48
|
+
@startup_script = '' if @startup_script == UNSET_VALUE
|
49
|
+
end
|
50
|
+
|
51
|
+
def validate(machine)
|
52
|
+
errors = []
|
53
|
+
|
54
|
+
key = machine.config.ssh.private_key_path
|
55
|
+
key = key.first if key.is_a?(Array)
|
56
|
+
if !key
|
57
|
+
errors << 'You have to specify config.ssh.private_key_path.'
|
58
|
+
elsif !File.file?(File.expand_path("#{key}.pub", machine.env.root_path))
|
59
|
+
errors << "Cannot find SSH public key: #{key}.pub."
|
60
|
+
end
|
61
|
+
|
62
|
+
if both_os_and_snapshot_provided?
|
63
|
+
errors << 'You have to specify one of provider.os or provider.snapshot.'
|
64
|
+
end
|
65
|
+
|
66
|
+
{'vultr' => errors}
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def both_os_and_snapshot_provided?
|
72
|
+
@os != UNSET_VALUE && @snapshot
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'vultr/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, @machine.provider_config.timeout)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
class ApiClient
|
15
|
+
include Vagrant::Util::Retryable
|
16
|
+
|
17
|
+
TimeoutError = Class.new(StandardError)
|
18
|
+
|
19
|
+
def initialize(token, timeout)
|
20
|
+
::Vultr.api_key = token
|
21
|
+
@timeout = timeout || 300
|
22
|
+
end
|
23
|
+
|
24
|
+
def servers
|
25
|
+
servers = request { ::Vultr::Server.list }
|
26
|
+
servers = servers.values if servers.any?
|
27
|
+
|
28
|
+
servers
|
29
|
+
end
|
30
|
+
|
31
|
+
def server(sub_id)
|
32
|
+
servers.find { |server| server['SUBID'] == sub_id }
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_server(attributes)
|
36
|
+
params = {
|
37
|
+
DCID: region_id(attributes[:region]),
|
38
|
+
VPSPLANID: vps_plan_id(attributes[:plan]),
|
39
|
+
SSHKEYID: ssh_key_id(attributes[:ssh_key_name]),
|
40
|
+
SCRIPTID: startup_script_id(attributes[:startup_script_name]),
|
41
|
+
enable_ipv6: attributes[:enable_ipv6],
|
42
|
+
enable_private_network: attributes[:enable_private_network],
|
43
|
+
label: attributes[:label],
|
44
|
+
tag: attributes[:tag],
|
45
|
+
hostname: attributes[:hostname]
|
46
|
+
}
|
47
|
+
|
48
|
+
if attributes[:snapshot]
|
49
|
+
params.merge!(OSID: os_id('Snapshot'), SNAPSHOTID: attributes[:snapshot])
|
50
|
+
else
|
51
|
+
params.merge!(OSID: os_id(attributes[:os]))
|
52
|
+
end
|
53
|
+
|
54
|
+
request { ::Vultr::Server.create(params) }['SUBID']
|
55
|
+
end
|
56
|
+
|
57
|
+
def start_server(sub_id)
|
58
|
+
request { ::Vultr::Server.start(SUBID: sub_id) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def reboot_server(sub_id)
|
62
|
+
request { ::Vultr::Server.reboot(SUBID: sub_id) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def stop_server(sub_id)
|
66
|
+
request { ::Vultr::Server.halt(SUBID: sub_id) }
|
67
|
+
end
|
68
|
+
|
69
|
+
def destroy_server(sub_id)
|
70
|
+
request { ::Vultr::Server.destroy(SUBID: sub_id) }
|
71
|
+
end
|
72
|
+
|
73
|
+
def os_id(os)
|
74
|
+
oses = request { ::Vultr::OS.list }
|
75
|
+
oses.values.find { |o| o['name'] == os }['OSID']
|
76
|
+
end
|
77
|
+
|
78
|
+
def region_id(region)
|
79
|
+
regions = request { ::Vultr::Regions.list }
|
80
|
+
regions.values.find { |r| r['name'] == region }['DCID']
|
81
|
+
end
|
82
|
+
|
83
|
+
def vps_plan_id(plan)
|
84
|
+
plans = request { ::Vultr::Plans.list }
|
85
|
+
plans.values.find { |p| p['name'] == plan }['VPSPLANID']
|
86
|
+
end
|
87
|
+
|
88
|
+
def startup_script_id(startup_script_name)
|
89
|
+
scripts = request { ::Vultr::StartupScript.list }
|
90
|
+
script = scripts.values.find { |s| s['name'] == startup_script_name }
|
91
|
+
script['SCRIPTID'] if script
|
92
|
+
end
|
93
|
+
|
94
|
+
def ssh_key_id(ssh_key_name)
|
95
|
+
ssh_keys = request { ::Vultr::SSHKey.list }
|
96
|
+
ssh_key = ssh_keys.values.find { |s| s['name'] == ssh_key_name }
|
97
|
+
ssh_key['SSHKEYID'] if ssh_key
|
98
|
+
end
|
99
|
+
|
100
|
+
def create_ssh_key(name, key)
|
101
|
+
request { ::Vultr::SSHKey.create(name: name, ssh_key: key) }['SSHKEYID']
|
102
|
+
end
|
103
|
+
|
104
|
+
def wait_to_activate(sub_id)
|
105
|
+
wait_until do
|
106
|
+
# it might be not shown in API for some reason
|
107
|
+
server = server(sub_id)
|
108
|
+
server && server['status'] == 'active'
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def wait_to_power_on(sub_id)
|
113
|
+
wait_until do
|
114
|
+
# it might be not shown in API for some reason
|
115
|
+
server = server(sub_id)
|
116
|
+
server && server['status'] == 'active' && server['power_status'] == 'running' && server['server_state'] == 'ok'
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def wait_to_destroy(sub_id)
|
121
|
+
wait_until { !server(sub_id) }
|
122
|
+
end
|
123
|
+
|
124
|
+
# @todo Fix the case when SSH key is not ready so it asks for password
|
125
|
+
# @todo Extract away from client?
|
126
|
+
def wait_for_ssh(machine)
|
127
|
+
# SSH may be unreachable after server is started
|
128
|
+
wait_until(Errno::ENETUNREACH) do
|
129
|
+
machine.communicate.wait_for_ready(@timeout)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def request
|
136
|
+
if interval = ENV['VULTR_RATE_LIMIT_INTERVAL_MS']
|
137
|
+
sleep interval.to_f / 1000
|
138
|
+
end
|
139
|
+
|
140
|
+
response = yield
|
141
|
+
if response[:status] != 200
|
142
|
+
raise "API request failed: #{response[:result]}."
|
143
|
+
else
|
144
|
+
response[:result]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def wait_until(exception = TimeoutError)
|
149
|
+
retryable(tries: @timeout, sleep: 1, on: exception) do
|
150
|
+
yield or raise exception
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Vultr
|
3
|
+
class Plugin < Vagrant.plugin(2)
|
4
|
+
name 'vagrant-vultr_pro'
|
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
|