vagrant-softlayer 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +16 -16
- data/CHANGELOG.md +61 -49
- data/QUICKSTART.md +380 -376
- data/README.md +258 -256
- data/contrib/vagrant-softlayer-boxes +418 -416
- data/contrib/vagrant-softlayer-vlans +339 -329
- data/lib/vagrant-softlayer/action/create_instance.rb +74 -74
- data/lib/vagrant-softlayer/action/setup_softlayer.rb +39 -39
- data/lib/vagrant-softlayer/action/update_dns.rb +94 -94
- data/lib/vagrant-softlayer/action/wait_for_provision.rb +40 -40
- data/lib/vagrant-softlayer/action/wait_for_rebuild.rb +38 -36
- data/lib/vagrant-softlayer/config.rb +282 -268
- data/lib/vagrant-softlayer/util/load_balancer.rb +96 -103
- data/lib/vagrant-softlayer/util/network.rb +75 -75
- data/lib/vagrant-softlayer/util/warden.rb +38 -38
- data/lib/vagrant-softlayer/version.rb +5 -5
- data/spec/vagrant-softlayer/config_spec.rb +271 -267
- data/vagrant-softlayer.gemspec +55 -55
- metadata +4 -4
@@ -1,103 +1,96 @@
|
|
1
|
-
module VagrantPlugins
|
2
|
-
module SoftLayer
|
3
|
-
module Util
|
4
|
-
# This mixin contains utility methods for load balancer management.
|
5
|
-
module LoadBalancer
|
6
|
-
# Whether load balancer management is enabled or not.
|
7
|
-
def enabled?
|
8
|
-
if @env[:machine].provider_config.load_balancers.empty?
|
9
|
-
@logger.debug("No load balancer has been defined. Going ahead.")
|
10
|
-
return false
|
11
|
-
end
|
12
|
-
|
13
|
-
# Currently we don't do load balancing for private machines.
|
14
|
-
if @env[:machine].provider_config.private_only
|
15
|
-
@logger.info("Load balancing doesn't work for private machines. Going ahead.")
|
16
|
-
return false
|
17
|
-
end
|
18
|
-
true
|
19
|
-
end
|
20
|
-
|
21
|
-
# Get existing stuff.
|
22
|
-
def read_load_balancers
|
23
|
-
mask = [
|
24
|
-
"id",
|
25
|
-
"ipAddress.ipAddress",
|
26
|
-
"virtualServers.serviceGroups.services.groupReferences",
|
27
|
-
"virtualServers.serviceGroups.services.healthChecks"
|
28
|
-
]
|
29
|
-
@logger.debug("Looking for existing load balancers.")
|
30
|
-
@load_balancers = sl_warden { @services["Account"].object_mask(mask).getAdcLoadBalancers }
|
31
|
-
@logger.debug("Got load balancer configuration:")
|
32
|
-
@logger.debug("-- #{@load_balancers}")
|
33
|
-
end
|
34
|
-
|
35
|
-
# For each load balancer, check if total connections
|
36
|
-
# are less than 100% and, if so, rebalance the allocations.
|
37
|
-
def rebalance!
|
38
|
-
read_load_balancers
|
39
|
-
|
40
|
-
@load_balancers.each do |load_balancer|
|
41
|
-
next if load_balancer["virtualServers"].empty?
|
42
|
-
next if 100 == load_balancer["virtualServers"].inject(0) { |sum, vs| sum += vs["allocation"] }
|
43
|
-
|
44
|
-
# Create allocation slots.
|
45
|
-
count = load_balancer["virtualServers"].count
|
46
|
-
allocation = [100 / count] * count
|
47
|
-
(100 % count).times { |i| allocation[i] += 1 }
|
48
|
-
|
49
|
-
# Rebalance allocations.
|
50
|
-
load_balancer["virtualServers"].each do |vs|
|
51
|
-
vs["allocation"] = allocation.pop
|
52
|
-
end
|
53
|
-
|
54
|
-
# Update the VIP object.
|
55
|
-
@logger.debug("Rebalancing VIP #{load_balancer['id']}")
|
56
|
-
@logger.debug("-- #{load_balancer}")
|
57
|
-
@services["VirtualIpAddress"].object_with_id(load_balancer["id"]).editObject("virtualServers" => load_balancer["virtualServers"])
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
# Initial setup.
|
62
|
-
def setup
|
63
|
-
# A plethora of service objects is required for managing
|
64
|
-
# load balancers. We instanciate'em all here.
|
65
|
-
@services = {
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
"
|
70
|
-
"
|
71
|
-
"
|
72
|
-
"
|
73
|
-
"
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
read_load_balancers
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
1
|
+
module VagrantPlugins
|
2
|
+
module SoftLayer
|
3
|
+
module Util
|
4
|
+
# This mixin contains utility methods for load balancer management.
|
5
|
+
module LoadBalancer
|
6
|
+
# Whether load balancer management is enabled or not.
|
7
|
+
def enabled?
|
8
|
+
if @env[:machine].provider_config.load_balancers.empty?
|
9
|
+
@logger.debug("No load balancer has been defined. Going ahead.")
|
10
|
+
return false
|
11
|
+
end
|
12
|
+
|
13
|
+
# Currently we don't do load balancing for private machines.
|
14
|
+
if @env[:machine].provider_config.private_only
|
15
|
+
@logger.info("Load balancing doesn't work for private machines. Going ahead.")
|
16
|
+
return false
|
17
|
+
end
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# Get existing stuff.
|
22
|
+
def read_load_balancers
|
23
|
+
mask = [
|
24
|
+
"id",
|
25
|
+
"ipAddress.ipAddress",
|
26
|
+
"virtualServers.serviceGroups.services.groupReferences",
|
27
|
+
"virtualServers.serviceGroups.services.healthChecks"
|
28
|
+
].join(",")
|
29
|
+
@logger.debug("Looking for existing load balancers.")
|
30
|
+
@load_balancers = sl_warden { @services["Account"].object_mask("mask[#{mask}]").getAdcLoadBalancers }
|
31
|
+
@logger.debug("Got load balancer configuration:")
|
32
|
+
@logger.debug("-- #{@load_balancers}")
|
33
|
+
end
|
34
|
+
|
35
|
+
# For each load balancer, check if total connections
|
36
|
+
# are less than 100% and, if so, rebalance the allocations.
|
37
|
+
def rebalance!
|
38
|
+
read_load_balancers
|
39
|
+
|
40
|
+
@load_balancers.each do |load_balancer|
|
41
|
+
next if load_balancer["virtualServers"].empty?
|
42
|
+
next if 100 == load_balancer["virtualServers"].inject(0) { |sum, vs| sum += vs["allocation"] }
|
43
|
+
|
44
|
+
# Create allocation slots.
|
45
|
+
count = load_balancer["virtualServers"].count
|
46
|
+
allocation = [100 / count] * count
|
47
|
+
(100 % count).times { |i| allocation[i] += 1 }
|
48
|
+
|
49
|
+
# Rebalance allocations.
|
50
|
+
load_balancer["virtualServers"].each do |vs|
|
51
|
+
vs["allocation"] = allocation.pop
|
52
|
+
end
|
53
|
+
|
54
|
+
# Update the VIP object.
|
55
|
+
@logger.debug("Rebalancing VIP #{load_balancer['id']}")
|
56
|
+
@logger.debug("-- #{load_balancer}")
|
57
|
+
@services["VirtualIpAddress"].object_with_id(load_balancer["id"]).editObject("virtualServers" => load_balancer["virtualServers"])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Initial setup.
|
62
|
+
def setup
|
63
|
+
# A plethora of service objects is required for managing
|
64
|
+
# load balancers. We instanciate'em all here.
|
65
|
+
@services = { "Account" => @env[:sl_client]["SoftLayer_Account"] }
|
66
|
+
[
|
67
|
+
"Health_Check_Type",
|
68
|
+
"Routing_Method",
|
69
|
+
"Routing_Type",
|
70
|
+
"Service",
|
71
|
+
"Service_Group",
|
72
|
+
"VirtualIpAddress",
|
73
|
+
"VirtualServer"
|
74
|
+
].each { |service| @services[service] = @env[:sl_client]["SoftLayer_Network_Application_Delivery_Controller_LoadBalancer_#{service}"] }
|
75
|
+
|
76
|
+
# We create enumerations for the various configurables.
|
77
|
+
@enums = {}
|
78
|
+
[
|
79
|
+
"Health_Check_Type",
|
80
|
+
"Routing_Method",
|
81
|
+
"Routing_Type"
|
82
|
+
].each do |service|
|
83
|
+
{}.tap do |enum|
|
84
|
+
sl_warden { @services[service].getAllObjects }.each do |record|
|
85
|
+
enum[record["name"].upcase] = record["id"]
|
86
|
+
end
|
87
|
+
@enums[service] = enum
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
read_load_balancers
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -1,75 +1,75 @@
|
|
1
|
-
module VagrantPlugins
|
2
|
-
module SoftLayer
|
3
|
-
module Util
|
4
|
-
module Network
|
5
|
-
# Gets hostname of the instance starting from the environment.
|
6
|
-
def hostname(env)
|
7
|
-
env[:machine].provider_config.hostname || env[:machine].config.vm.hostname
|
8
|
-
end
|
9
|
-
|
10
|
-
# Gets IP address of the instance starting from the environment.
|
11
|
-
#
|
12
|
-
# Returns the private IP address if the instance has been
|
13
|
-
# defined as private only, the public IP address otherwise.
|
14
|
-
def ip_address(env)
|
15
|
-
ip_address_record(env)[:address]
|
16
|
-
end
|
17
|
-
|
18
|
-
# Gets IP address ID of the instance starting from the environment.
|
19
|
-
#
|
20
|
-
# Returns the private IP address ID if the instance has been
|
21
|
-
# defined as private only, the public IP address ID otherwise.
|
22
|
-
def ip_address_id(env)
|
23
|
-
ip_address_record(env)[:id]
|
24
|
-
end
|
25
|
-
|
26
|
-
# Gets IP address record of the instance starting from the environment.
|
27
|
-
#
|
28
|
-
# Returns an hash with the following structure:
|
29
|
-
#
|
30
|
-
# :address
|
31
|
-
# :id
|
32
|
-
#
|
33
|
-
# Returns the private IP address record if the instance has been
|
34
|
-
# defined as private only, the public IP address record otherwise
|
35
|
-
# unless the force_private_ip override is true.
|
36
|
-
def ip_address_record(env)
|
37
|
-
data_type = env[:machine].provider_config.private_only ? "primaryBackendNetworkComponent" : "primaryNetworkComponent"
|
38
|
-
data_type = "primaryBackendNetworkComponent" if env[:machine].provider_config.force_private_ip
|
39
|
-
mask = {
|
40
|
-
record = sl_warden { env[:sl_machine].object_mask(mask).getObject }
|
41
|
-
return {
|
42
|
-
:address => record[data_type]["primaryIpAddressRecord"]["ipAddress"],
|
43
|
-
:id => record[data_type]["primaryIpAddressRecord"]["id"]
|
44
|
-
}
|
45
|
-
end
|
46
|
-
|
47
|
-
# Returns SSH keys starting from the configuration parameter.
|
48
|
-
#
|
49
|
-
# In the configuration, each key could be passed either as an
|
50
|
-
# id or as a label. The routine will detect this and lookup
|
51
|
-
# the id if needed.
|
52
|
-
#
|
53
|
-
# The first parameter is the current environment.
|
54
|
-
#
|
55
|
-
# The second parameter is useful for returning: if it is set
|
56
|
-
# the routine will return just the array of ids (this is needed,
|
57
|
-
# as an example, for reloading OS), otherwise an hash is
|
58
|
-
# returned (this latter case is needed instead for creating
|
59
|
-
# an instance).
|
60
|
-
def ssh_keys(env, ids_only = false)
|
61
|
-
account =
|
62
|
-
acc_keys = sl_warden { account.object_mask("id
|
63
|
-
key_ids = []
|
64
|
-
Array(env[:machine].provider_config.ssh_key).each do |key|
|
65
|
-
pattern = key.is_a?(String) ? "label" : "id"
|
66
|
-
key_hash = acc_keys.find { |acc_key| acc_key[pattern] == key }
|
67
|
-
raise Errors::SLSshKeyNotFound, :key => key unless key_hash
|
68
|
-
key_ids << key_hash["id"]
|
69
|
-
end
|
70
|
-
return (ids_only ? key_ids : key_ids.map { |key_id| { :id => key_id } })
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
1
|
+
module VagrantPlugins
|
2
|
+
module SoftLayer
|
3
|
+
module Util
|
4
|
+
module Network
|
5
|
+
# Gets hostname of the instance starting from the environment.
|
6
|
+
def hostname(env)
|
7
|
+
env[:machine].provider_config.hostname || env[:machine].config.vm.hostname
|
8
|
+
end
|
9
|
+
|
10
|
+
# Gets IP address of the instance starting from the environment.
|
11
|
+
#
|
12
|
+
# Returns the private IP address if the instance has been
|
13
|
+
# defined as private only, the public IP address otherwise.
|
14
|
+
def ip_address(env)
|
15
|
+
ip_address_record(env)[:address]
|
16
|
+
end
|
17
|
+
|
18
|
+
# Gets IP address ID of the instance starting from the environment.
|
19
|
+
#
|
20
|
+
# Returns the private IP address ID if the instance has been
|
21
|
+
# defined as private only, the public IP address ID otherwise.
|
22
|
+
def ip_address_id(env)
|
23
|
+
ip_address_record(env)[:id]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Gets IP address record of the instance starting from the environment.
|
27
|
+
#
|
28
|
+
# Returns an hash with the following structure:
|
29
|
+
#
|
30
|
+
# :address
|
31
|
+
# :id
|
32
|
+
#
|
33
|
+
# Returns the private IP address record if the instance has been
|
34
|
+
# defined as private only, the public IP address record otherwise
|
35
|
+
# unless the force_private_ip override is true.
|
36
|
+
def ip_address_record(env)
|
37
|
+
data_type = env[:machine].provider_config.private_only ? "primaryBackendNetworkComponent" : "primaryNetworkComponent"
|
38
|
+
data_type = "primaryBackendNetworkComponent" if env[:machine].provider_config.force_private_ip
|
39
|
+
mask = "#{data_type}.primaryIpAddressRecord.id,#{data_type}.primaryIpAddressRecord.ipAddress"
|
40
|
+
record = sl_warden { env[:sl_machine].object_mask("mask[#{mask}]").getObject }
|
41
|
+
return {
|
42
|
+
:address => record[data_type]["primaryIpAddressRecord"]["ipAddress"],
|
43
|
+
:id => record[data_type]["primaryIpAddressRecord"]["id"]
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns SSH keys starting from the configuration parameter.
|
48
|
+
#
|
49
|
+
# In the configuration, each key could be passed either as an
|
50
|
+
# id or as a label. The routine will detect this and lookup
|
51
|
+
# the id if needed.
|
52
|
+
#
|
53
|
+
# The first parameter is the current environment.
|
54
|
+
#
|
55
|
+
# The second parameter is useful for returning: if it is set
|
56
|
+
# the routine will return just the array of ids (this is needed,
|
57
|
+
# as an example, for reloading OS), otherwise an hash is
|
58
|
+
# returned (this latter case is needed instead for creating
|
59
|
+
# an instance).
|
60
|
+
def ssh_keys(env, ids_only = false)
|
61
|
+
account = env[:sl_client]["SoftLayer_Account"]
|
62
|
+
acc_keys = sl_warden { account.object_mask("mask[id,label]").getSshKeys }
|
63
|
+
key_ids = []
|
64
|
+
Array(env[:machine].provider_config.ssh_key).each do |key|
|
65
|
+
pattern = key.is_a?(String) ? "label" : "id"
|
66
|
+
key_hash = acc_keys.find { |acc_key| acc_key[pattern] == key }
|
67
|
+
raise Errors::SLSshKeyNotFound, :key => key unless key_hash
|
68
|
+
key_ids << key_hash["id"]
|
69
|
+
end
|
70
|
+
return (ids_only ? key_ids : key_ids.map { |key_id| { :id => key_id } })
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -1,38 +1,38 @@
|
|
1
|
-
module VagrantPlugins
|
2
|
-
module SoftLayer
|
3
|
-
module Util
|
4
|
-
module Warden
|
5
|
-
# Handles gracefully SoftLayer API calls.
|
6
|
-
#
|
7
|
-
# The block code is executed, catching both common
|
8
|
-
# connection errors and API exceptions.
|
9
|
-
#
|
10
|
-
# Optionally, in the not-so-uncommon case when
|
11
|
-
# the object (e.g. the SoftLayer instance) is not
|
12
|
-
# found, executes a proc and/or retry the API call
|
13
|
-
# after some seconds.
|
14
|
-
#
|
15
|
-
# A future version of the method will add a retry timeout.
|
16
|
-
def sl_warden(rescue_proc = nil, retry_interval = 0, &block)
|
17
|
-
begin
|
18
|
-
yield
|
19
|
-
rescue ::OpenSSL::SSL::SSLError
|
20
|
-
raise Errors::SLCertificateError
|
21
|
-
rescue
|
22
|
-
if e.class
|
23
|
-
out = rescue_proc.call if rescue_proc
|
24
|
-
if retry_interval > 0
|
25
|
-
sleep retry_interval
|
26
|
-
retry
|
27
|
-
else
|
28
|
-
return out
|
29
|
-
end
|
30
|
-
else
|
31
|
-
raise Errors::SLApiError, :class => e.class, :message => e.message
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
1
|
+
module VagrantPlugins
|
2
|
+
module SoftLayer
|
3
|
+
module Util
|
4
|
+
module Warden
|
5
|
+
# Handles gracefully SoftLayer API calls.
|
6
|
+
#
|
7
|
+
# The block code is executed, catching both common
|
8
|
+
# connection errors and API exceptions.
|
9
|
+
#
|
10
|
+
# Optionally, in the not-so-uncommon case when
|
11
|
+
# the object (e.g. the SoftLayer instance) is not
|
12
|
+
# found, executes a proc and/or retry the API call
|
13
|
+
# after some seconds.
|
14
|
+
#
|
15
|
+
# A future version of the method will add a retry timeout.
|
16
|
+
def sl_warden(rescue_proc = nil, retry_interval = 0, &block)
|
17
|
+
begin
|
18
|
+
yield
|
19
|
+
rescue ::OpenSSL::SSL::SSLError
|
20
|
+
raise Errors::SLCertificateError
|
21
|
+
rescue Exception => e
|
22
|
+
if e.class != SocketError && (e.message.start_with?("Unable to find object") || e.message.start_with?("Object does not exist"))
|
23
|
+
out = rescue_proc.call if rescue_proc
|
24
|
+
if retry_interval > 0
|
25
|
+
sleep retry_interval
|
26
|
+
retry
|
27
|
+
else
|
28
|
+
return out
|
29
|
+
end
|
30
|
+
else
|
31
|
+
raise Errors::SLApiError, :class => e.class, :message => e.message
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
module VagrantPlugins
|
2
|
-
module SoftLayer
|
3
|
-
VERSION = "0.
|
4
|
-
end
|
5
|
-
end
|
1
|
+
module VagrantPlugins
|
2
|
+
module SoftLayer
|
3
|
+
VERSION = "0.4.0"
|
4
|
+
end
|
5
|
+
end
|
@@ -1,267 +1,271 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe VagrantPlugins::SoftLayer::Config do
|
4
|
-
let(:config) { described_class.new }
|
5
|
-
let(:machine) { double("machine") }
|
6
|
-
|
7
|
-
describe "defaults" do
|
8
|
-
subject do
|
9
|
-
config.tap do |o|
|
10
|
-
o.finalize!
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
its("api_key") { should be_nil }
|
15
|
-
its("
|
16
|
-
its("
|
17
|
-
|
18
|
-
|
19
|
-
its("
|
20
|
-
its("
|
21
|
-
its("
|
22
|
-
its("
|
23
|
-
its("
|
24
|
-
its("
|
25
|
-
its("
|
26
|
-
its("
|
27
|
-
its("
|
28
|
-
its("
|
29
|
-
its("
|
30
|
-
its("
|
31
|
-
its("
|
32
|
-
its("
|
33
|
-
its("
|
34
|
-
its("
|
35
|
-
its("
|
36
|
-
its("
|
37
|
-
its("
|
38
|
-
its("
|
39
|
-
|
40
|
-
its("
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
srv.
|
104
|
-
srv.
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
expect(config.load_balancers.first[:service].
|
110
|
-
expect(config.load_balancers.first[:service].
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
config.
|
137
|
-
config.
|
138
|
-
|
139
|
-
config.
|
140
|
-
config.
|
141
|
-
config.
|
142
|
-
config.
|
143
|
-
config.
|
144
|
-
config.
|
145
|
-
config.
|
146
|
-
config.
|
147
|
-
config.
|
148
|
-
config.
|
149
|
-
config.
|
150
|
-
config.
|
151
|
-
config.
|
152
|
-
config.
|
153
|
-
config.
|
154
|
-
config.
|
155
|
-
config.
|
156
|
-
|
157
|
-
config.
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
config.
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
config.
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
config.
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
config.
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
config.
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
config.
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
config.
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
config.
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
config.
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
config.
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
config.
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
config.
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
config.
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
config.
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
config.
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe VagrantPlugins::SoftLayer::Config do
|
4
|
+
let(:config) { described_class.new }
|
5
|
+
let(:machine) { double("machine") }
|
6
|
+
|
7
|
+
describe "defaults" do
|
8
|
+
subject do
|
9
|
+
config.tap do |o|
|
10
|
+
o.finalize!
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
its("api_key") { should be_nil }
|
15
|
+
its("api_timeout") { should eq 60 }
|
16
|
+
its("endpoint_url") { should eq VagrantPlugins::SoftLayer::API_PUBLIC_ENDPOINT }
|
17
|
+
its("username") { should be_nil }
|
18
|
+
|
19
|
+
its("datacenter") { should be_nil }
|
20
|
+
its("dedicated") { should be_false }
|
21
|
+
its("disk_capacity") { should be_nil }
|
22
|
+
its("domain") { should be_nil }
|
23
|
+
its("force_private_ip") { should be_false }
|
24
|
+
its("hostname") { should be_nil }
|
25
|
+
its("hourly_billing") { should be_true }
|
26
|
+
its("image_guid") { should be_nil }
|
27
|
+
its("local_disk") { should be_true }
|
28
|
+
its("max_memory") { should eq 1024 }
|
29
|
+
its("network_speed") { should eq 10 }
|
30
|
+
its("operating_system") { should eq "UBUNTU_LATEST" }
|
31
|
+
its("post_install") { should be_nil }
|
32
|
+
its("private_only") { should be_false }
|
33
|
+
its("provision_timeout") { should eq 1200 }
|
34
|
+
its("rebuild_timeout") { should eq 1200 }
|
35
|
+
its("ssh_key") { should be_nil }
|
36
|
+
its("start_cpus") { should eq 1 }
|
37
|
+
its("transaction_wait") { should be_true }
|
38
|
+
its("user_data") { should be_nil }
|
39
|
+
its("vlan_private") { should be_nil }
|
40
|
+
its("vlan_public") { should be_nil }
|
41
|
+
|
42
|
+
its("load_balancers") { should eq [] }
|
43
|
+
its("manage_dns") { should be_false }
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "overriding defaults" do
|
47
|
+
context "booleans" do
|
48
|
+
[true, false].each do |bool|
|
49
|
+
[:dedicated, :force_private_ip, :hourly_billing, :local_disk, :manage_dns, :private_only, :transaction_wait].each do |attribute|
|
50
|
+
it "should accept both true and false for #{attribute}" do
|
51
|
+
config.send("#{attribute}=".to_sym, bool)
|
52
|
+
config.finalize!
|
53
|
+
expect(config.send(attribute)).to eq bool
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "integers" do
|
60
|
+
[:api_timeout, :max_memory, :network_speed, :provision_timeout, :rebuild_timeout, :ssh_key, :start_cpus, :vlan_private, :vlan_public].each do |attribute|
|
61
|
+
it "should not default #{attribute} if overridden" do
|
62
|
+
config.send("#{attribute}=".to_sym, 999)
|
63
|
+
config.finalize!
|
64
|
+
expect(config.send(attribute)).to eq 999
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "strings" do
|
70
|
+
[:api_key, :datacenter, :endpoint_url, :username, :domain, :hostname, :image_guid, :operating_system, :post_install, :ssh_key, :user_data, :vlan_private, :vlan_public].each do |attribute|
|
71
|
+
it "should not default #{attribute} if overridden" do
|
72
|
+
config.send("#{attribute}=".to_sym, "foo")
|
73
|
+
config.finalize!
|
74
|
+
expect(config.send(attribute)).to eq "foo"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "int hash" do
|
80
|
+
it "should not default disk_capacity if overriden" do
|
81
|
+
config.send("disk_capacity=".to_sym, { 0 => 100, 2 => 25 } )
|
82
|
+
config.finalize!
|
83
|
+
expect(config.send("disk_capacity")).to eq { 0 => 100, 2 => 25 }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "joining load balancer" do
|
89
|
+
it "should set weight to 1 by default" do
|
90
|
+
config.join_load_balancer :port => 443, :vip => "1.1.1.1"
|
91
|
+
config.finalize!
|
92
|
+
expect(config.load_balancers.first[:service].weight).to eq(1)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should set passed options" do
|
96
|
+
config.join_load_balancer :foo => "bar", :port => 443, :vip => "1.1.1.1"
|
97
|
+
config.finalize!
|
98
|
+
expect(config.load_balancers.first[:foo]).to eq("bar")
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should set service parameters" do
|
102
|
+
config.join_load_balancer :port => 443, :vip => "1.1.1.1" do |srv|
|
103
|
+
srv.destination_port = 443
|
104
|
+
srv.health_check = "DNS"
|
105
|
+
srv.notes = "Some notes"
|
106
|
+
srv.weight = 9
|
107
|
+
end
|
108
|
+
config.finalize!
|
109
|
+
expect(config.load_balancers.first[:service].destination_port).to eq(443)
|
110
|
+
expect(config.load_balancers.first[:service].health_check).to eq("DNS")
|
111
|
+
expect(config.load_balancers.first[:service].notes).to eq("Some notes")
|
112
|
+
expect(config.load_balancers.first[:service].weight).to eq(9)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "using SL_ environment variables" do
|
117
|
+
before :each do
|
118
|
+
ENV.stub(:[]).with("SL_API_KEY").and_return("env_api_key")
|
119
|
+
ENV.stub(:[]).with("SL_USERNAME").and_return("env_username")
|
120
|
+
end
|
121
|
+
|
122
|
+
subject do
|
123
|
+
config.tap do |o|
|
124
|
+
o.finalize!
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
its("api_key") { should eq "env_api_key" }
|
129
|
+
its("username") { should eq "env_username" }
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "validation" do
|
133
|
+
before :each do
|
134
|
+
# Setup some good configuration values
|
135
|
+
config.api_key = "An API key"
|
136
|
+
config.api_timeout = 60
|
137
|
+
config.username = "An username"
|
138
|
+
|
139
|
+
config.datacenter = "ams01"
|
140
|
+
config.dedicated = false
|
141
|
+
config.domain = "example.com"
|
142
|
+
config.disk_capacity = { 0 => 25 }
|
143
|
+
config.force_private_ip = false
|
144
|
+
config.hostname = "vagrant"
|
145
|
+
config.hourly_billing = true
|
146
|
+
config.image_guid = nil
|
147
|
+
config.local_disk = true
|
148
|
+
config.max_memory = 1024
|
149
|
+
config.network_speed = 10
|
150
|
+
config.operating_system = "UBUNTU_LATEST"
|
151
|
+
config.post_install = "http://example.com/foo"
|
152
|
+
config.provision_timeout = 1200
|
153
|
+
config.rebuild_timeout = 1200
|
154
|
+
config.ssh_key = ["First key", "Second key"]
|
155
|
+
config.start_cpus = 1
|
156
|
+
config.transaction_wait = true
|
157
|
+
config.user_data = "some metadata"
|
158
|
+
config.vlan_private = 111
|
159
|
+
config.vlan_public = 222
|
160
|
+
|
161
|
+
config.manage_dns = false
|
162
|
+
|
163
|
+
machine.stub_chain(:config, :vm, :hostname).and_return(nil)
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should validate" do
|
167
|
+
config.finalize!
|
168
|
+
expect(config.validate(machine)["SoftLayer"]).to have(:no).item
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should fail if API key is not given" do
|
172
|
+
config.api_key = nil
|
173
|
+
config.finalize!
|
174
|
+
expect(config.validate(machine)["SoftLayer"]).to have(1).item
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should fail if username is not given" do
|
178
|
+
config.username = nil
|
179
|
+
config.finalize!
|
180
|
+
expect(config.validate(machine)["SoftLayer"]).to have(1).item
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should fail if domain is not given" do
|
184
|
+
config.domain = nil
|
185
|
+
config.finalize!
|
186
|
+
expect(config.validate(machine)["SoftLayer"]).to have(1).item
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should fail if hostname is not given" do
|
190
|
+
config.hostname = nil
|
191
|
+
config.finalize!
|
192
|
+
expect(config.validate(machine)["SoftLayer"]).to have(1).item
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should validate if hostname is not given but config.vm.hostname is set" do
|
196
|
+
config.hostname = nil
|
197
|
+
config.finalize!
|
198
|
+
machine.stub_chain(:config, :vm, :hostname).and_return("vagrant")
|
199
|
+
expect(config.validate(machine)["SoftLayer"]).to have(:no).item
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should fail if ssh key is not given" do
|
203
|
+
config.ssh_key = nil
|
204
|
+
config.finalize!
|
205
|
+
expect(config.validate(machine)["SoftLayer"]).to have(1).item
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should fail if a load balancer is specified without vip" do
|
209
|
+
config.join_load_balancer :port => 443 do |srv|
|
210
|
+
srv.destination_port = 443
|
211
|
+
end
|
212
|
+
config.finalize!
|
213
|
+
expect(config.validate(machine)["SoftLayer"]).to have(1).item
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should fail if a load balancer is specified without port" do
|
217
|
+
config.join_load_balancer :vip => "1.1.1.1" do |srv|
|
218
|
+
srv.destination_port = 443
|
219
|
+
end
|
220
|
+
config.finalize!
|
221
|
+
expect(config.validate(machine)["SoftLayer"]).to have(1).item
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should fail if a load balancer is specified without destination port" do
|
225
|
+
config.join_load_balancer :port => 443, :vip => "1.1.1.1"
|
226
|
+
config.finalize!
|
227
|
+
expect(config.validate(machine)["SoftLayer"]).to have(1).item
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should fail if two load balancers han been defined with same vip and port" do
|
231
|
+
config.join_load_balancer :port => 443, :vip => "1.1.1.1" do |srv|
|
232
|
+
srv.destination_port = 443
|
233
|
+
end
|
234
|
+
config.join_load_balancer :port => 443, :vip => "1.1.1.1" do |srv|
|
235
|
+
srv.destination_port = 8443
|
236
|
+
end
|
237
|
+
config.finalize!
|
238
|
+
expect(config.validate(machine)["SoftLayer"]).to have(1).item
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should validate if a load balancer if specified with vip, port and destination port" do
|
242
|
+
config.join_load_balancer :port => 443, :vip => "1.1.1.1" do |srv|
|
243
|
+
srv.destination_port = 443
|
244
|
+
end
|
245
|
+
config.finalize!
|
246
|
+
expect(config.validate(machine)["SoftLayer"]).to have(:no).item
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should fail if disk_capacity and image_guid are both specified" do
|
250
|
+
config.disk_capacity = { 0 => 25 }
|
251
|
+
config.image_guid = "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE"
|
252
|
+
config.operating_system = nil
|
253
|
+
config.finalize!
|
254
|
+
expect(config.validate(machine)["SoftLayer"]).to have(1).item
|
255
|
+
end
|
256
|
+
|
257
|
+
it "should fail if operating system and image_guid are both specified" do
|
258
|
+
config.image_guid = "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE"
|
259
|
+
config.operating_system = "UBUNTU_LATEST"
|
260
|
+
config.finalize!
|
261
|
+
expect(config.validate(machine)["SoftLayer"]).to have(1).item
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should validate if operating_system and disk_capacity are both specified" do
|
265
|
+
config.operating_system = "UBUNTU_LATEST"
|
266
|
+
config.disk_capacity = { 0 => 25 }
|
267
|
+
config.finalize!
|
268
|
+
expect(config.validate(machine)["SoftLayer"]).to have(:no).item
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|