clc-chef-metal-vsphere 0.3.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.
@@ -0,0 +1,250 @@
1
+ require 'rbvmomi'
2
+
3
+ module ChefMetalVsphere
4
+ module Helpers
5
+
6
+ def vim(options = connect_options)
7
+ # reconnect on every call - connections may silently timeout during long operations (e.g. cloning)
8
+ RbVmomi::VIM.connect options
9
+ end
10
+
11
+ def find_vm(dc_name, vm_folder, vm_name)
12
+ folder = find_folder(dc_name, vm_folder) or raise("vSphere Folder not found [#{vm_folder}] for vm #{vm_name}")
13
+ vm = folder.find(vm_name, RbVmomi::VIM::VirtualMachine)
14
+ end
15
+
16
+ def find_vm_by_id(uuid, connection = vim)
17
+ vm = connection.searchIndex.FindByUuid({:uuid => uuid, :vmSearch => true, :instanceUuid => true})
18
+ end
19
+
20
+ def vm_started?(vm, wait_on_port = 22)
21
+ return false if vm.nil?
22
+ state = vm.runtime.powerState
23
+ return false unless state == 'poweredOn'
24
+ return false unless port_ready?(vm, wait_on_port)
25
+ return true
26
+ end
27
+
28
+ def vm_stopped?(vm)
29
+ return true if vm.nil?
30
+ state = vm.runtime.powerState
31
+ return false unless state == 'poweredOff'
32
+ return false
33
+ end
34
+
35
+ def start_vm(vm, wait_on_port = 22)
36
+ state = vm.runtime.powerState
37
+ unless state == 'poweredOn'
38
+ vm.PowerOnVM_Task.wait_for_completion
39
+ end
40
+ end
41
+
42
+ def stop_vm(vm)
43
+ begin
44
+ vm.ShutdownGuest
45
+ sleep 2 until vm.runtime.powerState == 'poweredOff'
46
+ rescue
47
+ vm.PowerOffVM_Task.wait_for_completion
48
+ end
49
+ end
50
+
51
+ def port_ready?(vm, port)
52
+ vm_ip = vm.guest.ipAddress
53
+ return false if vm_ip.nil?
54
+
55
+ begin
56
+ tcp_socket = TCPSocket.new(vm_ip, port)
57
+ readable = IO.select([tcp_socket], nil, nil, 5)
58
+ if readable
59
+ true
60
+ else
61
+ false
62
+ end
63
+ rescue Errno::ETIMEDOUT
64
+ false
65
+ rescue Errno::EPERM
66
+ false
67
+ rescue Errno::ECONNREFUSED
68
+ false
69
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH
70
+ false
71
+ ensure
72
+ tcp_socket && tcp_socket.close
73
+ end
74
+ end
75
+
76
+ #folder could be like: /Level1/Level2/folder_name
77
+ def find_folder(dc_name, folder_name)
78
+ #dc(dc_name).vmFolder.childEntity.grep(RbVmomi::VIM::Folder).find { |x| x.name == folder_name }
79
+ baseEntity = dc(dc_name).vmFolder
80
+ if folder_name && folder_name.length > 0
81
+ entityArray = folder_name.split('/')
82
+ entityArray.each do |entityArrItem|
83
+ if entityArrItem != ''
84
+ baseEntity = baseEntity.childEntity.grep(RbVmomi::VIM::Folder).find { |f| f.name == entityArrItem }
85
+ end
86
+ end
87
+ end
88
+ baseEntity
89
+ end
90
+
91
+ def dc(dc_name)
92
+ vim.serviceInstance.find_datacenter(dc_name) or raise("vSphere Datacenter not found [#{datacenter}]")
93
+ end
94
+
95
+ def do_vm_clone(dc_name, vm_template, vm_name, options)
96
+ datacenter = dc(dc_name)
97
+ pool = options[:resource_pool] ? find_pool(datacenter, options[:resource_pool]) : vm_template.resourcePool
98
+ rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(pool: pool)
99
+ raise ':resource_pool must be specified when cloning from a VM Template' if pool.nil?
100
+
101
+ unless options[:datastore].to_s.empty?
102
+ rspec.datastore = find_datastore(datacenter, options[:datastore])
103
+ end
104
+
105
+ clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(
106
+ location: rspec,
107
+ powerOn: false,
108
+ template: false
109
+ )
110
+
111
+ clone_spec.config = RbVmomi::VIM.VirtualMachineConfigSpec(:deviceChange => Array.new)
112
+
113
+ if options.has_key?(:customization_spec)
114
+ if(options[:customization_spec].is_a?(Hash))
115
+ cust_options = options[:customization_spec]
116
+ raise ArgumentError, "domain is required" unless cust_options.key?(:domain)
117
+ if cust_options.key?(:ipsettings)
118
+ raise ArgumentError, "ip and subnetMask is required for static ip" unless cust_options[:ipsettings].key?(:ip) and
119
+ cust_options[:ipsettings].key?(:subnetMask)
120
+ cust_ip_settings = RbVmomi::VIM::CustomizationIPSettings.new(cust_options[:ipsettings])
121
+ cust_ip_settings.ip = RbVmomi::VIM::CustomizationFixedIp(:ipAddress => cust_options[:ipsettings][:ip])
122
+ end
123
+ cust_domain = cust_options[:domain]
124
+ cust_ip_settings ||= RbVmomi::VIM::CustomizationIPSettings.new(:ip => RbVmomi::VIM::CustomizationDhcpIpGenerator.new())
125
+ cust_ip_settings.dnsDomain = cust_domain
126
+ cust_global_ip_settings = RbVmomi::VIM::CustomizationGlobalIPSettings.new
127
+ cust_global_ip_settings.dnsServerList = cust_ip_settings.dnsServerList
128
+ cust_global_ip_settings.dnsSuffixList = [cust_domain]
129
+ cust_hostname = RbVmomi::VIM::CustomizationFixedName.new(:name => cust_options[:hostname]) if cust_options.key?(:hostname)
130
+ cust_hostname ||= RbVmomi::VIM::CustomizationFixedName.new(:name => vm_name)
131
+ cust_hwclockutc = cust_options[:hw_clock_utc]
132
+ cust_timezone = cust_options[:time_zone]
133
+ cust_prep = RbVmomi::VIM::CustomizationLinuxPrep.new(
134
+ :domain => cust_domain,
135
+ :hostName => cust_hostname,
136
+ :hwClockUTC => cust_hwclockutc,
137
+ :timeZone => cust_timezone)
138
+ cust_adapter_mapping = [RbVmomi::VIM::CustomizationAdapterMapping.new(:adapter => cust_ip_settings)]
139
+ cust_spec = RbVmomi::VIM::CustomizationSpec.new(
140
+ :identity => cust_prep,
141
+ :globalIPSettings => cust_global_ip_settings,
142
+ :nicSettingMap => cust_adapter_mapping)
143
+ else
144
+ cust_spec = find_customization_spec(options[:customization_spec])
145
+ end
146
+ clone_spec.customization = cust_spec
147
+ end
148
+
149
+ unless options[:annotation].to_s.nil?
150
+ clone_spec.config.annotation = options[:annotation]
151
+ end
152
+
153
+ unless options[:num_cpus].to_s.nil?
154
+ clone_spec.config.numCPUs = options[:num_cpus]
155
+ end
156
+
157
+ unless options[:memory_mb].to_s.nil?
158
+ clone_spec.config.memoryMB = options[:memory_mb]
159
+ end
160
+
161
+ unless options[:network_name].to_s.nil?
162
+ network = find_network(datacenter, options[:network_name])
163
+ card = vm_template.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard).first
164
+ begin
165
+ switch_port = RbVmomi::VIM.DistributedVirtualSwitchPortConnection(:switchUuid => network.config.distributedVirtualSwitch.uuid, :portgroupKey => network.key)
166
+ card.backing.port = switch_port
167
+ rescue
168
+ # not connected to a distibuted switch?
169
+ card.backing.deviceName = options[:network_name]
170
+ end
171
+ dev_spec = RbVmomi::VIM.VirtualDeviceConfigSpec(:device => card, :operation => "edit")
172
+ clone_spec.config.deviceChange.push dev_spec
173
+ end
174
+
175
+ vm_template.CloneVM_Task(
176
+ name: vm_name,
177
+ folder: find_folder(dc_name, options[:vm_folder]),
178
+ spec: clone_spec
179
+ ).wait_for_completion
180
+
181
+ vm = find_vm(dc_name, options[:vm_folder], vm_name)
182
+
183
+ unless options[:additional_disk_size_gb].to_s.nil?
184
+ if options[:datastore].to_s.empty?
185
+ raise ":datastore must be specified when adding a disk to a cloned vm"
186
+ end
187
+ idx = vm.disks.count
188
+ task = vm.ReconfigVM_Task(:spec => RbVmomi::VIM.VirtualMachineConfigSpec(:deviceChange =>[RbVmomi::VIM::VirtualDeviceConfigSpec(
189
+ :operation => :add,
190
+ :fileOperation => :create,
191
+ :device => RbVmomi::VIM.VirtualDisk(
192
+ :key => idx,
193
+ :backing => RbVmomi::VIM.VirtualDiskFlatVer2BackingInfo(
194
+ :fileName => "[#{options[:datastore]}]",
195
+ :diskMode => 'persistent',
196
+ :thinProvisioned => true
197
+ ),
198
+ :capacityInKB => options[:additional_disk_size_gb] * 1024 * 1024,
199
+ :controllerKey => 1000,
200
+ :unitNumber => idx
201
+ )
202
+ )]))
203
+ task.wait_for_completion
204
+ end
205
+
206
+ vm
207
+ end
208
+
209
+ def find_network(dc, network_name)
210
+ baseEntity = dc.network
211
+ baseEntity.find { |f| f.name == network_name } or raise "no such network #{network_name}"
212
+ end
213
+
214
+ def find_datastore(dc, datastore_name)
215
+ baseEntity = dc.datastore
216
+ baseEntity.find { |f| f.info.name == datastore_name } or raise "no such datastore #{datastore_name}"
217
+ end
218
+
219
+ def find_pool(dc, pool_name)
220
+ baseEntity = dc.hostFolder
221
+ entityArray = pool_name.split('/')
222
+ entityArray.each do |entityArrItem|
223
+ if entityArrItem != ''
224
+ if baseEntity.is_a? RbVmomi::VIM::Folder
225
+ baseEntity = baseEntity.childEntity.find { |f| f.name == entityArrItem } or nil
226
+ elsif baseEntity.is_a? RbVmomi::VIM::ClusterComputeResource or baseEntity.is_a? RbVmomi::VIM::ComputeResource
227
+ baseEntity = baseEntity.resourcePool.resourcePool.find { |f| f.name == entityArrItem } or nil
228
+ elsif baseEntity.is_a? RbVmomi::VIM::ResourcePool
229
+ baseEntity = baseEntity.resourcePool.find { |f| f.name == entityArrItem } or nil
230
+ else
231
+ baseEntity = nil
232
+ end
233
+ end
234
+ end
235
+
236
+ raise "vSphere ResourcePool not found [#{pool_name}]" if baseEntity.nil?
237
+
238
+ baseEntity = baseEntity.resourcePool if not baseEntity.is_a?(RbVmomi::VIM::ResourcePool) and baseEntity.respond_to?(:resourcePool)
239
+ baseEntity
240
+ end
241
+
242
+ def find_customization_spec(customization_spec)
243
+ csm = vim.serviceContent.customizationSpecManager
244
+ csi = csm.GetCustomizationSpec(:name => customization_spec)
245
+ spec = csi.spec
246
+ raise "Customization Spec not found [#{customization_spec}]" if spec.nil?
247
+ spec
248
+ end
249
+ end
250
+ end
@@ -0,0 +1,31 @@
1
+ require 'uri'
2
+
3
+ module URI
4
+ class VsphereUrl < Generic
5
+ DEFAULT_PORT = 443
6
+ DEFAULT_PATH = '/sdk'
7
+
8
+ def self.from_config(options)
9
+ URI("vsphere://#{options[:host]}:#{options[:port]}#{options[:path]}?use_ssl=#{options[:use_ssl]}&insecure=#{options[:insecure]}")
10
+ end
11
+
12
+ def use_ssl
13
+ if query
14
+ ssl_query = query.split('&').each.select{|q| q.start_with?('use_ssl=')}.first
15
+ ssl_query == 'use_ssl=true'
16
+ else
17
+ true
18
+ end
19
+ end
20
+
21
+ def insecure
22
+ if query
23
+ insecure_query = query.split('&').each.select{|q| q.start_with?('insecure=')}.first
24
+ insecure_query == 'insecure=true'
25
+ else
26
+ false
27
+ end
28
+ end
29
+ end
30
+ @@schemes['VSPHERE'] = VsphereUrl
31
+ end
@@ -0,0 +1 @@
1
+ config.rb
@@ -0,0 +1,123 @@
1
+ require 'chef_metal_vsphere/vsphere_driver'
2
+ #require 'chef_metal_vsphere/ubuntu_patch'
3
+ require 'chef_metal/chef_machine_spec'
4
+
5
+ # A file named config.rb in the same directory as this spec file
6
+ # must exist containing the driver options to use for the test.
7
+ # Here is an example:
8
+ # {
9
+ # :driver_options => {
10
+ # :host => '213.45.67.88',
11
+ # :user => 'vmapi',
12
+ # :password => 'SuperSecureP@ssw0rd',
13
+ # :insecure => true
14
+ # },
15
+ # :machine_options => {
16
+ # :start_timeout => 600,
17
+ # :create_timeout => 600,
18
+ # :bootstrap_options => {
19
+ # :datacenter => 'QA1',
20
+ # :template_name => 'UBUNTU-12-64-TEMPLATE',
21
+ # :vm_folder => 'DLAB',
22
+ # :num_cpus => 2,
23
+ # :network_name => 'vlan152_172.21.152',
24
+ # :memory_mb => 4096,
25
+ # :resource_pool => 'CLSTR02/DLAB',
26
+ # :ssh => {
27
+ # :user => 'root',
28
+ # :password => 'SuperSecureP@ssw0rd',
29
+ # :paranoid => false,
30
+ # :port => 22
31
+ # },
32
+ # :convergence_options => {}
33
+ # }
34
+ # }
35
+ # }
36
+
37
+ describe "vsphere_driver" do
38
+ include ChefMetalVsphere::Helpers
39
+
40
+ before :all do
41
+ @vm_name = "cmvd-test-#{SecureRandom.hex}"
42
+ @metal_config = eval File.read(File.expand_path('../config.rb', __FILE__))
43
+ Cheffish.honor_local_mode do
44
+ chef_server = Cheffish.default_chef_server(@metal_config)
45
+ puts "chef server:#{chef_server}"
46
+ @machine_spec = ChefMetal::ChefMachineSpec.new({'name' => @vm_name}, chef_server)
47
+ @driver = ChefMetal.driver_for_url("vsphere://#{@metal_config[:driver_options][:host]}", @metal_config)
48
+ action_handler = ChefMetal::ActionHandler.new
49
+ @driver.allocate_machine(action_handler, @machine_spec, @metal_config[:machine_options])
50
+ @metal_config[:machine_options][:convergence_options] = {:chef_server => chef_server}
51
+ @driver.ready_machine(action_handler, @machine_spec, @metal_config[:machine_options])
52
+ @server_id = @machine_spec.location['server_id']
53
+ @connection = vim(@metal_config[:driver_options])
54
+ @vm = find_vm_by_id(@server_id, @connection)
55
+ end
56
+ end
57
+
58
+
59
+ context 'when allocating a machine' do
60
+
61
+ it "adds machine to the correct folder" do
62
+ expect(@vm.parent.name).to eq(@metal_config[:machine_options][:bootstrap_options][:vm_folder])
63
+ end
64
+ it "has a matching id with the machine_spec" do
65
+ expect(@vm.config.instanceUuid).to eq(@machine_spec.location['server_id'])
66
+ end
67
+ it "has the correct name" do
68
+ expect(@vm.config.name).to eq(@vm_name)
69
+ end
70
+ it "has the correct number of CPUs" do
71
+ expect(@vm.config.hardware.numCPU).to eq(@metal_config[:machine_options][:bootstrap_options][:num_cpus])
72
+ end
73
+ it "has the correct amount of memory" do
74
+ expect(@vm.config.hardware.memoryMB).to eq(@metal_config[:machine_options][:bootstrap_options][:memory_mb])
75
+ end
76
+ it "is on the correct network" do
77
+ expect(@vm.network[0].name).to eq(@metal_config[:machine_options][:bootstrap_options][:network_name])
78
+ end
79
+ it "is on the correct datastore" do
80
+ expect(@vm.datastore[0].name).to eq(@metal_config[:machine_options][:bootstrap_options][:datastore])
81
+ end
82
+ it "is in the correct resource pool" do
83
+ expect(@vm.resourcePool.name).to eq(@metal_config[:machine_options][:bootstrap_options][:resource_pool].split('/')[1])
84
+ end
85
+ it "is in the correct cluster" do
86
+ expect(@vm.resourcePool.owner.name).to eq(@metal_config[:machine_options][:bootstrap_options][:resource_pool].split('/')[0])
87
+ end
88
+ it "is in the correct datacenter" do
89
+ expect(@connection.serviceInstance.find_datacenter(@metal_config[:machine_options][:bootstrap_options][:datacenter]).find_vm("#{@vm.parent.name}/#{@vm_name}")).not_to eq(nil)
90
+ end
91
+ it "has an added disk of the correct size" do
92
+ disk_count = @vm.disks.count
93
+ expect(@vm.disks[disk_count-1].capacityInKB).to eq(@metal_config[:machine_options][:bootstrap_options][:additional_disk_size_gb] * 1024 * 1024)
94
+ end
95
+ it "has the correct IP address" do
96
+ if @vm.guest.toolsRunningStatus != "guestToolsRunning"
97
+ now = Time.now.utc
98
+ until (Time.now.utc - now) > 30 || (@vm.guest.toolsRunningStatus == "guestToolsRunning" && !@vm.guest.ipAddress.nil? && @vm.guest.ipAddress.length > 0) do
99
+ print "."
100
+ sleep 5
101
+ end
102
+ end
103
+ expect(@vm.guest.ipAddress).to eq(@metal_config[:machine_options][:bootstrap_options][:customization_spec][:ipsettings][:ip])
104
+ end
105
+ end
106
+
107
+ context "destroy_machine" do
108
+
109
+ it "removes the machine" do
110
+ Cheffish.honor_local_mode do
111
+ chef_server = Cheffish.default_chef_server(@metal_config)
112
+ driver = ChefMetal.driver_for_url("vsphere://#{@metal_config[:driver_options][:host]}", @metal_config)
113
+ action_handler = ChefMetal::ActionHandler.new
114
+ machine_spec = ChefMetal::ChefMachineSpec.new({'name' => @vm_name}, chef_server)
115
+ machine_spec.location = { 'driver_url' => driver.driver_url,
116
+ 'server_id' => @server_id}
117
+ driver.destroy_machine(action_handler, machine_spec, @metal_config[:machine_options])
118
+ end
119
+ vm = find_vm_by_id(@server_id, @connection)
120
+ expect(vm).to eq(nil)
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,206 @@
1
+ require 'chef_metal_vsphere/vsphere_driver'
2
+
3
+ describe "canonicalize_url" do
4
+
5
+ context "when config does not include the properties included in the url" do
6
+ metal_config = {
7
+ :driver_options => {
8
+ :user => 'vmapi',
9
+ :password => '<password>'
10
+ },
11
+ :machine_options => {
12
+ :ssh => {
13
+ :password => '<password>',
14
+ :paranoid => false
15
+ },
16
+ :bootstrap_options => {
17
+ :datacenter => 'QA1',
18
+ :template_name => 'UBUNTU-12-64-TEMPLATE',
19
+ :vm_folder => 'DLAB',
20
+ :num_cpus => 2,
21
+ :memory_mb => 4096,
22
+ :resource_pool => 'CLSTR02/DLAB'
23
+ }
24
+ },
25
+ :log_level => :debug
26
+ }
27
+
28
+ let(:results) {
29
+ ChefMetalVsphere::VsphereDriver.canonicalize_url('vsphere://3.3.3.3:999/crazyapi?use_ssl=false&insecure=true', metal_config)
30
+ }
31
+
32
+ it "populates the config with correct host from the driver url" do
33
+ expect(results[1][:driver_options][:connect_options][:host]).to eq('3.3.3.3')
34
+ end
35
+ it "populates the config with correct port from the driver url" do
36
+ expect(results[1][:driver_options][:connect_options][:port]).to eq(999)
37
+ end
38
+ it "populates the config with correct path from the driver url" do
39
+ expect(results[1][:driver_options][:connect_options][:path]).to eq('/crazyapi')
40
+ end
41
+ it "populates the config with correct use_ssl setting from the driver url" do
42
+ expect(results[1][:driver_options][:connect_options][:use_ssl]).to eq(false)
43
+ end
44
+ it "populates the config with correct insecure setting from the driver url" do
45
+ expect(results[1][:driver_options][:connect_options][:insecure]).to eq(true)
46
+ end
47
+ end
48
+
49
+ context "when config keys are stringified" do
50
+ metal_config = {
51
+ 'driver_options' => {
52
+ 'user' => 'vmapi',
53
+ 'password' => '<password>'
54
+ },
55
+ 'machine_options' => {
56
+ 'ssh' => {
57
+ 'password' => '<password>'
58
+ },
59
+ 'bootstrap_options' => {
60
+ 'datacenter' => 'QA1'
61
+ }
62
+ }
63
+ }
64
+
65
+ let(:results) {
66
+ ChefMetalVsphere::VsphereDriver.canonicalize_url('vsphere://3.3.3.3:999/crazyapi?use_ssl=false&insecure=true', metal_config)
67
+ }
68
+
69
+ it "will symbolize user" do
70
+ expect(results[1][:driver_options][:connect_options][:user]).to eq('vmapi')
71
+ end
72
+ it "will symbolize password" do
73
+ expect(results[1][:driver_options][:connect_options][:password]).to eq('<password>')
74
+ end
75
+ it "will symbolize ssh password" do
76
+ expect(results[1][:machine_options][:ssh][:password]).to eq('<password>')
77
+ end
78
+ it "will symbolize ssh bootstrap options" do
79
+ expect(results[1][:machine_options][:bootstrap_options][:datacenter]).to eq('QA1')
80
+ end
81
+ end
82
+
83
+ context "when no url is in the config" do
84
+ metal_config = {
85
+ :driver_options => {
86
+ :user => 'vmapi',
87
+ :password => '<password>',
88
+ :host => '4.4.4.4',
89
+ :port => 888,
90
+ :path => '/yoda',
91
+ :use_ssl => 'false',
92
+ :insecure => 'true'
93
+ },
94
+ :machine_options => {
95
+ :ssh => {
96
+ :password => '<password>',
97
+ :paranoid => false
98
+ },
99
+ :bootstrap_options => {
100
+ :datacenter => 'QA1',
101
+ :template_name => 'UBUNTU-12-64-TEMPLATE',
102
+ :vm_folder => 'DLAB',
103
+ :num_cpus => 2,
104
+ :memory_mb => 4096,
105
+ :resource_pool => 'CLSTR02/DLAB'
106
+ }
107
+ },
108
+ :log_level => :debug
109
+ }
110
+
111
+ let(:results) {
112
+ ChefMetalVsphere::VsphereDriver.canonicalize_url(nil, metal_config)
113
+ }
114
+
115
+ it "creates the correct driver url from config settings" do
116
+ expect(results[0]).to eq('vsphere://4.4.4.4:888/yoda?use_ssl=false&insecure=true')
117
+ end
118
+ end
119
+
120
+ context "when no url is in the config and config is missing defaulted values" do
121
+ metal_config = {
122
+ :driver_options => {
123
+ :user => 'vmapi',
124
+ :password => '<password>',
125
+ :host => '4.4.4.4'
126
+ },
127
+ :machine_options => {
128
+ :bootstrap_options => {
129
+ :datacenter => 'QA1',
130
+ :template_name => 'UBUNTU-12-64-TEMPLATE',
131
+ :vm_folder => 'DLAB',
132
+ :num_cpus => 2,
133
+ :memory_mb => 4096,
134
+ :resource_pool => 'CLSTR02/DLAB',
135
+ :ssh => {
136
+ :password => '<password>',
137
+ :paranoid => false
138
+ }
139
+ }
140
+ },
141
+ :log_level => :debug
142
+ }
143
+
144
+ let(:results) {
145
+ ChefMetalVsphere::VsphereDriver.canonicalize_url(nil, metal_config)
146
+ }
147
+
148
+ it "creates the correct driver url from default settings" do
149
+ expect(results[0]).to eq('vsphere://4.4.4.4/sdk?use_ssl=true&insecure=false')
150
+ end
151
+ it "populates the config with correct port from default settings" do
152
+ expect(results[1][:driver_options][:connect_options][:port]).to eq(443)
153
+ end
154
+ it "populates the config with correct path from default settings" do
155
+ expect(results[1][:driver_options][:connect_options][:path]).to eq('/sdk')
156
+ end
157
+ it "populates the config with correct use_ssl setting from default settings" do
158
+ expect(results[1][:driver_options][:connect_options][:use_ssl]).to eq(true)
159
+ end
160
+ it "populates the config with correct insecure setting from default settings" do
161
+ expect(results[1][:driver_options][:connect_options][:insecure]).to eq(false)
162
+ end
163
+ it "populates the config with correct ssh port from default settings" do
164
+ expect(results[1][:machine_options][:bootstrap_options][:ssh][:port]).to eq(22)
165
+ end
166
+ end
167
+
168
+ context "when missing host" do
169
+ metal_config = {
170
+ :driver_options => {
171
+ :user => 'vmapi',
172
+ :password => '<password>',
173
+ }
174
+ }
175
+
176
+ it "should raise an error" do
177
+ expect{ChefMetalVsphere::VsphereDriver.canonicalize_url(nil,metal_config)}.to raise_error(RuntimeError)
178
+ end
179
+ end
180
+
181
+ context "when missing user" do
182
+ metal_config = {
183
+ :driver_options => {
184
+ :host => 'host',
185
+ :password => '<password>',
186
+ }
187
+ }
188
+
189
+ it "should raise an error" do
190
+ expect{ChefMetalVsphere::VsphereDriver.canonicalize_url(nil,metal_config)}.to raise_error(RuntimeError)
191
+ end
192
+ end
193
+
194
+ context "when missing password" do
195
+ metal_config = {
196
+ :driver_options => {
197
+ :host => 'host',
198
+ :user => 'user',
199
+ }
200
+ }
201
+
202
+ it "should raise an error" do
203
+ expect{ChefMetalVsphere::VsphereDriver.canonicalize_url(nil,metal_config)}.to raise_error(RuntimeError)
204
+ end
205
+ end
206
+ end