vagrant-softlayer 0.3.3 → 0.4.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 +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
|