kitchen-vcenter 2.6.0 → 2.7.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '09fe38f6c02640a964e4018849dd5051de454bf0a9c92d43e5d26958210a68a3'
4
- data.tar.gz: e84e03176304cb5d8a9720c47e03e38474d959de33f076b25ef9571d670288e7
3
+ metadata.gz: 336491e73efecaf915ea3d66abee8ec788a918b5f4f9a6b89a9a186622f1fbc4
4
+ data.tar.gz: 1c90b4a62e44c40837955a48afde23509c0afccbae563430fc6bfdc3ff7caae0
5
5
  SHA512:
6
- metadata.gz: 9fc5020968df60fc311e0ad4b6ced4e694201641974d8bae3213a97f03dbf951cb5811f81b516e73962de2e0420eac8019f353252969a2702caf48d76b88898a
7
- data.tar.gz: b3ad895ee096db923c9363f2461cad8315ff5cc6130cf2bb00ada31d2a501a46d95d350795e11afe04f5f4f0a1b29ad9f398d293eea00602a76e51974d9a5876
6
+ metadata.gz: bff63dd4a20821ce5ec1f8a2032ceae2962b4d26345810c23ebf44dc5548afc85b642342f617f54d8be79b8075b815f65c20df48070b718897216102cdeab2fc
7
+ data.tar.gz: 8384025e3a26ea8a33122f770aecb961a608f96deab7e349d4501676b1ce8628fc4035b65f0428be363fb31d845c677644729f95382de9d017be03d2e15650f6
@@ -20,5 +20,5 @@
20
20
  # The main kitchen-vcenter module
21
21
  module KitchenVcenter
22
22
  # The version of this version of test-kitchen we assume enterprises want.
23
- VERSION = "2.6.0"
23
+ VERSION = "2.7.6"
24
24
  end
@@ -18,7 +18,8 @@
18
18
  require "kitchen"
19
19
  require "vsphere-automation-cis"
20
20
  require "vsphere-automation-vcenter"
21
- require "support/clone_vm"
21
+ require_relative "../../kitchen-vcenter/version"
22
+ require_relative "../../support/clone_vm"
22
23
  require "securerandom"
23
24
  require "uri"
24
25
 
@@ -50,6 +51,7 @@ module Kitchen
50
51
  default_config :vm_wait_interval, 2.0
51
52
  default_config :vm_rollback, false
52
53
  default_config :customize, nil
54
+ default_config :guest_customization, nil
53
55
  default_config :interface, nil
54
56
  default_config :active_discovery, false
55
57
  default_config :active_discovery_command, nil
@@ -57,6 +59,7 @@ module Kitchen
57
59
  default_config :vm_username, "vagrant"
58
60
  default_config :vm_password, "vagrant"
59
61
  default_config :vm_win_network, "Ethernet0"
62
+ default_config :transform_ip, nil
60
63
 
61
64
  default_config :benchmark, false
62
65
  default_config :benchmark_file, "kitchen-vcenter.csv"
@@ -82,6 +85,8 @@ module Kitchen
82
85
  #
83
86
  # @param [Object] state is the state of the vm
84
87
  def create(state)
88
+ debug format("Starting kitchen-vcenter %s", ::KitchenVcenter::VERSION)
89
+
85
90
  save_and_validate_parameters
86
91
  connect
87
92
 
@@ -112,10 +117,13 @@ module Kitchen
112
117
  end
113
118
 
114
119
  # Check that the datacenter exists
115
- datacenter_exists?(config[:datacenter])
120
+ dc_folder = File.dirname(config[:datacenter])
121
+ dc_folder = nil if dc_folder == "."
122
+ dc_name = File.basename(config[:datacenter])
123
+ datacenter_exists?(dc_folder, dc_name)
116
124
 
117
125
  # Get datacenter and cluster information
118
- datacenter = get_datacenter(config[:datacenter])
126
+ datacenter = get_datacenter(dc_folder, dc_name)
119
127
  cluster_id = get_cluster_id(config[:cluster])
120
128
 
121
129
  # Using the clone class, create a machine for TK
@@ -152,12 +160,14 @@ module Kitchen
152
160
  wait_timeout: config[:vm_wait_timeout],
153
161
  wait_interval: config[:vm_wait_interval],
154
162
  customize: config[:customize],
163
+ guest_customization: config[:guest_customization],
155
164
  active_discovery: config[:active_discovery],
156
165
  active_discovery_command: config[:active_discovery_command],
157
166
  vm_os: config[:vm_os],
158
167
  vm_username: config[:vm_username],
159
168
  vm_password: config[:vm_password],
160
169
  vm_win_network: config[:vm_win_network],
170
+ transform_ip: config[:transform_ip],
161
171
  benchmark: config[:benchmark],
162
172
  benchmark_file: config[:benchmark_file],
163
173
  }
@@ -283,10 +293,13 @@ module Kitchen
283
293
 
284
294
  # Sees in the datacenter exists or not
285
295
  #
296
+ # @param [folder] folder is the name of the folder in which the Datacenter is stored in inventory, possibly nil
286
297
  # @param [name] name is the name of the datacenter
287
- def datacenter_exists?(name)
298
+ def datacenter_exists?(folder, name)
288
299
  dc_api = VSphereAutomation::VCenter::DatacenterApi.new(api_client)
289
- dcs = dc_api.list({ filter_names: name }).value
300
+ opts = { filter_names: name }
301
+ opts[:filter_folders] = get_folder(folder, "DATACENTER") if folder
302
+ dcs = dc_api.list(opts).value
290
303
 
291
304
  raise format("Unable to find data center: %s", name) if dcs.empty?
292
305
  end
@@ -321,9 +334,10 @@ module Kitchen
321
334
  # Gets the folder you want to create the VM
322
335
  #
323
336
  # @param [name] name is the name of the folder
324
- def get_folder(name)
337
+ # @param [type] type is the type of the folder, one of VIRTUAL_MACHINE, DATACENTER, possibly other values
338
+ def get_folder(name, type = "VIRTUAL_MACHINE")
325
339
  folder_api = VSphereAutomation::VCenter::FolderApi.new(api_client)
326
- folders = folder_api.list({ filter_names: name, filter_type: "VIRTUAL_MACHINE" }).value
340
+ folders = folder_api.list({ filter_names: name, filter_type: type }).value
327
341
 
328
342
  raise format("Unable to find folder: %s", name) if folders.empty?
329
343
 
@@ -344,10 +358,13 @@ module Kitchen
344
358
 
345
359
  # Gets the info of the datacenter
346
360
  #
361
+ # @param [folder] folder is the name of the folder in which the Datacenter is stored in inventory, possibly nil
347
362
  # @param [name] name is the name of the Datacenter
348
- def get_datacenter(name)
363
+ def get_datacenter(folder, name)
349
364
  dc_api = VSphereAutomation::VCenter::DatacenterApi.new(api_client)
350
- dcs = dc_api.list({ filter_names: name }).value
365
+ opts = { filter_names: name }
366
+ opts[:filter_folders] = get_folder(folder, "DATACENTER") if folder
367
+ dcs = dc_api.list(opts).value
351
368
 
352
369
  raise format("Unable to find data center: %s", name) if dcs.empty?
353
370
 
@@ -1,6 +1,6 @@
1
1
  require "kitchen"
2
2
  require "rbvmomi"
3
- require "support/guest_operations"
3
+ require_relative "guest_operations"
4
4
 
5
5
  class Support
6
6
  class CloneError < RuntimeError; end
@@ -81,6 +81,17 @@ class Support
81
81
  raise Support::CloneError.new("Timeout waiting for IP address") if ip.nil?
82
82
  raise Support::CloneError.new(format("Error getting accessible IP address, got %s. Check DHCP server and scope exhaustion", ip)) if ip =~ /^169\.254\./
83
83
 
84
+ # Allow IP rewriting (e.g. for 1:1 NAT)
85
+ if options[:transform_ip]
86
+ Kitchen.logger.info format("Received IP: %s", ip)
87
+
88
+ # rubocop:disable Security/Eval
89
+ ip = lambda { eval options[:transform_ip] }.call
90
+ # rubocop:enable Security/Eval
91
+
92
+ Kitchen.logger.info format("Transformed to IP: %s", ip)
93
+ end
94
+
84
95
  @ip = ip
85
96
  end
86
97
 
@@ -210,13 +221,13 @@ class Support
210
221
  case options[:vm_os].downcase.to_sym
211
222
  when :linux
212
223
  # @todo: allow override if no dhclient
213
- return [
224
+ [
214
225
  "/sbin/modprobe -r vmxnet3",
215
226
  "/sbin/modprobe vmxnet3",
216
227
  "/sbin/dhclient",
217
228
  ]
218
229
  when :windows
219
- return [
230
+ [
220
231
  "netsh interface set Interface #{options[:vm_win_network]} disable",
221
232
  "netsh interface set Interface #{options[:vm_win_network]} enable",
222
233
  "ipconfig /renew",
@@ -251,6 +262,8 @@ class Support
251
262
  # "wmic nicconfig get IPAddress",
252
263
  # "netsh interface ip show ipaddress #{options[:vm_win_network]}"
253
264
  end
265
+ else
266
+ options[:active_discovery_command]
254
267
  end
255
268
  end
256
269
 
@@ -395,15 +408,109 @@ class Support
395
408
  options[:clone_type] == :full
396
409
  end
397
410
 
411
+ def root_folder
412
+ @root_folder ||= vim.serviceInstance.content.rootFolder
413
+ end
414
+
415
+ #
416
+ # @return [String]
417
+ #
418
+ def datacenter
419
+ options[:datacenter]
420
+ end
421
+
422
+ #
423
+ # @return [RbVmomi::VIM::Datacenter]
424
+ #
425
+ def find_datacenter
426
+ vim.serviceInstance.find_datacenter(datacenter)
427
+ rescue RbVmomi::Fault
428
+ root_folder.childEntity.grep(RbVmomi::VIM::Datacenter).find { |x| x.name == datacenter }
429
+ end
430
+
431
+ def ip?(string)
432
+ IPAddr.new(string)
433
+ true
434
+ rescue IPAddr::InvalidAddressError
435
+ false
436
+ end
437
+
438
+ def customization_spec
439
+ unless options[:guest_customization]
440
+ return false
441
+ end
442
+
443
+ unless ip?(options[:guest_customization][:ip_address])
444
+ raise Support::CloneError.new("Guest customization error: ip_address is required to be formatted as an IPv4 address")
445
+ end
446
+
447
+ unless ip?(options[:guest_customization][:subnet_mask])
448
+ raise Support::CloneError.new("Guest customization error: subnet_mask is required to be formatted as an IPv4 address")
449
+ end
450
+
451
+ options[:guest_customization][:gateway].each do |v|
452
+ unless ip?(v)
453
+ raise Support::CloneError.new("Guest customization error: gateway is required to be formatted as an IPv4 address")
454
+ end
455
+ end
456
+
457
+ options[:guest_customization][:dns_server_list].each do |v|
458
+ unless ip?(v)
459
+ raise Support::CloneError.new("Guest customization error: dns_server_list is required to be formatted as an IPv4 address")
460
+ end
461
+ end
462
+
463
+ unless %i{dns_domain timezone dns_server_list dns_suffix_list ip_address gateway subnet_mask}.all? { |k| options[:guest_customization].key? k }
464
+ raise Support::CloneError.new("Guest customization error: currently all options are required to support guest customization")
465
+ end
466
+
467
+ if !options[:guest_customization][:dns_server_list].is_a?(Array)
468
+ raise Support::CloneError.new("Guest customization error: dns_server_list must be an array")
469
+ elsif !options[:guest_customization][:dns_suffix_list].is_a?(Array)
470
+ raise Support::CloneError.new("Guest customization error: dns_suffix_list must be an array")
471
+ elsif !options[:guest_customization][:gateway].is_a?(Array)
472
+ raise Support::CloneError.new("Guest customization error: gateway must be an array")
473
+ end
474
+
475
+ spec = RbVmomi::VIM::CustomizationSpec.new(
476
+ identity: RbVmomi::VIM::CustomizationLinuxPrep.new(
477
+ domain: options[:guest_customization][:dns_domain],
478
+ hostName: RbVmomi::VIM::CustomizationFixedName.new(
479
+ name: name
480
+ ),
481
+ hwClockUTC: true,
482
+ timeZone: options[:guest_customization][:timezone]
483
+ ),
484
+ globalIPSettings: RbVmomi::VIM::CustomizationGlobalIPSettings.new(
485
+ dnsServerList: options[:guest_customization][:dns_server_list],
486
+ dnsSuffixList: options[:guest_customization][:dns_suffix_list]
487
+ ),
488
+ nicSettingMap: [RbVmomi::VIM::CustomizationAdapterMapping.new(
489
+ adapter: RbVmomi::VIM::CustomizationIPSettings.new(
490
+ ip: RbVmomi::VIM::CustomizationFixedIp(
491
+ ipAddress: options[:guest_customization][:ip_address]
492
+ ),
493
+ gateway: options[:guest_customization][:gateway],
494
+ subnetMask: options[:guest_customization][:subnet_mask],
495
+ dnsDomain: options[:guest_customization][:dns_domain]
496
+ )
497
+ )]
498
+ )
499
+
500
+ spec
501
+ end
502
+
398
503
  def clone
399
504
  benchmark_start if benchmark?
400
505
 
401
506
  # set the datacenter name
402
- dc = vim.serviceInstance.find_datacenter(options[:datacenter])
507
+ dc = find_datacenter
508
+
509
+ # get guest customization spec
510
+ guest_customization = customization_spec
403
511
 
404
512
  # reference template using full inventory path
405
- root_folder = vim.serviceInstance.content.rootFolder
406
- inventory_path = format("/%s/vm/%s", options[:datacenter], options[:template])
513
+ inventory_path = format("/%s/vm/%s", datacenter, options[:template])
407
514
  src_vm = root_folder.findByInventoryPath(inventory_path)
408
515
  raise Support::CloneError.new(format("Unable to find template: %s", options[:template])) if src_vm.nil?
409
516
 
@@ -432,10 +539,11 @@ class Support
432
539
  # Change network, if wanted
433
540
  unless options[:network_name].nil?
434
541
  networks = dc.network.select { |n| n.name == options[:network_name] }
435
- raise Support::CloneError.new(format("Could not find network named %s", option[:network_name])) if networks.empty?
542
+ raise Support::CloneError.new(format("Could not find network named %s", options[:network_name])) if networks.empty?
436
543
 
437
544
  Kitchen.logger.warn format("Found %d networks named %s, picking first one", networks.count, options[:network_name]) if networks.count > 1
438
545
  network_obj = networks.first
546
+ network_device = network_device(src_vm)
439
547
 
440
548
  if network_obj.is_a? RbVmomi::VIM::DistributedVirtualPortgroup
441
549
  Kitchen.logger.info format("Assigning network %s...", network_obj.pretty_path)
@@ -443,7 +551,6 @@ class Support
443
551
  vds_obj = network_obj.config.distributedVirtualSwitch
444
552
  Kitchen.logger.info format("Using vDS '%s' for network connectivity...", vds_obj.name)
445
553
 
446
- network_device = network_device(src_vm)
447
554
  network_device.backing = RbVmomi::VIM.VirtualEthernetCardDistributedVirtualPortBackingInfo(
448
555
  port: RbVmomi::VIM.DistributedVirtualSwitchPortConnection(
449
556
  portgroupKey: network_obj.key,
@@ -520,9 +627,15 @@ class Support
520
627
  benchmark_checkpoint("initialized") if benchmark?
521
628
  task = src_vm.InstantClone_Task(spec: clone_spec)
522
629
  else
523
- clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(location: relocate_spec,
524
- powerOn: options[:poweron] && options[:customize].nil?,
525
- template: false)
630
+ clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(
631
+ location: relocate_spec,
632
+ powerOn: options[:poweron] && options[:customize].nil?,
633
+ template: false
634
+ )
635
+
636
+ if guest_customization
637
+ clone_spec.customization = guest_customization
638
+ end
526
639
 
527
640
  benchmark_checkpoint("initialized") if benchmark?
528
641
  task = src_vm.CloneVM_Task(spec: clone_spec, folder: dest_folder, name: name)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-vcenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0
4
+ version: 2.7.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef Software
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-05 00:00:00.000000000 Z
11
+ date: 2020-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbvmomi
@@ -30,20 +30,6 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '3.0'
33
- - !ruby/object:Gem::Dependency
34
- name: savon
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '2.11'
40
- type: :runtime
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: '2.11'
47
33
  - !ruby/object:Gem::Dependency
48
34
  name: test-kitchen
49
35
  requirement: !ruby/object:Gem::Requirement
@@ -78,34 +64,6 @@ dependencies:
78
64
  - - "~>"
79
65
  - !ruby/object:Gem::Version
80
66
  version: '0.4'
81
- - !ruby/object:Gem::Dependency
82
- name: bundler
83
- requirement: !ruby/object:Gem::Requirement
84
- requirements:
85
- - - ">="
86
- - !ruby/object:Gem::Version
87
- version: '0'
88
- type: :development
89
- prerelease: false
90
- version_requirements: !ruby/object:Gem::Requirement
91
- requirements:
92
- - - ">="
93
- - !ruby/object:Gem::Version
94
- version: '0'
95
- - !ruby/object:Gem::Dependency
96
- name: rake
97
- requirement: !ruby/object:Gem::Requirement
98
- requirements:
99
- - - ">="
100
- - !ruby/object:Gem::Version
101
- version: '0'
102
- type: :development
103
- prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- requirements:
106
- - - ">="
107
- - !ruby/object:Gem::Version
108
- version: '0'
109
67
  description: Test Kitchen driver for VMware vCenter using SDK
110
68
  email:
111
69
  - oss@chef.io
@@ -130,7 +88,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
88
  requirements:
131
89
  - - ">="
132
90
  - !ruby/object:Gem::Version
133
- version: '2.3'
91
+ version: '2.4'
134
92
  required_rubygems_version: !ruby/object:Gem::Requirement
135
93
  requirements:
136
94
  - - ">="