kitchen-vcenter 2.6.2 → 2.7.8

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: 2d7f326a420401fc6ad764643170303d54c7db1c10fda9ba496fe1ad02cb832c
4
- data.tar.gz: 20cd7d03f6b5e9c10925005272d6f8917c25b12a84843483c2e33141e556a90f
3
+ metadata.gz: 9e4016eb3acf59b1720fa8db8a286182337c9bd38528a94b52796f29f7779497
4
+ data.tar.gz: 7b73e59e8e6437d819fcede40a6bf34fcb691e44211a8b7ecc0d5b66db02dae9
5
5
  SHA512:
6
- metadata.gz: ae4a1d9d879b5cf7e5a1e29a7c6df553058d59050e62899e701b3f023606228e8d0b3ac920b65e618ead7aaa4c7dcd4b6b8a7228b7fcc21aab7aeb840c211c4f
7
- data.tar.gz: 4e723721ea9cf9f2484e92df940772a399b9b2146b333440b4e1cbc7bff3fda7f5054142eea0aac5df606c046a84d1765c9fc97b74711ed1d71fbb752dab673e
6
+ metadata.gz: 9fecbd078bec90c376c8c502926790e4d9bf308ddd8fc30b3911e2e06998fd63d6f21c7f2ce38c31e7227dd5b723506ab5da21d693797b6195653d1867d1af49
7
+ data.tar.gz: 5304bc077b139e731ab5530c9f76ea26292b0349b89109f924f873d3098f7ca6ac1d0d0b032a348fc26f00ce010402befac0db5a958f0ddab41ae0eac8dae04a
@@ -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.2"
23
+ VERSION = "2.7.8"
24
24
  end
@@ -18,6 +18,7 @@
18
18
  require "kitchen"
19
19
  require "vsphere-automation-cis"
20
20
  require "vsphere-automation-vcenter"
21
+ require_relative "../../kitchen-vcenter/version"
21
22
  require_relative "../../support/clone_vm"
22
23
  require "securerandom"
23
24
  require "uri"
@@ -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
 
@@ -403,14 +420,14 @@ module Kitchen
403
420
  # impact on small environments, but on large deployments with lots of clusters and pools,
404
421
  # provisioned machines are likely to "jump around" available hosts.
405
422
  #
406
- # This behaviour is carried on from versions 1.2.1 and lower, but likely to be removed in
423
+ # This behavior is carried on from versions 1.2.1 and lower, but likely to be removed in
407
424
  # a new major version due to these insufficiencies and the confusing code for it
408
425
 
409
- # Remove default pool for first pass (<= 1.2.1 behaviour to pick first user-defined pool found)
426
+ # Remove default pool for first pass (<= 1.2.1 behavior to pick first user-defined pool found)
410
427
  resource_pools = rp_api.list.value.delete_if { |pool| pool.name == "Resources" }
411
428
  debug("Search of all resource pools found: " + resource_pools.map(&:name).to_s)
412
429
 
413
- # Revert to default pool, if no user-defined pool found (> 1.2.1 behaviour)
430
+ # Revert to default pool, if no user-defined pool found (> 1.2.1 behavior)
414
431
  # (This one might not be found under some circumstances by the statement above)
415
432
  return get_resource_pool("Resources") if resource_pools.empty?
416
433
  else
@@ -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,7 +539,7 @@ 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
@@ -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.2
4
+ version: 2.7.8
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-02-12 00:00:00.000000000 Z
11
+ date: 2020-07-31 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
  - - ">="