vagrant-brightbox 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.
- data/.gitignore +15 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +10 -0
- data/LICENSE +8 -0
- data/README.md +217 -0
- data/Rakefile +21 -0
- data/Vagrantfile.example +105 -0
- data/dummy.box +0 -0
- data/example_box/README.md +9 -0
- data/example_box/metadata.json +3 -0
- data/lib/vagrant-brightbox/action/connect_brightbox.rb +53 -0
- data/lib/vagrant-brightbox/action/create_server.rb +137 -0
- data/lib/vagrant-brightbox/action/delete_server.rb +26 -0
- data/lib/vagrant-brightbox/action/forced_halt.rb +27 -0
- data/lib/vagrant-brightbox/action/is_created.rb +18 -0
- data/lib/vagrant-brightbox/action/is_running.rb +18 -0
- data/lib/vagrant-brightbox/action/map_cloud_ip.rb +68 -0
- data/lib/vagrant-brightbox/action/message_already_created.rb +16 -0
- data/lib/vagrant-brightbox/action/message_not_created.rb +16 -0
- data/lib/vagrant-brightbox/action/read_ssh_info.rb +69 -0
- data/lib/vagrant-brightbox/action/read_state.rb +38 -0
- data/lib/vagrant-brightbox/action/start_server.rb +28 -0
- data/lib/vagrant-brightbox/action/sync_folders.rb +58 -0
- data/lib/vagrant-brightbox/action/timed_provision.rb +21 -0
- data/lib/vagrant-brightbox/action/unsupported.rb +18 -0
- data/lib/vagrant-brightbox/action.rb +166 -0
- data/lib/vagrant-brightbox/config.rb +268 -0
- data/lib/vagrant-brightbox/errors.rb +34 -0
- data/lib/vagrant-brightbox/plugin.rb +73 -0
- data/lib/vagrant-brightbox/provider.rb +50 -0
- data/lib/vagrant-brightbox/util/timer.rb +17 -0
- data/lib/vagrant-brightbox/version.rb +5 -0
- data/lib/vagrant-brightbox.rb +18 -0
- data/locales/en.yml +88 -0
- data/spec/vagrant-brightbox/config_spec.rb +179 -0
- data/vagrant-brightbox.gemspec +23 -0
- metadata +122 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Brightbox
|
5
|
+
module Action
|
6
|
+
class MapCloudIp
|
7
|
+
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new("vagrant_brightbox::action::map_cloud_ips")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
|
15
|
+
@app.call(env)
|
16
|
+
|
17
|
+
machine = env[:machine]
|
18
|
+
|
19
|
+
if no_cloud_ips_required?(env[:machine].config.vm.networks)
|
20
|
+
@logger.info("No public ipv4 network required")
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
if machine.id.nil?
|
25
|
+
@logger.info("No server found - can't map public ips")
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
29
|
+
server = env[:brightbox_compute].servers.get(machine.id)
|
30
|
+
if server.nil?
|
31
|
+
@logger.info("Machine cannot be found; assuming it got destroyed.")
|
32
|
+
machine.id = nil
|
33
|
+
return
|
34
|
+
end
|
35
|
+
|
36
|
+
unless server.cloud_ips.empty?
|
37
|
+
@logger.info("Server already has public ip address.")
|
38
|
+
return
|
39
|
+
end
|
40
|
+
|
41
|
+
target_ip = unallocated_cloud_ip(env[:brightbox_compute].cloud_ips)
|
42
|
+
|
43
|
+
if target_ip.nil?
|
44
|
+
@logger.info("Couldn't allocate a cloud ip")
|
45
|
+
env[:ui].info I18n.t("vagrant_brightbox.errors.no_free_cloud_ip")
|
46
|
+
return
|
47
|
+
end
|
48
|
+
|
49
|
+
target_ip.map(server)
|
50
|
+
env[:ui].info I18n.t("vagrant_brightbox.mapped_cloud_ip", :server => server.id, :cloud_ip => target_ip.public_ip)
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def unallocated_cloud_ip(ip_list)
|
55
|
+
ip_list.all.detect(ip_list.method(:allocate)) {|ip| !ip.mapped? }
|
56
|
+
end
|
57
|
+
|
58
|
+
def no_cloud_ips_required?(networks)
|
59
|
+
networks.any? do |x|
|
60
|
+
x.first == :private_network ||
|
61
|
+
(x.first == :public_network && element[1][:ipv6])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Brightbox
|
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_brightbox.already_created"))
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Brightbox
|
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_brightbox.not_created"))
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Brightbox
|
5
|
+
module Action
|
6
|
+
# This action reads the SSH info for the machine and puts it into the
|
7
|
+
# `:machine_ssh_info` key in the environment.
|
8
|
+
class ReadSSHInfo
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new("vagrant_brightbox::action::read_ssh_info")
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
env[:machine_ssh_info] = read_ssh_info(env[:brightbox_compute], env[:machine])
|
16
|
+
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
def read_ssh_info(brightbox, machine)
|
21
|
+
return nil if machine.id.nil?
|
22
|
+
|
23
|
+
# Find the machine
|
24
|
+
server = brightbox.servers.get(machine.id)
|
25
|
+
if server.nil?
|
26
|
+
# The machine can't be found
|
27
|
+
@logger.info("Machine couldn't be found, assuming it got destroyed.")
|
28
|
+
machine.id = nil
|
29
|
+
return nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get the configuration
|
33
|
+
region = machine.provider_config.region
|
34
|
+
config = machine.provider_config.get_region_config(region)
|
35
|
+
|
36
|
+
if use_private_network?(machine.config.vm.networks)
|
37
|
+
host_name = server.fqdn
|
38
|
+
elsif use_ipv6_public_network?(machine.config.vm.networks)
|
39
|
+
host_name = "ipv6.#{server.fqdn}"
|
40
|
+
elsif server.public_ip_address
|
41
|
+
host_name = server.dns_name
|
42
|
+
else
|
43
|
+
@logger.error("Cannot find public ip address - defaulting to private")
|
44
|
+
host_name = server.fqdn
|
45
|
+
end
|
46
|
+
|
47
|
+
# Read the DNS info
|
48
|
+
return {
|
49
|
+
:host => host_name,
|
50
|
+
:port => 22,
|
51
|
+
:private_key_path => config.ssh_private_key_path,
|
52
|
+
:username => config.ssh_username
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def use_private_network?(network_structure)
|
57
|
+
network_structure.any? {|x| x.first == :private_network }
|
58
|
+
end
|
59
|
+
|
60
|
+
def use_ipv6_public_network?(network_structure)
|
61
|
+
network_structure.any? do |element|
|
62
|
+
element.first == :public_network && element[1][:ipv6]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Brightbox
|
5
|
+
module Action
|
6
|
+
# This action reads the state of the machine and puts it in the
|
7
|
+
# `:machine_state_id` key in the environment.
|
8
|
+
class ReadState
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new("vagrant_brightbox::action::read_state")
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
env[:machine_state_id] = read_state(env[:brightbox_compute], env[:machine])
|
16
|
+
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
def read_state(brightbox, machine)
|
21
|
+
return :not_created if machine.id.nil?
|
22
|
+
|
23
|
+
# Find the machine
|
24
|
+
server = brightbox.servers.get(machine.id)
|
25
|
+
if server.nil? || [:deleted, :deleting, :failed].include?(server.state.to_sym)
|
26
|
+
# The machine can't be found
|
27
|
+
@logger.info("Machine not found or terminated, assuming it got destroyed.")
|
28
|
+
machine.id = nil
|
29
|
+
return :not_created
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return the state
|
33
|
+
return server.state.to_sym
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Brightbox
|
5
|
+
module Action
|
6
|
+
# This starts the server via the api
|
7
|
+
class StartServer
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new("vagrant_brightbox::action::start_server")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
server = env[:brightbox_compute].servers.get(env[:machine].id)
|
15
|
+
|
16
|
+
# Make the action idempotent
|
17
|
+
unless server.ready?
|
18
|
+
# start the server.
|
19
|
+
env[:ui].info(I18n.t("vagrant_brightbox.starting_server"))
|
20
|
+
server.start
|
21
|
+
end
|
22
|
+
|
23
|
+
@app.call(env)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
require "vagrant/util/subprocess"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module Brightbox
|
7
|
+
module Action
|
8
|
+
# This middleware uses `rsync` to sync the folders over to the
|
9
|
+
# Brightbox server.
|
10
|
+
class SyncFolders
|
11
|
+
def initialize(app, env)
|
12
|
+
@app = app
|
13
|
+
@logger = Log4r::Logger.new("vagrant_brightbox::action::sync_folders")
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
@app.call(env)
|
18
|
+
|
19
|
+
ssh_info = env[:machine].ssh_info
|
20
|
+
|
21
|
+
env[:machine].config.vm.synced_folders.each do |id, data|
|
22
|
+
hostpath = File.expand_path(data[:hostpath], env[:root_path])
|
23
|
+
guestpath = data[:guestpath]
|
24
|
+
|
25
|
+
# Make sure there is a trailing slash on the host path to
|
26
|
+
# avoid creating an additional directory with rsync
|
27
|
+
hostpath = "#{hostpath}/" if hostpath !~ /\/$/
|
28
|
+
|
29
|
+
env[:ui].info(I18n.t("vagrant_brightbox.rsync_folder",
|
30
|
+
:hostpath => hostpath,
|
31
|
+
:guestpath => guestpath))
|
32
|
+
|
33
|
+
# Create the guest path
|
34
|
+
env[:machine].communicate.sudo("mkdir -p '#{guestpath}'")
|
35
|
+
env[:machine].communicate.sudo(
|
36
|
+
"chown #{ssh_info[:username]} '#{guestpath}'")
|
37
|
+
|
38
|
+
# Rsync over to the guest path using the SSH info
|
39
|
+
command = [
|
40
|
+
"rsync", "--verbose", "--archive", "-z",
|
41
|
+
"--exclude", ".vagrant/",
|
42
|
+
"-e", "ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no -i '#{ssh_info[:private_key_path]}'",
|
43
|
+
hostpath,
|
44
|
+
"#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
|
45
|
+
|
46
|
+
r = Vagrant::Util::Subprocess.execute(*command)
|
47
|
+
if r.exit_code != 0
|
48
|
+
raise Errors::RsyncError,
|
49
|
+
:guestpath => guestpath,
|
50
|
+
:hostpath => hostpath,
|
51
|
+
:stderr => r.stderr
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "vagrant-brightbox/util/timer"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Brightbox
|
5
|
+
module Action
|
6
|
+
# This is the same as the builtin provision except it times the
|
7
|
+
# provisioner runs.
|
8
|
+
class TimedProvision < Vagrant::Action::Builtin::Provision
|
9
|
+
def run_provisioner(env, p)
|
10
|
+
timer = Util::Timer.time do
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
env[:metrics] ||= {}
|
15
|
+
env[:metrics]["provisioner_times"] ||= []
|
16
|
+
env[:metrics]["provisioner_times"] << [p.class.to_s, timer]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Brightbox
|
3
|
+
module Action
|
4
|
+
class Unsupported
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env[:ui].warn(I18n.t("vagrant_brightbox.unsupported"))
|
11
|
+
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
require "vagrant/action/builder"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module Brightbox
|
7
|
+
module Action
|
8
|
+
# Include the built-in modules so we can use them as top-level things.
|
9
|
+
include Vagrant::Action::Builtin
|
10
|
+
|
11
|
+
# This action is called to destroy the remote machine.
|
12
|
+
def self.action_destroy
|
13
|
+
Vagrant::Action::Builder.new.tap do |b|
|
14
|
+
b.use ConfigValidate
|
15
|
+
b.use Call, IsCreated do |env, b2|
|
16
|
+
if env[:result]
|
17
|
+
b2.use ConnectBrightbox
|
18
|
+
b2.use DeleteServer
|
19
|
+
else
|
20
|
+
b2.use MessageNotCreated
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# This action is called to halt the server - gracefully or by force.
|
27
|
+
def self.action_halt
|
28
|
+
Vagrant::Action::Builder.new.tap do |b|
|
29
|
+
b.use ConfigValidate
|
30
|
+
b.use Call, IsCreated do |env, b2|
|
31
|
+
if env[:result]
|
32
|
+
b2.use Call, GracefulHalt, :inactive, :active do |env2, b3|
|
33
|
+
if !env2[:result]
|
34
|
+
b3.use ConnectBrightbox
|
35
|
+
b3.use ForcedHalt
|
36
|
+
end
|
37
|
+
end
|
38
|
+
else
|
39
|
+
b2.use MessageNotCreated
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# This action reloads the machine - essentially shutting it down
|
46
|
+
# and bringing it back up again in the new configuration.
|
47
|
+
def self.action_reload
|
48
|
+
Vagrant::Action::Builder.new.tap do |b|
|
49
|
+
b.use Call, IsCreated do |env, b2|
|
50
|
+
if env[:result]
|
51
|
+
b2.use action_halt
|
52
|
+
b2.use action_up
|
53
|
+
else
|
54
|
+
b2.use MessageNotCreated
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# This action is called when `vagrant provision` is called.
|
61
|
+
def self.action_provision
|
62
|
+
Vagrant::Action::Builder.new.tap do |b|
|
63
|
+
b.use ConfigValidate
|
64
|
+
b.use Call, IsCreated do |env, b2|
|
65
|
+
if env[:result]
|
66
|
+
b2.use Provision
|
67
|
+
b2.use SyncFolders
|
68
|
+
else
|
69
|
+
b2.use MessageNotCreated
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# This action is called to read the SSH info of the machine. The
|
77
|
+
# resulting state is expected to be put into the `:machine_ssh_info`
|
78
|
+
# key.
|
79
|
+
def self.action_read_ssh_info
|
80
|
+
Vagrant::Action::Builder.new.tap do |b|
|
81
|
+
b.use ConfigValidate
|
82
|
+
b.use ConnectBrightbox
|
83
|
+
b.use ReadSSHInfo
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# This action is called to read the state of the machine. The
|
88
|
+
# resulting state is expected to be put into the `:machine_state_id`
|
89
|
+
# key.
|
90
|
+
def self.action_read_state
|
91
|
+
Vagrant::Action::Builder.new.tap do |b|
|
92
|
+
b.use ConfigValidate
|
93
|
+
b.use ConnectBrightbox
|
94
|
+
b.use ReadState
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.action_ssh
|
99
|
+
Vagrant::Action::Builder.new.tap do |b|
|
100
|
+
b.use ConfigValidate
|
101
|
+
b.use Call, IsCreated do |env, b2|
|
102
|
+
if env[:result]
|
103
|
+
b2.use SSHExec
|
104
|
+
else
|
105
|
+
b2.use MessageNotCreated
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.action_up
|
112
|
+
Vagrant::Action::Builder.new.tap do |b|
|
113
|
+
b.use ConfigValidate
|
114
|
+
b.use ConnectBrightbox
|
115
|
+
b.use Call, IsCreated do |env, b2|
|
116
|
+
if env[:result]
|
117
|
+
b2.use Call, IsRunning do |env2, b3|
|
118
|
+
if env2[:result]
|
119
|
+
b3.use MessageAlreadyCreated
|
120
|
+
else
|
121
|
+
b3.use StartServer
|
122
|
+
b3.use MapCloudIp
|
123
|
+
end
|
124
|
+
end
|
125
|
+
else
|
126
|
+
b2.use Provision
|
127
|
+
b2.use SyncFolders
|
128
|
+
b2.use CreateServer
|
129
|
+
b2.use MapCloudIp
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.action_package
|
136
|
+
Vagrant::Action::Builder.new.tap do |b|
|
137
|
+
b.use Unsupported
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class << self
|
142
|
+
alias action_resume action_package
|
143
|
+
alias action_suspend action_package
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
# The autoload farm
|
149
|
+
action_root = Pathname.new(File.expand_path("../action", __FILE__))
|
150
|
+
autoload :ConnectBrightbox, action_root.join("connect_brightbox")
|
151
|
+
autoload :CreateServer, action_root.join("create_server")
|
152
|
+
autoload :DeleteServer, action_root.join("delete_server")
|
153
|
+
autoload :IsCreated, action_root.join("is_created")
|
154
|
+
autoload :IsRunning, action_root.join("is_running")
|
155
|
+
autoload :MessageAlreadyCreated, action_root.join("message_already_created")
|
156
|
+
autoload :MessageNotCreated, action_root.join("message_not_created")
|
157
|
+
autoload :ReadSSHInfo, action_root.join("read_ssh_info")
|
158
|
+
autoload :ReadState, action_root.join("read_state")
|
159
|
+
autoload :SyncFolders, action_root.join("sync_folders")
|
160
|
+
autoload :MapCloudIp, action_root.join("map_cloud_ip")
|
161
|
+
autoload :ForcedHalt, action_root.join("forced_halt")
|
162
|
+
autoload :StartServer, action_root.join("start_server")
|
163
|
+
autoload :Unsupported, action_root.join("unsupported")
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|