fog-vsphere 3.6.5 → 3.6.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fog/vsphere/compute.rb +12 -0
  3. data/lib/fog/vsphere/models/compute/nvmecontroller.rb +24 -0
  4. data/lib/fog/vsphere/models/compute/scsicontroller.rb +5 -1
  5. data/lib/fog/vsphere/models/compute/server.rb +33 -18
  6. data/lib/fog/vsphere/models/compute/volume.rb +1 -2
  7. data/lib/fog/vsphere/requests/compute/create_vm.rb +11 -4
  8. data/lib/fog/vsphere/requests/compute/get_vm_first_nvme_controller.rb +21 -0
  9. data/lib/fog/vsphere/requests/compute/list_vm_nvme_controllers.rb +29 -0
  10. data/lib/fog/vsphere/requests/compute/vm_clone.rb +1 -1
  11. data/lib/fog/vsphere/version.rb +1 -1
  12. data/tests/class_from_string_tests.rb +33 -0
  13. data/tests/compute_tests.rb +53 -0
  14. data/tests/fixtures/vcr_cassettes/6_7/create_folder.yml +609 -0
  15. data/tests/fixtures/vcr_cassettes/6_7/folder_destroy.yml +823 -0
  16. data/tests/fixtures/vcr_cassettes/6_7/get_cluster.yml +663 -0
  17. data/tests/fixtures/vcr_cassettes/6_7/get_compute_resource.yml +1046 -0
  18. data/tests/fixtures/vcr_cassettes/6_7/get_datacenter.yml +498 -0
  19. data/tests/fixtures/vcr_cassettes/6_7/get_folder.yml +2038 -0
  20. data/tests/fixtures/vcr_cassettes/6_7/get_host.yml +386 -0
  21. data/tests/fixtures/vcr_cassettes/6_7/get_network.yml +932 -0
  22. data/tests/fixtures/vcr_cassettes/6_7/get_storage_pod.yml +225 -0
  23. data/tests/fixtures/vcr_cassettes/6_7/get_template.yml +329 -0
  24. data/tests/fixtures/vcr_cassettes/6_7/get_virtual_machine.yml +329 -0
  25. data/tests/fixtures/vcr_cassettes/6_7/get_vm_first_nvme_controller.yml +105 -0
  26. data/tests/fixtures/vcr_cassettes/6_7/get_vm_first_sata_controller.yml +209 -0
  27. data/tests/fixtures/vcr_cassettes/6_7/get_vm_first_scsi_controller.yml +111 -0
  28. data/tests/fixtures/vcr_cassettes/6_7/shared.yml +164 -0
  29. data/tests/helper.rb +6 -0
  30. data/tests/helpers/mock_helper.rb +9 -0
  31. data/tests/models/compute/cluster_tests.rb +18 -0
  32. data/tests/models/compute/hosts_tests.rb +11 -0
  33. data/tests/models/compute/rules_tests.rb +28 -0
  34. data/tests/models/compute/server_tests.rb +74 -0
  35. data/tests/models/compute/server_unit_tests.rb +13 -0
  36. data/tests/models/compute/servers_tests.rb +14 -0
  37. data/tests/models/compute/ticket_tests.rb +12 -0
  38. data/tests/models/compute/tickets_tests.rb +8 -0
  39. data/tests/requests/compute/create_folder_tests.rb +19 -0
  40. data/tests/requests/compute/current_time_tests.rb +10 -0
  41. data/tests/requests/compute/folder_destroy_tests.rb +39 -0
  42. data/tests/requests/compute/get_cluster_tests.rb +19 -0
  43. data/tests/requests/compute/get_compute_resource_tests.rb +19 -0
  44. data/tests/requests/compute/get_datacenter_tests.rb +19 -0
  45. data/tests/requests/compute/get_folder_tests.rb +28 -0
  46. data/tests/requests/compute/get_host_tests.rb +19 -0
  47. data/tests/requests/compute/get_network_tests.rb +78 -0
  48. data/tests/requests/compute/get_storage_pod_tests.rb +19 -0
  49. data/tests/requests/compute/get_template_tests.rb +19 -0
  50. data/tests/requests/compute/get_virtual_machine_tests.rb +19 -0
  51. data/tests/requests/compute/get_vm_first_nvme_controller_tests.rb +19 -0
  52. data/tests/requests/compute/get_vm_first_sata_controller_tests.rb +19 -0
  53. data/tests/requests/compute/get_vm_first_scsi_controller_tests.rb +19 -0
  54. data/tests/requests/compute/list_child_snapshots_tests.rb +9 -0
  55. data/tests/requests/compute/list_clusters_tests.rb +10 -0
  56. data/tests/requests/compute/list_datastores_tests.rb +17 -0
  57. data/tests/requests/compute/list_hosts_tests.rb +10 -0
  58. data/tests/requests/compute/list_networks_tests.rb +17 -0
  59. data/tests/requests/compute/list_storage_pods_test.rb +9 -0
  60. data/tests/requests/compute/list_virtual_machines_tests.rb +34 -0
  61. data/tests/requests/compute/list_vm_cdroms_tests.rb +9 -0
  62. data/tests/requests/compute/list_vm_snapshots_tests.rb +9 -0
  63. data/tests/requests/compute/modify_vm_cdrom_tests.rb +20 -0
  64. data/tests/requests/compute/revert_to_snapshot_tests.rb +13 -0
  65. data/tests/requests/compute/set_vm_customvalue_tests.rb +18 -0
  66. data/tests/requests/compute/update_vm_tests.rb +13 -0
  67. data/tests/requests/compute/vm_clone_tests.rb +55 -0
  68. data/tests/requests/compute/vm_config_vnc_tests.rb +18 -0
  69. data/tests/requests/compute/vm_destroy_tests.rb +14 -0
  70. data/tests/requests/compute/vm_migrate_tests.rb +15 -0
  71. data/tests/requests/compute/vm_power_off_tests.rb +24 -0
  72. data/tests/requests/compute/vm_power_on_tests.rb +15 -0
  73. data/tests/requests/compute/vm_reboot_tests.rb +24 -0
  74. data/tests/requests/compute/vm_reconfig_cdrom_tests.rb +14 -0
  75. data/tests/requests/compute/vm_reconfig_cpus_tests.rb +17 -0
  76. data/tests/requests/compute/vm_reconfig_hardware_tests.rb +17 -0
  77. data/tests/requests/compute/vm_reconfig_memory_tests.rb +17 -0
  78. data/tests/requests/compute/vm_suspend_tests.rb +23 -0
  79. data/tests/requests/compute/vm_take_snapshot_tests.rb +17 -0
  80. data/tests/test_helper.rb +74 -0
  81. metadata +152 -19
  82. data/.github/workflows/ruby.yml +0 -42
  83. data/.gitignore +0 -25
  84. data/.rubocop.yml +0 -44
  85. data/.rubocop_todo.yml +0 -614
  86. data/CONTRIBUTING.md +0 -55
  87. data/Gemfile +0 -5
  88. data/Jenkinsfile +0 -10
  89. data/fog-vsphere.gemspec +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a169539c87e9059730923e051d3e08ef56a1d376d44a79cc95d13a8fe10756f2
4
- data.tar.gz: bc058ee169f529dbd0d5ee6110fa1e08e2ee9d885f8e4b0ecf119af4a69fde94
3
+ metadata.gz: 819e41def6f26e5e5c0b8da2e15fbd84afd9d4ff2d32b566fd67edc616e5d765
4
+ data.tar.gz: 305ceccf0f1718b079d7082723b0d760ff3738033e4f1492719be75d301f96ea
5
5
  SHA512:
6
- metadata.gz: ce176624f1d5e490a885548c6bea5b6e19badc4f23316edb499ff521ebc251bac6a281ffea719301b0af5139d01e639b10dbbae6fe0883f24b33522b29685110
7
- data.tar.gz: 67aafb6d34c2764899b3ccb3b88bb17f5334094df9483e288d1970950a88f38aa152dc7926a0b1c04beb01337032cac520586b8788da7d36fd55288e82c7c542
6
+ metadata.gz: 979f8ff4d77c5dd92bbe2f404308c4100db6f5d59ba8ea0ac382b4e578e8ee775c5eb5d1355ebe43b035537aaf295e55dfb7a1a5e58da58cefc6a05d4ebe3eb4
7
+ data.tar.gz: 81742888f852d0d898d0d61105552eca3380d23af4da0b8600c142976311eba0735fdfb13eef9326e79ffcaf26b87e5a9b338bb7f65f4e6791d81d29676f5643
@@ -43,6 +43,7 @@ module Fog
43
43
  model :customfield
44
44
  collection :customfields
45
45
  model :scsicontroller
46
+ model :nvmecontroller
46
47
  model :process
47
48
  model :cdrom
48
49
  collection :cdroms
@@ -111,6 +112,7 @@ module Fog
111
112
  request :list_customfields
112
113
  request :get_vm_first_scsi_controller
113
114
  request :list_vm_scsi_controllers
115
+ request :list_vm_nvme_controllers
114
116
  request :set_vm_customvalue
115
117
  request :vm_take_snapshot
116
118
  request :list_vm_snapshots
@@ -136,6 +138,7 @@ module Fog
136
138
  request :host_start_maintenance
137
139
  request :host_finish_maintenance
138
140
  request :get_vm_first_sata_controller
141
+ request :get_vm_first_nvme_controller
139
142
 
140
143
  module Shared
141
144
  attr_reader :vsphere_is_vcenter
@@ -346,10 +349,12 @@ module Fog
346
349
  end
347
350
  end
348
351
 
352
+ # rubocop:disable Metrics/ClassLength
349
353
  class Mock
350
354
  include Shared
351
355
  # rubocop:disable Metrics/MethodLength
352
356
  def self.data
357
+ # rubocop:disable Metrics/BlockLength
353
358
  @data ||= Hash.new do |hash, key|
354
359
  hash[key] = {
355
360
  servers: {
@@ -380,6 +385,11 @@ module Fog
380
385
  'type' => 'VirtualLsiLogicController',
381
386
  'unit_number' => 7,
382
387
  'key' => 1000 }],
388
+ 'nvme_controllers' =>
389
+ [{
390
+ 'type' => 'VirtualNVMEController',
391
+ 'key' => 2000
392
+ }],
383
393
  'interfaces' =>
384
394
  [{ 'mac' => '00:50:56:a9:00:28',
385
395
  'network' => 'dvportgroup-123456',
@@ -616,6 +626,7 @@ module Fog
616
626
  }
617
627
  }
618
628
  end
629
+ # rubocop:enable Metrics/BlockLength
619
630
  end
620
631
 
621
632
  # rubocop:enable Metrics/MethodLength
@@ -637,6 +648,7 @@ module Fog
637
648
  self.class.data.delete(@vsphere_username)
638
649
  end
639
650
  end
651
+ # rubocop:enable Metrics/ClassLength
640
652
 
641
653
  class Real
642
654
  include Shared
@@ -0,0 +1,24 @@
1
+ module Fog
2
+ module Vsphere
3
+ class Compute
4
+ class NVMEController < Fog::Model
5
+ attribute :type
6
+ attribute :unit_number
7
+ attribute :key, type: :integer
8
+ attribute :server_id
9
+ DEFAULT_KEY = 2000
10
+ DEFAULT_TYPE = "VirtualNVMEController".freeze
11
+
12
+ def initialize(attributes = {})
13
+ super
14
+ self.key ||= DEFAULT_KEY
15
+ self.type ||= DEFAULT_TYPE
16
+ end
17
+
18
+ def to_s
19
+ "#{type} ##{key}:, unit_number: #{unit_number}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -8,9 +8,13 @@ module Fog
8
8
  attribute :key, type: :integer
9
9
  attribute :server_id
10
10
 
11
+ DEFAULT_KEY = 1000
12
+ DEFAULT_TYPE = "VirtualLsiLogicController".freeze
13
+
11
14
  def initialize(attributes = {})
12
15
  super
13
- self.key ||= 1000
16
+ self.key ||= DEFAULT_KEY
17
+ self.type ||= DEFAULT_TYPE
14
18
  end
15
19
 
16
20
  def to_s
@@ -3,7 +3,7 @@ require 'fog/compute/models/server'
3
3
  module Fog
4
4
  module Vsphere
5
5
  class Compute
6
- class Server < Fog::Compute::Server
6
+ class Server < Fog::Compute::Server # rubocop:disable Metrics/ClassLength
7
7
  extend Fog::Deprecation
8
8
  deprecate(:ipaddress, :public_ip_address)
9
9
  deprecate(:scsi_controller, :scsi_controllers)
@@ -49,6 +49,7 @@ module Fog
49
49
  attribute :guest_id
50
50
  attribute :hardware_version
51
51
  attribute :scsi_controllers, type: :array
52
+ attribute :nvme_controllers, type: :array
52
53
  attribute :cpuHotAddEnabled
53
54
  attribute :memoryHotAddEnabled
54
55
  attribute :firmware
@@ -60,9 +61,10 @@ module Fog
60
61
  super defaults.merge(attributes)
61
62
  self.instance_uuid ||= id # TODO: remvoe instance_uuid as it can be replaced with simple id
62
63
  initialize_interfaces
63
- initialize_volumes
64
64
  initialize_customvalues
65
65
  initialize_scsi_controllers
66
+ initialize_nvme_controllers
67
+ initialize_volumes
66
68
  end
67
69
 
68
70
  # Lazy Loaded Attributes
@@ -289,6 +291,10 @@ module Fog
289
291
  attributes[:scsi_controllers] ||= service.list_vm_scsi_controllers(id)
290
292
  end
291
293
 
294
+ def nvme_controllers
295
+ attributes[:nvme_controllers] ||= service.list_vm_nvme_controllers(id)
296
+ end
297
+
292
298
  def scsi_controller
293
299
  scsi_controllers.first
294
300
  end
@@ -348,16 +354,21 @@ module Fog
348
354
  end
349
355
  end
350
356
 
357
+ def unassigned_volumes?
358
+ attributes[:volumes]&.any? { |vol| !vol.key?(:controller_key) } || false
359
+ end
360
+
361
+ def update_controller_key(vol)
362
+ vol.controller_key ||= attributes[:scsi_controllers].first&.key || 1000
363
+ end
364
+
351
365
  def initialize_volumes
352
- if attributes[:volumes] && attributes[:volumes].is_a?(Array)
353
- attributes[:volumes].map! do |vol|
354
- if vol.is_a?(Hash)
355
- service.volumes.new({ server: self }.merge(vol))
356
- else
357
- vol.server = self
358
- vol
359
- end
360
- end
366
+ return unless attributes[:volumes].is_a?(Array)
367
+ attributes[:volumes].map! do |vol|
368
+ vol = service.volumes.new({ server: self }.merge(vol)) if vol.is_a?(Hash)
369
+ vol.server = self
370
+ update_controller_key(vol)
371
+ vol
361
372
  end
362
373
  end
363
374
 
@@ -368,19 +379,23 @@ module Fog
368
379
  end
369
380
 
370
381
  def initialize_scsi_controllers
371
- if attributes[:scsi_controllers] && attributes[:scsi_controllers].is_a?(Array)
382
+ if attributes[:scsi_controllers].is_a?(Array) && !attributes[:scsi_controllers].empty?
372
383
  attributes[:scsi_controllers].map! do |controller|
373
384
  controller.is_a?(Hash) ? Fog::Vsphere::Compute::SCSIController.new(controller) : controller
374
385
  end
375
- elsif attributes[:scsi_controller] && attributes[:scsi_controller].is_a?(Hash)
386
+ elsif attributes[:scsi_controller].is_a?(Hash) && !attributes[:scsi_controller].empty?
376
387
  attributes[:scsi_controllers] = [
377
388
  Fog::Vsphere::Compute::SCSIController.new(attributes[:scsi_controller])
378
389
  ]
379
- elsif attributes[:volumes] && attributes[:volumes].is_a?(Array) && !attributes[:volumes].empty?
380
- # Create a default scsi controller if there are any disks but no controller defined
381
- attributes[:scsi_controllers] = [
382
- Fog::Vsphere::Compute::SCSIController.new
383
- ]
390
+ end
391
+ attributes[:scsi_controllers] = [Fog::Vsphere::Compute::SCSIController.new] if !attributes[:scsi_controllers]&.any? && unassigned_volumes?
392
+ end
393
+
394
+ def initialize_nvme_controllers
395
+ if attributes[:nvme_controllers].is_a?(Array)
396
+ attributes[:nvme_controllers].map! do |controller|
397
+ controller.is_a?(Hash) ? Fog::Vsphere::Compute::NVMEController.new(controller) : controller
398
+ end
384
399
  end
385
400
  end
386
401
  end
@@ -126,8 +126,7 @@ module Fog
126
126
  {
127
127
  thin: true,
128
128
  name: 'Hard disk',
129
- mode: 'persistent',
130
- controller_key: 1000
129
+ mode: 'persistent'
131
130
  }
132
131
  end
133
132
 
@@ -138,10 +138,14 @@ module Fog
138
138
  devices << nics.map { |nic| create_interface(nic, nics.index(nic), :add, attributes) }
139
139
  end
140
140
 
141
- if (scsi_controllers = (attributes[:scsi_controllers] || attributes['scsi_controller']))
141
+ if (scsi_controllers = attributes[:scsi_controllers] || attributes['scsi_controller'])
142
142
  devices << scsi_controllers.each_with_index.map { |controller, index| create_controller(controller, index) }
143
143
  end
144
144
 
145
+ if (nvme_controllers = attributes[:nvme_controllers])
146
+ devices << nvme_controllers.each_with_index.map { |controller, index| create_controller(controller, index) }
147
+ end
148
+
145
149
  if (disks = attributes[:volumes])
146
150
  devices << disks.map { |disk| create_disk(disk, :add, storage_pod: get_storage_pod_from_volumes(attributes)) }
147
151
  end
@@ -241,11 +245,15 @@ module Fog
241
245
  end
242
246
 
243
247
  def create_controller(controller = nil, index = 0)
248
+ device_options = {}
244
249
  options = if controller
245
250
  controller_default_options.merge(controller.attributes)
246
251
  else
247
252
  controller_default_options
248
- end
253
+ end
254
+ unless [RbVmomi::VIM::VirtualAHCIController, RbVmomi::VIM::VirtualNVMEController, "VirtualNVMEController"].include?(options[:type])
255
+ device_options[:sharedBus] = controller_get_shared_from_options(options)
256
+ end
249
257
  controller_class = if options[:type].is_a? String
250
258
  Fog::Vsphere.class_from_string options[:type], 'RbVmomi::VIM'
251
259
  else
@@ -254,8 +262,7 @@ module Fog
254
262
  {
255
263
  operation: options[:operation],
256
264
  device: controller_class.new(key: options[:key] || (1000 + index),
257
- busNumber: options[:bus_id] || index,
258
- **(options[:type] == RbVmomi::VIM::VirtualAHCIController ? {} : {sharedBus: controller_get_shared_from_options(options)}))
265
+ busNumber: options[:bus_id] || index, **device_options)
259
266
  }
260
267
  end
261
268
 
@@ -0,0 +1,21 @@
1
+ module Fog
2
+ module Vsphere
3
+ class Compute
4
+ class Real
5
+ def get_vm_first_nvme_controller(vm_id)
6
+ ctrl = get_vm_ref(vm_id).config.hardware.device.find { |device| device.is_a?(RbVmomi::VIM::VirtualNVMEController) }
7
+ raise Fog::Vsphere::Compute::NotFound, "No NVME controller found for #{vm_id}" unless ctrl
8
+ {
9
+ type: ctrl&.class.to_s,
10
+ device_info: ctrl&.deviceInfo,
11
+ bus_number: ctrl&.busNumber,
12
+ key: ctrl&.key
13
+ }
14
+ end
15
+ end
16
+ class Mock
17
+ def get_vm_first_nvme_controller(vm_id); end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ module Fog
2
+ module Vsphere
3
+ class Compute
4
+ class Real
5
+ def list_vm_nvme_controllers(vm_id)
6
+ list_vm_nvme_controllers_raw(vm_id).map do |raw_controller|
7
+ Fog::Vsphere::Compute::NVMEController.new(raw_controller)
8
+ end
9
+ end
10
+
11
+ def list_vm_nvme_controllers_raw(vm_id)
12
+ get_vm_ref(vm_id).config.hardware.device.grep(RbVmomi::VIM::VirtualNVMEController).map do |ctrl|
13
+ {
14
+ type: ctrl.class.to_s,
15
+ key: ctrl.key
16
+ }
17
+ end
18
+ end
19
+ end
20
+ class Mock
21
+ def list_vm_nvme_controllers(vm_id)
22
+ raise Fog::Vsphere::Compute::NotFound, 'VM not Found' unless data[:servers].key?(vm_id)
23
+ return [] unless data[:servers][vm_id].key?('nvme_controllers')
24
+ data[:servers][vm_id]['nvme_controllers'].map { |h| h.merge(server_id: vm_id) }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -886,8 +886,8 @@ module Fog
886
886
  )
887
887
  end
888
888
  end
889
-
890
889
  # rubocop:enable Metrics/ClassLength
890
+
891
891
  class Mock
892
892
  include Shared
893
893
  def vm_clone(options = {})
@@ -1,5 +1,5 @@
1
1
  module Fog
2
2
  module Vsphere
3
- VERSION = '3.6.5'.freeze
3
+ VERSION = '3.6.6'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,33 @@
1
+ require_relative './helper'
2
+
3
+ class A; class B; class C; end; end; end
4
+
5
+ class TestClassFromString < Minitest::Test
6
+ def test_empty_string
7
+ assert_nil(Fog::Vsphere.class_from_string(''))
8
+ end
9
+
10
+ def test_nil
11
+ assert_nil(Fog::Vsphere.class_from_string(nil))
12
+ end
13
+
14
+ def test_name_as_class
15
+ assert_equal(A, Fog::Vsphere.class_from_string(A))
16
+ end
17
+
18
+ def test_name_as_string
19
+ assert_equal(A, Fog::Vsphere.class_from_string('A'))
20
+ end
21
+
22
+ def test_unexpected_input
23
+ assert_nil(Fog::Vsphere.class_from_string(8))
24
+ end
25
+
26
+ def test_nested_class_without_default_path
27
+ assert_equal(A::B::C, Fog::Vsphere.class_from_string(A::B::C))
28
+ end
29
+
30
+ def test_nested_class_with_default_path
31
+ assert_equal(A::B::C, Fog::Vsphere.class_from_string('C', 'A::B'))
32
+ end
33
+ end
@@ -0,0 +1,53 @@
1
+ Shindo.tests('Fog::Compute[:vsphere]', ['vsphere']) do
2
+ compute = Fog::Compute[:vsphere]
3
+
4
+ tests('| convert_vm_mob_ref_to_attr_hash') do
5
+ # Mock the RbVmomi::VIM::ManagedObject class
6
+ class MockManagedObject
7
+ attr_reader :parent, :_ref
8
+
9
+ def initialize
10
+ @parent = @_ref = 'vm-123'
11
+ end
12
+
13
+ # rubocop:disable Naming/VariableName
14
+ def collect!(*_pathSet)
15
+ { '_ref' => 'vm-123', 'name' => 'fakevm' }
16
+ end
17
+ end
18
+
19
+ fake_vm_mob_ref = MockManagedObject.new
20
+
21
+ tests('When converting an incomplete vm object') do
22
+ test('it should return a Hash') do
23
+ compute.send(:convert_vm_mob_ref_to_attr_hash, fake_vm_mob_ref).is_a? Hash
24
+ end
25
+ tests('The converted Hash should') do
26
+ attr_hash = compute.send(:convert_vm_mob_ref_to_attr_hash, fake_vm_mob_ref)
27
+ test('have a name') { attr_hash['name'] == 'fakevm' }
28
+ test('have a mo_ref') { attr_hash['mo_ref'] == 'vm-123' }
29
+ test('have an id') { attr_hash['id'] == 'vm-123' }
30
+ test('not have a instance_uuid') { attr_hash['instance_uuid'].nil? }
31
+ end
32
+ end
33
+
34
+ tests('When passed a nil object') do
35
+ attr_hash = compute.send :convert_vm_mob_ref_to_attr_hash, nil
36
+ test('it should return a nil object') do
37
+ attr_hash.nil?
38
+ end
39
+ end
40
+ end
41
+
42
+ tests('Compute attributes') do
43
+ %w[vsphere_is_vcenter vsphere_rev vsphere_username vsphere_server].each do |attr|
44
+ test("it should respond to #{attr}") { compute.respond_to? attr }
45
+ end
46
+ end
47
+
48
+ tests('Compute collections') do
49
+ %w[servers].each do |collection|
50
+ test("it should respond to #{collection}") { compute.respond_to? collection }
51
+ end
52
+ end
53
+ end