vagrant-scaleway 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.ruby-version +1 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +21 -0
- data/README.md +69 -0
- data/Rakefile +9 -0
- data/dummy.box +0 -0
- data/example_box/metadata.json +3 -0
- data/lib/vagrant-scaleway.rb +17 -0
- data/lib/vagrant-scaleway/action.rb +179 -0
- data/lib/vagrant-scaleway/action/connect_scaleway.rb +34 -0
- data/lib/vagrant-scaleway/action/create_server.rb +75 -0
- data/lib/vagrant-scaleway/action/destroy_server.rb +34 -0
- data/lib/vagrant-scaleway/action/is_created.rb +18 -0
- data/lib/vagrant-scaleway/action/is_stopped.rb +18 -0
- data/lib/vagrant-scaleway/action/message_already_created.rb +16 -0
- data/lib/vagrant-scaleway/action/message_not_created.rb +16 -0
- data/lib/vagrant-scaleway/action/message_will_not_destroy.rb +16 -0
- data/lib/vagrant-scaleway/action/read_ssh_info.rb +50 -0
- data/lib/vagrant-scaleway/action/read_state.rb +36 -0
- data/lib/vagrant-scaleway/action/start_server.rb +90 -0
- data/lib/vagrant-scaleway/action/stop_server.rb +26 -0
- data/lib/vagrant-scaleway/action/warn_networks.rb +19 -0
- data/lib/vagrant-scaleway/config.rb +113 -0
- data/lib/vagrant-scaleway/errors.rb +21 -0
- data/lib/vagrant-scaleway/plugin.rb +73 -0
- data/lib/vagrant-scaleway/provider.rb +47 -0
- data/lib/vagrant-scaleway/util/timer.rb +17 -0
- data/lib/vagrant-scaleway/version.rb +5 -0
- data/locales/en.yml +81 -0
- data/vagrant-scaleway.gemspec +25 -0
- metadata +131 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Scaleway
|
3
|
+
module Action
|
4
|
+
# This destroys the running server.
|
5
|
+
class DestroyServer
|
6
|
+
def initialize(app, _env)
|
7
|
+
@app = app
|
8
|
+
@logger = Log4r::Logger.new('vagrant_scaleway::action::destroy_server')
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
server = env[:scaleway_compute].servers.get(env[:machine].id)
|
13
|
+
|
14
|
+
# Destroy the server and remove the tracking ID
|
15
|
+
env[:ui].info(I18n.t('vagrant_scaleway.destroying'))
|
16
|
+
|
17
|
+
begin
|
18
|
+
server.destroy
|
19
|
+
rescue Fog::Scaleway::Compute::InvalidRequestError => e
|
20
|
+
if e.message =~ /server should be stopped/
|
21
|
+
server.terminate(false)
|
22
|
+
else
|
23
|
+
raise
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
env[:machine].id = nil
|
28
|
+
|
29
|
+
@app.call(env)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Scaleway
|
3
|
+
module Action
|
4
|
+
# This can be used with "Call" built-in to check if the machine
|
5
|
+
# is created and branch in the middleware.
|
6
|
+
class IsCreated
|
7
|
+
def initialize(app, _env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env[:result] = env[:machine].state.id != :not_created
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Scaleway
|
3
|
+
module Action
|
4
|
+
# This can be used with "Call" built-in to check if the machine
|
5
|
+
# is stopped and branch in the middleware.
|
6
|
+
class IsStopped
|
7
|
+
def initialize(app, _env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env[:result] = env[:machine].state.id == :stopped
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Scaleway
|
3
|
+
module Action
|
4
|
+
class MessageAlreadyCreated
|
5
|
+
def initialize(app, _env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env[:ui].info(I18n.t('vagrant_scaleway.already_status', status: 'created'))
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Scaleway
|
3
|
+
module Action
|
4
|
+
class MessageNotCreated
|
5
|
+
def initialize(app, _env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env[:ui].info(I18n.t('vagrant_scaleway.not_created'))
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Scaleway
|
3
|
+
module Action
|
4
|
+
class MessageWillNotDestroy
|
5
|
+
def initialize(app, _env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env[:ui].info(I18n.t('vagrant_scaleway.will_not_destroy', name: env[:machine].name))
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Scaleway
|
3
|
+
module Action
|
4
|
+
# This action reads the SSH info for the machine and puts it into the
|
5
|
+
# `:machine_ssh_info` key in the environment.
|
6
|
+
class ReadSSHInfo
|
7
|
+
def initialize(app, _env)
|
8
|
+
@app = app
|
9
|
+
@logger = Log4r::Logger.new('vagrant_scaleway::action::read_ssh_info')
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
env[:machine_ssh_info] = read_ssh_info(env[:scaleway_compute], env[:machine])
|
14
|
+
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_ssh_info(scaleway, machine)
|
19
|
+
return nil if machine.id.nil?
|
20
|
+
|
21
|
+
# Find the machine
|
22
|
+
server = scaleway.servers.get(machine.id)
|
23
|
+
if server.nil?
|
24
|
+
# The machine can't be found
|
25
|
+
@logger.info("Machine couldn't be found, assuming it got destroyed.")
|
26
|
+
machine.id = nil
|
27
|
+
return nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# read attribute override
|
31
|
+
ssh_host_attribute = machine.provider_config.ssh_host_attribute
|
32
|
+
# default host attributes to try. NOTE: Order matters!
|
33
|
+
ssh_attrs = %i(public_ip_address public_dns_name private_ip_address private_dns_name)
|
34
|
+
ssh_attrs = (Array(ssh_host_attribute) + ssh_attrs).uniq if ssh_host_attribute
|
35
|
+
# try each attribute, get out on first value
|
36
|
+
host = nil
|
37
|
+
while !host && (attr = ssh_attrs.shift)
|
38
|
+
begin
|
39
|
+
host = server.send(attr)
|
40
|
+
rescue NoMethodError
|
41
|
+
@logger.info("SSH host attribute not found #{attr}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
{ host: host, port: 22, username: 'root' }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Scaleway
|
3
|
+
module Action
|
4
|
+
# This action reads the state of the machine and puts it in the
|
5
|
+
# `:machine_state_id` key in the environment.
|
6
|
+
class ReadState
|
7
|
+
def initialize(app, _env)
|
8
|
+
@app = app
|
9
|
+
@logger = Log4r::Logger.new('vagrant_scaleway::action::read_state')
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
env[:machine_state_id] = read_state(env[:scaleway_compute], env[:machine])
|
14
|
+
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_state(scaleway, machine)
|
19
|
+
return :not_created if machine.id.nil?
|
20
|
+
|
21
|
+
# Find the machine
|
22
|
+
server = scaleway.servers.get(machine.id)
|
23
|
+
if server.nil?
|
24
|
+
# The machine can't be found
|
25
|
+
@logger.info('Machine not found, assuming it got destroyed.')
|
26
|
+
machine.id = nil
|
27
|
+
return :not_created
|
28
|
+
end
|
29
|
+
|
30
|
+
# Return the state
|
31
|
+
server.state.to_sym
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'vagrant/util/retryable'
|
2
|
+
require 'vagrant-scaleway/util/timer'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module Scaleway
|
6
|
+
module Action
|
7
|
+
# This starts a stopped server.
|
8
|
+
class StartServer
|
9
|
+
include Vagrant::Util::Retryable
|
10
|
+
|
11
|
+
def initialize(app, _env)
|
12
|
+
@app = app
|
13
|
+
@logger = Log4r::Logger.new('vagrant_scaleway::action::start_server')
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# Initialize metrics if they haven't been
|
18
|
+
env[:metrics] ||= {}
|
19
|
+
|
20
|
+
config = env[:machine].provider_config
|
21
|
+
|
22
|
+
server = env[:scaleway_compute].servers.get(env[:machine].id)
|
23
|
+
|
24
|
+
env[:ui].info(I18n.t('vagrant_scaleway.starting'))
|
25
|
+
|
26
|
+
begin
|
27
|
+
server.poweron
|
28
|
+
rescue Fog::Scaleway::Compute::Error => e
|
29
|
+
raise Errors::FogError, message: e.message
|
30
|
+
end
|
31
|
+
|
32
|
+
# Wait for the server to be ready first
|
33
|
+
env[:metrics]['server_ready_time'] = Util::Timer.time do
|
34
|
+
tries = config.server_ready_timeout / 2
|
35
|
+
|
36
|
+
env[:ui].info(I18n.t('vagrant_scaleway.waiting_for_ready'))
|
37
|
+
begin
|
38
|
+
retryable(on: Fog::Errors::TimeoutError, tries: tries) do
|
39
|
+
# If we're interrupted don't worry about waiting
|
40
|
+
next if env[:interrupted]
|
41
|
+
|
42
|
+
# Wait for the server to be ready
|
43
|
+
server.wait_for(2, config.server_check_interval) { ready? }
|
44
|
+
end
|
45
|
+
rescue Fog::Errors::TimeoutError
|
46
|
+
# Notify the user
|
47
|
+
raise Errors::ServerReadyTimeout,
|
48
|
+
timeout: config.server_ready_timeout
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
@logger.info("Time to server ready: #{env[:metrics]['server_ready_time']}")
|
53
|
+
|
54
|
+
unless env[:interrupted]
|
55
|
+
env[:metrics]['server_ssh_time'] = Util::Timer.time do
|
56
|
+
# Wait for SSH to be ready.
|
57
|
+
env[:ui].info(I18n.t('vagrant_scaleway.waiting_for_ssh'))
|
58
|
+
network_ready_retries = 0
|
59
|
+
network_ready_retries_max = 10
|
60
|
+
loop do
|
61
|
+
# If we're interrupted then just back out
|
62
|
+
break if env[:interrupted]
|
63
|
+
# When a server comes up, it's networking may not be ready by
|
64
|
+
# the time we connect.
|
65
|
+
begin
|
66
|
+
break if env[:machine].communicate.ready?
|
67
|
+
rescue Exception => e
|
68
|
+
if network_ready_retries < network_ready_retries_max
|
69
|
+
network_ready_retries += 1
|
70
|
+
@logger.warn(I18n.t('vagrant_scaleway.waiting_for_ssh, retrying'))
|
71
|
+
else
|
72
|
+
raise e
|
73
|
+
end
|
74
|
+
end
|
75
|
+
sleep 2
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
@logger.info("Time for SSH ready: #{env[:metrics]['server_ssh_time']}")
|
80
|
+
|
81
|
+
# Ready and booted!
|
82
|
+
env[:ui].info(I18n.t('vagrant_scaleway.ready'))
|
83
|
+
end
|
84
|
+
|
85
|
+
@app.call(env)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Scaleway
|
3
|
+
module Action
|
4
|
+
# This stops the running server.
|
5
|
+
class StopServer
|
6
|
+
def initialize(app, _env)
|
7
|
+
@app = app
|
8
|
+
@logger = Log4r::Logger.new('vagrant_scaleway::action::stop_server')
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
server = env[:scaleway_compute].servers.get(env[:machine].id)
|
13
|
+
|
14
|
+
if env[:machine].state.id == :stopped
|
15
|
+
env[:ui].info(I18n.t('vagrant_scaleway.already_status', status: env[:machine].state.id))
|
16
|
+
else
|
17
|
+
env[:ui].info(I18n.t('vagrant_scaleway.stopping'))
|
18
|
+
server.poweroff(false)
|
19
|
+
end
|
20
|
+
|
21
|
+
@app.call(env)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Scaleway
|
3
|
+
module Action
|
4
|
+
class WarnNetworks
|
5
|
+
def initialize(app, _env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
if env[:machine].config.vm.networks.length > 1
|
11
|
+
env[:ui].warn(I18n.t('vagrant_scaleway.warn_networks'))
|
12
|
+
end
|
13
|
+
|
14
|
+
@app.call(env)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Scaleway
|
3
|
+
class Config < Vagrant.plugin('2', :config)
|
4
|
+
# The bootscript ID. If nil, the default bootscript for the image will be
|
5
|
+
# used.
|
6
|
+
#
|
7
|
+
# @return [String]
|
8
|
+
attr_accessor :bootscript
|
9
|
+
|
10
|
+
# The type of the server to launch, such as 'C1'. Defaults to 'C2S'.
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
attr_accessor :commercial_type
|
14
|
+
|
15
|
+
# The image ID.
|
16
|
+
#
|
17
|
+
# @return [String]
|
18
|
+
attr_accessor :image
|
19
|
+
|
20
|
+
# The name of the server.
|
21
|
+
#
|
22
|
+
# @return [String]
|
23
|
+
attr_accessor :name
|
24
|
+
|
25
|
+
# The organization ID. It can also be configured with SCW_ORGANIZATION
|
26
|
+
# environment variable.
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
attr_accessor :organization
|
30
|
+
|
31
|
+
# The security group to associate with the server. If nil, organization's
|
32
|
+
# default security group will be used.
|
33
|
+
#
|
34
|
+
# @return [String]
|
35
|
+
attr_accessor :security_group
|
36
|
+
|
37
|
+
# The interval to wait for checking a server's state. Defaults to 2
|
38
|
+
# seconds.
|
39
|
+
#
|
40
|
+
# @return [Fixnum]
|
41
|
+
attr_accessor :server_check_interval
|
42
|
+
|
43
|
+
# The timeout to wait for a server to become ready. Defaults to 120
|
44
|
+
# seconds.
|
45
|
+
#
|
46
|
+
# @return [Fixnum]
|
47
|
+
attr_accessor :server_ready_timeout
|
48
|
+
|
49
|
+
# Specifies which address to connect to with ssh.
|
50
|
+
# Must be one of:
|
51
|
+
# - :public_ip_address
|
52
|
+
# - :public_dns_name
|
53
|
+
# - :private_ip_address
|
54
|
+
# - :private_dns_name
|
55
|
+
# This attribute also accepts an array of symbols.
|
56
|
+
#
|
57
|
+
# @return [Symbol]
|
58
|
+
attr_accessor :ssh_host_attribute
|
59
|
+
|
60
|
+
# Tags to apply to the server.
|
61
|
+
#
|
62
|
+
# @return [Array]
|
63
|
+
attr_accessor :tags
|
64
|
+
|
65
|
+
# The API token to access Scaleway. It can also be configured with
|
66
|
+
# SCW_TOKEN environment variable.
|
67
|
+
#
|
68
|
+
# @return [String]
|
69
|
+
attr_accessor :token
|
70
|
+
|
71
|
+
def initialize
|
72
|
+
@bootscript = UNSET_VALUE
|
73
|
+
@commercial_type = UNSET_VALUE
|
74
|
+
@image = UNSET_VALUE
|
75
|
+
@name = UNSET_VALUE
|
76
|
+
@organization = UNSET_VALUE
|
77
|
+
@server_check_interval = UNSET_VALUE
|
78
|
+
@server_ready_timeout = UNSET_VALUE
|
79
|
+
@security_group = UNSET_VALUE
|
80
|
+
@ssh_host_attribute = UNSET_VALUE
|
81
|
+
@tags = []
|
82
|
+
@token = UNSET_VALUE
|
83
|
+
end
|
84
|
+
|
85
|
+
def finalize!
|
86
|
+
@bootscript = nil if @bootscript == UNSET_VALUE
|
87
|
+
@commercial_type = 'C2S' if @commercial_type == UNSET_VALUE
|
88
|
+
@image = '75c28f52-6c64-40fc-bb31-f53ca9d02de9' if @image == UNSET_VALUE
|
89
|
+
|
90
|
+
if @name == UNSET_VALUE
|
91
|
+
require 'securerandom'
|
92
|
+
@name = "scw-#{SecureRandom.hex(3)}"
|
93
|
+
end
|
94
|
+
|
95
|
+
@organization = ENV['SCW_ORGANIZATION'] if @organization == UNSET_VALUE
|
96
|
+
@server_check_interval = 2 if @server_check_interval == UNSET_VALUE
|
97
|
+
@server_ready_timeout = 120 if @server_ready_timeout == UNSET_VALUE
|
98
|
+
@security_group = nil if @security_group == UNSET_VALUE
|
99
|
+
@ssh_host_attribute = nil if @ssh_host_attribute == UNSET_VALUE
|
100
|
+
@token = ENV['SCW_TOKEN'] if @token == UNSET_VALUE
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def validate(machine)
|
105
|
+
errors = _detected_errors
|
106
|
+
|
107
|
+
errors << I18n.t('vagrant_scaleway.config.organization_required') if @organization.nil?
|
108
|
+
errors << I18n.t('vagrant_scaleway.config.token_required') if @token.nil?
|
109
|
+
|
110
|
+
{ 'Scaleway Provider' => errors }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|