kitchen-vcenter 2.7.0 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da86b6422044114b6f2b89cc85b8dc527fa5b743f2ff733e604c4730773e6fae
4
- data.tar.gz: dab5b088008e3344b2d52fca17d97a4fffaf25a4dbf486b4ac7139d82bedbf00
3
+ metadata.gz: f3fb477d8c5d39ca1340bb9593fbbbfcd54d3fceb477f6aeb996f92bd0c62897
4
+ data.tar.gz: fe45e70e975a4a26e87f92c3ce46d844993c954bfcd41c9dc9808229aadb1ec2
5
5
  SHA512:
6
- metadata.gz: 7fe27912e489acea7d4d126ca4ff6db750d24dbb56024ff387816db7b2948522da203a1d01cb728a7f16b10b0e44fb0bd27bfefa54a93849328fde67fe939d07
7
- data.tar.gz: daadea97931ae326c43ab040ccd3cd5ebea0d724f76a8c9e3cc86b5e16c2f47b519fb7e66859f3db106b5366f05fd20d6ee5e373ef29d5098756d58845a9d1ee
6
+ metadata.gz: fe27bc6dc42e1ccfbcb8593281337b8aa5f7c20eae4c7a66a63887daef0d6be6d31ce82ef82e91cc90cf9e297ea3a096999ed00801737919879341e623d489c8
7
+ data.tar.gz: cf02a3623872e75f65bbe7a106ed616bf50f705fcbf39bdd36d7d5c4c88a2335f872075ce88736df4587536c2dccce09a3feeff3d8431cf9091dc329e829638b
@@ -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.7.0"
23
+ VERSION = "2.8.0"
24
24
  end
@@ -20,8 +20,8 @@ require "vsphere-automation-cis"
20
20
  require "vsphere-automation-vcenter"
21
21
  require_relative "../../kitchen-vcenter/version"
22
22
  require_relative "../../support/clone_vm"
23
- require "securerandom"
24
- require "uri"
23
+ require "securerandom" unless defined?(SecureRandom)
24
+ require "uri" unless defined?(URI)
25
25
 
26
26
  # The main kitchen module
27
27
  module Kitchen
@@ -51,6 +51,7 @@ module Kitchen
51
51
  default_config :vm_wait_interval, 2.0
52
52
  default_config :vm_rollback, false
53
53
  default_config :customize, nil
54
+ default_config :guest_customization, nil
54
55
  default_config :interface, nil
55
56
  default_config :active_discovery, false
56
57
  default_config :active_discovery_command, nil
@@ -116,10 +117,13 @@ module Kitchen
116
117
  end
117
118
 
118
119
  # Check that the datacenter exists
119
- 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)
120
124
 
121
125
  # Get datacenter and cluster information
122
- datacenter = get_datacenter(config[:datacenter])
126
+ datacenter = get_datacenter(dc_folder, dc_name)
123
127
  cluster_id = get_cluster_id(config[:cluster])
124
128
 
125
129
  # Using the clone class, create a machine for TK
@@ -133,7 +137,7 @@ module Kitchen
133
137
  unless config[:folder].nil?
134
138
  config[:folder] = {
135
139
  name: config[:folder],
136
- id: get_folder(config[:folder]),
140
+ id: get_folder(config[:folder], "VIRTUAL_MACHINE", datacenter),
137
141
  }
138
142
  end
139
143
 
@@ -156,6 +160,7 @@ module Kitchen
156
160
  wait_timeout: config[:vm_wait_timeout],
157
161
  wait_interval: config[:vm_wait_interval],
158
162
  customize: config[:customize],
163
+ guest_customization: config[:guest_customization],
159
164
  active_discovery: config[:active_discovery],
160
165
  active_discovery_command: config[:active_discovery_command],
161
166
  vm_os: config[:vm_os],
@@ -288,10 +293,13 @@ module Kitchen
288
293
 
289
294
  # Sees in the datacenter exists or not
290
295
  #
296
+ # @param [folder] folder is the name of the folder in which the Datacenter is stored in inventory, possibly nil
291
297
  # @param [name] name is the name of the datacenter
292
- def datacenter_exists?(name)
298
+ def datacenter_exists?(folder, name)
293
299
  dc_api = VSphereAutomation::VCenter::DatacenterApi.new(api_client)
294
- 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
295
303
 
296
304
  raise format("Unable to find data center: %s", name) if dcs.empty?
297
305
  end
@@ -326,13 +334,20 @@ module Kitchen
326
334
  # Gets the folder you want to create the VM
327
335
  #
328
336
  # @param [name] name is the name of the folder
329
- def get_folder(name)
337
+ # @param [type] type is the type of the folder, one of VIRTUAL_MACHINE, DATACENTER, possibly other values
338
+ # @param [datacenter] datacenter is the datacenter of the folder
339
+ def get_folder(name, type = "VIRTUAL_MACHINE", datacenter = nil)
330
340
  folder_api = VSphereAutomation::VCenter::FolderApi.new(api_client)
331
- folders = folder_api.list({ filter_names: name, filter_type: "VIRTUAL_MACHINE" }).value
341
+ parent_path, basename = File.split(name)
342
+ filter = { filter_names: basename, filter_type: type }
343
+ filter[:filter_datacenters] = datacenter if datacenter
344
+ filter[:filter_parent_folders] = get_folder(parent_path, type, datacenter) unless parent_path == "."
332
345
 
333
- raise format("Unable to find folder: %s", name) if folders.empty?
346
+ folders = folder_api.list(filter).value
334
347
 
335
- raise format("%s returned too many folders", name) if folders.length > 1
348
+ raise format("Unable to find folder: %s", basename) if folders.empty?
349
+
350
+ raise format("`%s` returned too many folders", basename) if folders.length > 1
336
351
 
337
352
  folders.first.folder
338
353
  end
@@ -349,10 +364,13 @@ module Kitchen
349
364
 
350
365
  # Gets the info of the datacenter
351
366
  #
367
+ # @param [folder] folder is the name of the folder in which the Datacenter is stored in inventory, possibly nil
352
368
  # @param [name] name is the name of the Datacenter
353
- def get_datacenter(name)
369
+ def get_datacenter(folder, name)
354
370
  dc_api = VSphereAutomation::VCenter::DatacenterApi.new(api_client)
355
- dcs = dc_api.list({ filter_names: name }).value
371
+ opts = { filter_names: name }
372
+ opts[:filter_folders] = get_folder(folder, "DATACENTER") if folder
373
+ dcs = dc_api.list(opts).value
356
374
 
357
375
  raise format("Unable to find data center: %s", name) if dcs.empty?
358
376
 
@@ -408,14 +426,14 @@ module Kitchen
408
426
  # impact on small environments, but on large deployments with lots of clusters and pools,
409
427
  # provisioned machines are likely to "jump around" available hosts.
410
428
  #
411
- # This behaviour is carried on from versions 1.2.1 and lower, but likely to be removed in
429
+ # This behavior is carried on from versions 1.2.1 and lower, but likely to be removed in
412
430
  # a new major version due to these insufficiencies and the confusing code for it
413
431
 
414
- # Remove default pool for first pass (<= 1.2.1 behaviour to pick first user-defined pool found)
432
+ # Remove default pool for first pass (<= 1.2.1 behavior to pick first user-defined pool found)
415
433
  resource_pools = rp_api.list.value.delete_if { |pool| pool.name == "Resources" }
416
434
  debug("Search of all resource pools found: " + resource_pools.map(&:name).to_s)
417
435
 
418
- # Revert to default pool, if no user-defined pool found (> 1.2.1 behaviour)
436
+ # Revert to default pool, if no user-defined pool found (> 1.2.1 behavior)
419
437
  # (This one might not be found under some circumstances by the statement above)
420
438
  return get_resource_pool("Resources") if resource_pools.empty?
421
439
  else
@@ -221,13 +221,13 @@ class Support
221
221
  case options[:vm_os].downcase.to_sym
222
222
  when :linux
223
223
  # @todo: allow override if no dhclient
224
- return [
224
+ [
225
225
  "/sbin/modprobe -r vmxnet3",
226
226
  "/sbin/modprobe vmxnet3",
227
227
  "/sbin/dhclient",
228
228
  ]
229
229
  when :windows
230
- return [
230
+ [
231
231
  "netsh interface set Interface #{options[:vm_win_network]} disable",
232
232
  "netsh interface set Interface #{options[:vm_win_network]} enable",
233
233
  "ipconfig /renew",
@@ -428,12 +428,104 @@ class Support
428
428
  root_folder.childEntity.grep(RbVmomi::VIM::Datacenter).find { |x| x.name == datacenter }
429
429
  end
430
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
+ if options[:guest_customization][:ip_address]
444
+ unless ip?(options[:guest_customization][:ip_address])
445
+ raise Support::CloneError.new("Guest customization error: ip_address is required to be formatted as an IPv4 address")
446
+ end
447
+
448
+ unless options[:guest_customization][:subnet_mask]
449
+ raise Support::CloneError.new("Guest customization error: subnet_mask is required if assigning a fixed IPv4 address")
450
+ end
451
+
452
+ unless ip?(options[:guest_customization][:subnet_mask])
453
+ raise Support::CloneError.new("Guest customization error: subnet_mask is required to be formatted as an IPv4 address")
454
+ end
455
+ end
456
+
457
+ if options[:guest_customization][:gateway]
458
+ unless options[:guest_customization][:gateway].is_a?(Array)
459
+ raise Support::CloneError.new("Guest customization error: gateway must be an array")
460
+ end
461
+
462
+ options[:guest_customization][:gateway].each do |v|
463
+ unless ip?(v)
464
+ raise Support::CloneError.new("Guest customization error: gateway is required to be formatted as an IPv4 address")
465
+ end
466
+ end
467
+ end
468
+
469
+ required = %i{dns_domain timezone dns_server_list dns_suffix_list}
470
+ missing = required - options[:guest_customization].keys
471
+ unless missing.empty?
472
+ raise Support::CloneError.new("Guest customization error: #{missing.join(", ")} are required to support guest customization")
473
+ end
474
+
475
+ options[:guest_customization][:dns_server_list].each do |v|
476
+ unless ip?(v)
477
+ raise Support::CloneError.new("Guest customization error: dns_server_list is required to be formatted as an IPv4 address")
478
+ end
479
+ end
480
+
481
+ if !options[:guest_customization][:dns_server_list].is_a?(Array)
482
+ raise Support::CloneError.new("Guest customization error: dns_server_list must be an array")
483
+ elsif !options[:guest_customization][:dns_suffix_list].is_a?(Array)
484
+ raise Support::CloneError.new("Guest customization error: dns_suffix_list must be an array")
485
+ end
486
+
487
+ if options[:guest_customization][:ip_address]
488
+ customized_ip = RbVmomi::VIM::CustomizationIPSettings.new(
489
+ ip: RbVmomi::VIM::CustomizationFixedIp(ipAddress: options[:guest_customization][:ip_address]),
490
+ gateway: options[:guest_customization][:gateway],
491
+ subnetMask: options[:guest_customization][:subnet_mask],
492
+ dnsDomain: options[:guest_customization][:dns_domain]
493
+ )
494
+ else
495
+ customized_ip = RbVmomi::VIM::CustomizationIPSettings.new(
496
+ ip: RbVmomi::VIM::CustomizationDhcpIpGenerator.new,
497
+ dnsDomain: options[:guest_customization][:dns_domain]
498
+ )
499
+ end
500
+
501
+ RbVmomi::VIM::CustomizationSpec.new(
502
+ identity: RbVmomi::VIM::CustomizationLinuxPrep.new(
503
+ domain: options[:guest_customization][:dns_domain],
504
+ hostName: RbVmomi::VIM::CustomizationFixedName.new(
505
+ name: name
506
+ ),
507
+ hwClockUTC: true,
508
+ timeZone: options[:guest_customization][:timezone]
509
+ ),
510
+ globalIPSettings: RbVmomi::VIM::CustomizationGlobalIPSettings.new(
511
+ dnsServerList: options[:guest_customization][:dns_server_list],
512
+ dnsSuffixList: options[:guest_customization][:dns_suffix_list]
513
+ ),
514
+ nicSettingMap: [RbVmomi::VIM::CustomizationAdapterMapping.new(
515
+ adapter: customized_ip
516
+ )]
517
+ )
518
+ end
519
+
431
520
  def clone
432
521
  benchmark_start if benchmark?
433
522
 
434
523
  # set the datacenter name
435
524
  dc = find_datacenter
436
525
 
526
+ # get guest customization spec
527
+ guest_customization = customization_spec
528
+
437
529
  # reference template using full inventory path
438
530
  inventory_path = format("/%s/vm/%s", datacenter, options[:template])
439
531
  src_vm = root_folder.findByInventoryPath(inventory_path)
@@ -552,9 +644,15 @@ class Support
552
644
  benchmark_checkpoint("initialized") if benchmark?
553
645
  task = src_vm.InstantClone_Task(spec: clone_spec)
554
646
  else
555
- clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(location: relocate_spec,
556
- powerOn: options[:poweron] && options[:customize].nil?,
557
- template: false)
647
+ clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(
648
+ location: relocate_spec,
649
+ powerOn: options[:poweron] && options[:customize].nil?,
650
+ template: false
651
+ )
652
+
653
+ if guest_customization
654
+ clone_spec.customization = guest_customization
655
+ end
558
656
 
559
657
  benchmark_checkpoint("initialized") if benchmark?
560
658
  task = src_vm.CloneVM_Task(spec: clone_spec, folder: dest_folder, name: name)
@@ -1,5 +1,5 @@
1
1
  require "rbvmomi"
2
- require "net/http"
2
+ require "net/http" unless defined?(Net::HTTP)
3
3
 
4
4
  class Support
5
5
  # Encapsulate VMware Tools GOM interaction, inspired by github:dnuffer/raidopt
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.7.0
4
+ version: 2.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef Software
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-14 00:00:00.000000000 Z
11
+ date: 2020-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbvmomi
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '1.11'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '3.0'
22
+ version: '4.0'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '1.11'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '3.0'
32
+ version: '4.0'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: test-kitchen
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -64,34 +64,6 @@ dependencies:
64
64
  - - "~>"
65
65
  - !ruby/object:Gem::Version
66
66
  version: '0.4'
67
- - !ruby/object:Gem::Dependency
68
- name: bundler
69
- requirement: !ruby/object:Gem::Requirement
70
- requirements:
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- version: '0'
74
- type: :development
75
- prerelease: false
76
- version_requirements: !ruby/object:Gem::Requirement
77
- requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- version: '0'
81
- - !ruby/object:Gem::Dependency
82
- name: rake
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
67
  description: Test Kitchen driver for VMware vCenter using SDK
96
68
  email:
97
69
  - oss@chef.io
@@ -116,7 +88,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
88
  requirements:
117
89
  - - ">="
118
90
  - !ruby/object:Gem::Version
119
- version: '2.3'
91
+ version: '2.4'
120
92
  required_rubygems_version: !ruby/object:Gem::Requirement
121
93
  requirements:
122
94
  - - ">="