kitchen-hyperv 0.5.4 → 0.5.5

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: 4b55ec98fe0feae9159324c3c4d4aba29d3c765e02ce8119a8018d626c77f033
4
- data.tar.gz: 0a97571d04c65942c06a8f20d7efb20088be51b793481dd11ece2c929d56faf8
3
+ metadata.gz: 9258c479984814c2d9aaf91a3686a9c5d917f190cbc48627e65d69bd911a5b61
4
+ data.tar.gz: 43a7870274649b11ca8597213fe6ec7c93ed18b16f5c4b90d1bfd80642fb5344
5
5
  SHA512:
6
- metadata.gz: 4579cd9d4e532a42092d1cf50bf7d6d74c9977f848bcf4ee83871378d82f843d2b13127ad0a0814d5fabd036ac76117a7fc02d478223b80fe92f6aa005ab817f
7
- data.tar.gz: 53278bdf748446af609e584df729fde28fe60db46afe6a747b9186f10399d4d1a39d8fee3fdde23d234ee2d988a5eb3081315330c93a84bead84d7e64ebf84c3
6
+ metadata.gz: ca0012d2cc41220779907a19b573f64ff69893f1cff7d28a68b41c80ab48ee52eb3a7d6ddb30d2c408139f2a4ec327479766ce207d65b64928b4e6dd393a21b0
7
+ data.tar.gz: 2994a51e52ddde357eacca301732b7ec7af40accd963ae47c0484a3aaeb9c1245e15f352c8ab64ec6aa9661328a052c8213b4400a259fb00c0e24a30c5ae591f
data/Gemfile CHANGED
@@ -11,7 +11,7 @@ group :integration do
11
11
  end
12
12
 
13
13
  group :changelog do
14
- gem "github_changelog_generator", "1.15.0"
14
+ gem "github_changelog_generator", "1.15.2"
15
15
  end
16
16
 
17
17
  group :debug do
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "https://github.com/test-kitchen/kitchen-hyperv"
15
15
  spec.license = "Apache-2.0"
16
16
 
17
- spec.files = %w{LICENSE kitchen-hyperv.gemspec Gemfile Rakefile support/hyperv.ps1}
17
+ spec.files = %w{LICENSE kitchen-hyperv.gemspec Gemfile Rakefile support/hyperv.ps1} + Dir.glob("lib/**/*")
18
18
  spec.require_paths = ["lib"]
19
19
 
20
20
  spec.add_development_dependency "bundler"
@@ -0,0 +1,297 @@
1
+ #
2
+ # Author:: Steven Murawski <smurawski@chef.io>
3
+ # Copyright:: Copyright (c) 2020 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require "kitchen"
20
+ require "kitchen/driver"
21
+ require_relative "hyperv_version"
22
+ require_relative "powershell"
23
+ require "mixlib/shellout"
24
+ require "fileutils"
25
+ require "json"
26
+
27
+ module Kitchen
28
+
29
+ module Driver
30
+
31
+ # Driver for Hyper-V
32
+ class Hyperv < Kitchen::Driver::Base
33
+
34
+ kitchen_driver_api_version 2
35
+ plugin_version Kitchen::Driver::HYPERV_VERSION
36
+
37
+ default_config :parent_vhd_folder
38
+ default_config :parent_vhd_name
39
+ default_config :memory_startup_bytes, 536_870_912
40
+ default_config :dynamic_memory_min_bytes, 536_870_912
41
+ default_config :dynamic_memory_max_bytes, 2_147_483_648
42
+ default_config :dynamic_memory, false
43
+ default_config :processor_count, 2
44
+ default_config :ip_address
45
+ default_config :gateway
46
+ default_config :dns_servers
47
+ default_config :subnet, "255.255.255.0"
48
+ default_config :vm_switch
49
+ default_config :vm_vlan_id
50
+ default_config :iso_path
51
+ default_config :boot_iso_path
52
+ default_config :enable_guest_services
53
+ default_config :vm_note
54
+ default_config :resize_vhd
55
+ default_config :additional_disks
56
+ default_config :vm_generation, 1
57
+ default_config :disable_secureboot, false
58
+ default_config :static_mac_address
59
+ default_config :disk_type do |driver|
60
+ File.extname(driver[:parent_vhd_name])
61
+ end
62
+
63
+ include Kitchen::Driver::PowerShellScripts
64
+
65
+ def create(state)
66
+ @state = state
67
+ validate_vm_settings
68
+ create_new_differencing_disk
69
+ create_additional_disks
70
+ create_virtual_machine
71
+ set_virtual_machine_note
72
+ update_state
73
+ mount_virtual_machine_iso
74
+ instance.transport.connection(@state).wait_until_ready
75
+ copy_vm_files
76
+ info("Hyper-V instance #{instance.to_str} created.")
77
+ end
78
+
79
+ def destroy(state)
80
+ @state = state
81
+ if differencing_disk_exists && !vm_exists_silent
82
+ remove_differencing_disk
83
+ end
84
+ return unless vm_exists
85
+
86
+ instance.transport.connection(state).close
87
+ remove_virtual_machine
88
+ remove_differencing_disk
89
+ remove_additional_disks
90
+ info("The Hyper-V instance #{instance.to_str} has been removed.")
91
+ state.delete(:id)
92
+ end
93
+
94
+ private
95
+
96
+ def validate_vm_settings
97
+ raise "Missing parent_vhd_folder" unless vhd_folder?
98
+ raise "Missing parent_vhd_name" unless vhd?
99
+
100
+ if config[:dynamic_memory]
101
+ startup_bytes = config[:memory_startup_bytes]
102
+ min = config[:dynamic_memory_min_bytes]
103
+ max = config[:dynamic_memory_max_bytes]
104
+ memory_valid = startup_bytes.between?(min, max)
105
+ warning = "memory_startup_bytes (#{startup_bytes}) must" \
106
+ " fall within dynamic memory range (#{min}-#{max})"
107
+ raise warning unless memory_valid
108
+ end
109
+ config[:vm_switch] = vm_switch
110
+ if config[:vm_vlan_id]
111
+ vm_vlan_id = config[:vm_vlan_id]
112
+ vm_vlan_id_min = 1
113
+ vm_vlan_id_max = 4094
114
+ vm_vlan_id_valid = vm_vlan_id.between?(vm_vlan_id_min, vm_vlan_id_max)
115
+ vm_vlan_id_warning = "vm_vlan_id (#{vm_vlan_id}) must be a valid 802.1Q" \
116
+ " VLAN ID between (#{vm_vlan_id_min}-#{vm_vlan_id_max})"
117
+ raise vm_vlan_id_warning unless vm_vlan_id_valid
118
+ end
119
+ end
120
+
121
+ def create_new_differencing_disk
122
+ info("Creating differencing disk for #{instance.name}.")
123
+ run_ps new_differencing_disk_ps
124
+ info("Created differencing disk for #{instance.name}.")
125
+ set_new_vhd_size
126
+ end
127
+
128
+ def create_additional_disks
129
+ return if config[:additional_disks].nil?
130
+
131
+ @additional_disk_objects = []
132
+ config[:additional_disks].each do |additional_disk|
133
+ raise "Missing name for additional disk" unless additional_disk[:name]
134
+
135
+ disk_type = additional_disk[:type] || config[:disk_type]
136
+ disk_path = additional_disk_path(additional_disk[:name], disk_type)
137
+ raise "Additional disk file already exists: #{disk_path}" if File.exist?(disk_path)
138
+
139
+ disk_size = additional_disk[:size_gb] || 5
140
+ info("Creating additional disk #{additional_disk[:name]} for #{instance.name}.")
141
+ run_ps new_additional_disk_ps(disk_path, disk_size)
142
+ info("Created additional disk #{additional_disk[:name]} for #{instance.name}.")
143
+ @additional_disk_objects.push(disk_path)
144
+ end
145
+ end
146
+
147
+ def vm_switch
148
+ default_switch_object = run_ps vm_default_switch_ps
149
+ if default_switch_object.nil? ||
150
+ !default_switch_object.key?("Name") ||
151
+ default_switch_object["Name"].empty?
152
+ raise "Failed to find a default VM Switch."
153
+ end
154
+
155
+ default_switch_object["Name"]
156
+ end
157
+
158
+ def create_virtual_machine
159
+ return if vm_exists
160
+
161
+ info("Creating virtual machine for #{instance.name}.")
162
+ new_vm_object = run_ps new_vm_ps
163
+ @state[:id] = new_vm_object["Id"]
164
+ info("Created virtual machine for #{instance.name}.")
165
+ end
166
+
167
+ def update_state
168
+ vm_details
169
+ @state[:id] = @vm["Id"]
170
+ @state[:hostname] = @vm["IpAddress"]
171
+ @state[:vm_name] = @vm["Name"]
172
+ end
173
+
174
+ def vm_details
175
+ run_ps set_vm_ipaddress_ps if config[:ip_address]
176
+ @vm = run_ps vm_details_ps
177
+ end
178
+
179
+ def mount_virtual_machine_iso
180
+ return unless config[:iso_path]
181
+
182
+ info("Mounting #{config[:iso_path]}")
183
+ run_ps mount_vm_iso
184
+ info("Done mounting #{config[:iso_path]}")
185
+ end
186
+
187
+ def set_new_vhd_size
188
+ return unless config[:resize_vhd]
189
+
190
+ info("Resizing differencing disk for #{instance.name}.")
191
+ run_ps resize_vhd
192
+ info("Resized differencing disk for #{instance.name}.")
193
+ end
194
+
195
+ def set_virtual_machine_note
196
+ return unless config[:vm_note]
197
+
198
+ info("Adding note to VM: '#{config[:vm_note]}'")
199
+ run_ps set_vm_note
200
+ end
201
+
202
+ def copy_vm_files
203
+ return if config[:copy_vm_files].nil?
204
+
205
+ info("Copying files to virtual machine")
206
+ config[:copy_vm_files].each do |file_info|
207
+ run_ps copy_vm_file_ps(file_info[:source], file_info[:dest])
208
+ end
209
+ info("Copied files to virtual machine")
210
+ end
211
+
212
+ def vm_exists
213
+ info("Checking for existing virtual machine.")
214
+ return false unless @state.key?(:id) && !@state[:id].nil?
215
+
216
+ existing_vm = run_ps ensure_vm_running_ps
217
+ return false if existing_vm.nil? || existing_vm["Id"].nil?
218
+
219
+ info("Found an exising VM with an ID: #{existing_vm["Id"]}")
220
+ true
221
+ end
222
+
223
+ # Used in testing if a stale diff disk exists. Silent so the output doesn't
224
+ # appear twice on the kitchen destroy command for the second check for vm_exists
225
+ def vm_exists_silent
226
+ return false unless @state.key?(:id) && !@state[:id].nil?
227
+
228
+ existing_vm = run_ps ensure_vm_running_ps
229
+ return false if existing_vm.nil? || existing_vm["Id"].nil?
230
+
231
+ true
232
+ end
233
+
234
+ def differencing_disk_exists
235
+ return unless File.exist? differencing_disk_path
236
+
237
+ true
238
+ end
239
+
240
+ def remove_virtual_machine
241
+ info("Deleting virtual machine for #{instance.name}")
242
+ run_ps delete_vm_ps
243
+ info("Deleted virtual machine for #{instance.name}")
244
+ end
245
+
246
+ def remove_differencing_disk
247
+ info("Removing the differencing disk for #{instance.name}.")
248
+ FileUtils.rm(differencing_disk_path)
249
+ info("Removed the differencing disk for #{instance.name}.")
250
+ end
251
+
252
+ def remove_additional_disks
253
+ return if config[:additional_disks].nil?
254
+
255
+ config[:additional_disks].each do |additional_disk|
256
+ raise "Missing name for additional disk" unless additional_disk[:name]
257
+
258
+ disk_type = additional_disk[:type] || config[:disk_type]
259
+ disk_path = additional_disk_path(additional_disk[:name], disk_type)
260
+ if File.exist?(disk_path)
261
+ info("Removing additional disk #{additional_disk[:name]} for #{instance.name}.")
262
+ FileUtils.rm(disk_path)
263
+ info("Removed additional disk #{additional_disk[:name]} for #{instance.name}.")
264
+ end
265
+ end
266
+ end
267
+
268
+ def kitchen_vm_path
269
+ @kitchen_vm_path ||= File.join(config[:kitchen_root], ".kitchen/#{instance.name}")
270
+ end
271
+
272
+ def boot_iso_path
273
+ @boot_iso_path ||= config[:boot_iso_path]
274
+ end
275
+
276
+ def differencing_disk_path
277
+ @differencing_disk_path ||= File.join(kitchen_vm_path, "diff" + "#{config[:disk_type]}")
278
+ end
279
+
280
+ def additional_disk_path(disk_name, disk_type)
281
+ File.join(kitchen_vm_path, disk_name + disk_type)
282
+ end
283
+
284
+ def parent_vhd_path
285
+ @parent_vhd_path ||= File.join(config[:parent_vhd_folder], config[:parent_vhd_name])
286
+ end
287
+
288
+ def vhd_folder?
289
+ config[:parent_vhd_folder] && Dir.exist?(config[:parent_vhd_folder])
290
+ end
291
+
292
+ def vhd?
293
+ config[:parent_vhd_name] && File.exist?(parent_vhd_path)
294
+ end
295
+ end
296
+ end
297
+ end
@@ -0,0 +1,22 @@
1
+ #
2
+ # Author:: Steven Murawski <smurawski@chef.io>
3
+ # Copyright:: Copyright (c) 2015-2020 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ module Kitchen
19
+ module Driver
20
+ HYPERV_VERSION = "0.5.5".freeze
21
+ end
22
+ end
@@ -0,0 +1,243 @@
1
+ #
2
+ # Author:: Steven Murawski <smurawski@chef.io>
3
+ # Copyright:: Copyright (c) 2020 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require "mixlib/shellout"
19
+ require "fileutils"
20
+ require "json"
21
+
22
+ module Kitchen
23
+ module Driver
24
+ module PowerShellScripts
25
+ def encode_command(script)
26
+ encoded_script = script.encode("UTF-16LE", "UTF-8")
27
+ Base64.strict_encode64(encoded_script)
28
+ end
29
+
30
+ def is_64bit?
31
+ os_arch = ENV["PROCESSOR_ARCHITEW6432"] || ENV["PROCESSOR_ARCHITECTURE"]
32
+ ruby_arch = ["foo"].pack("p").size == 4 ? 32 : 64
33
+ os_arch == "AMD64" && ruby_arch == 64
34
+ end
35
+
36
+ def is_32bit?
37
+ os_arch = ENV["PROCESSOR_ARCHITEW6432"] || ENV["PROCESSOR_ARCHITECTURE"]
38
+ ruby_arch = ["foo"].pack("p").size == 4 ? 32 : 64
39
+ os_arch != "AMD64" && ruby_arch == 32
40
+ end
41
+
42
+ def powershell_64_bit
43
+ if is_64bit? || is_32bit?
44
+ 'c:\windows\system32\windowspowershell\v1.0\powershell.exe'
45
+ else
46
+ 'c:\windows\sysnative\windowspowershell\v1.0\powershell.exe'
47
+ end
48
+ end
49
+
50
+ def wrap_command(script)
51
+ base_script_path = File.join(File.dirname(__FILE__), "/../../../support/hyperv.ps1")
52
+ debug("Loading functions from #{base_script_path}")
53
+ new_script = [ ". #{base_script_path}", "#{script}" ].join(";\n")
54
+ debug("Wrapped script: #{new_script}")
55
+ "#{powershell_64_bit} -noprofile -executionpolicy bypass" \
56
+ " -encodedcommand #{encode_command new_script} -outputformat Text"
57
+ end
58
+
59
+ # Convenience method to run a powershell command locally.
60
+ #
61
+ # @param cmd [String] command to run locally
62
+ # @param options [Hash] options hash
63
+ # @see Kitchen::ShellOut.run_command
64
+ # @api private
65
+ def run_ps(cmd, options = {})
66
+ cmd = "echo #{cmd}" if config[:dry_run]
67
+ debug("Preparing to run: ")
68
+ debug(" #{cmd}")
69
+ wrapped_command = wrap_command cmd
70
+ execute_command wrapped_command, options
71
+ end
72
+
73
+ def execute_command(cmd, options = {})
74
+ debug("#Local Command BEGIN (#{cmd})")
75
+ sh = Mixlib::ShellOut.new(cmd, options)
76
+ sh.run_command
77
+ debug("Local Command END #{Util.duration(sh.execution_time)}")
78
+ raise "Failed: #{sh.stderr}" if sh.error?
79
+
80
+ stdout = sanitize_stdout(sh.stdout)
81
+ JSON.parse(stdout) if stdout.length > 2
82
+ end
83
+
84
+ def sanitize_stdout(stdout)
85
+ stdout.split("\n").select { |s| !s.start_with?("PS") }.join("\n")
86
+ end
87
+
88
+ def new_differencing_disk_ps
89
+ <<-DIFF
90
+
91
+ New-DifferencingDisk -Path "#{differencing_disk_path}" -ParentPath "#{parent_vhd_path}"
92
+ DIFF
93
+ end
94
+
95
+ def new_additional_disk_ps(disk_path, disk_size)
96
+ <<-ADDDISK
97
+
98
+ New-VHD -Path "#{disk_path}" -SizeBytes #{disk_size}GB | Out-Null
99
+ ADDDISK
100
+ end
101
+
102
+ def ensure_vm_running_ps
103
+ <<-RUNNING
104
+
105
+ Assert-VmRunning -ID "#{@state[:id]}" | ConvertTo-Json
106
+ RUNNING
107
+ end
108
+
109
+ def new_vm_ps
110
+ <<-NEWVM
111
+
112
+ $NewVMParams = @{
113
+ Generation = #{config[:vm_generation]}
114
+ DisableSecureBoot = "#{config[:disable_secureboot]}"
115
+ MemoryStartupBytes = #{config[:memory_startup_bytes]}
116
+ StaticMacAddress = "#{config[:static_mac_address]}"
117
+ Name = "#{instance.name}"
118
+ Path = "#{kitchen_vm_path}"
119
+ VHDPath = "#{differencing_disk_path}"
120
+ SwitchName = "#{config[:vm_switch]}"
121
+ VlanId = #{config[:vm_vlan_id] || "$null"}
122
+ ProcessorCount = #{config[:processor_count]}
123
+ UseDynamicMemory = "#{config[:dynamic_memory]}"
124
+ DynamicMemoryMinBytes = #{config[:dynamic_memory_min_bytes]}
125
+ DynamicMemoryMaxBytes = #{config[:dynamic_memory_max_bytes]}
126
+ boot_iso_path = "#{boot_iso_path}"
127
+ EnableGuestServices = "#{config[:enable_guest_services]}"
128
+ #{additional_disks}
129
+ }
130
+ New-KitchenVM @NewVMParams | ConvertTo-Json
131
+ NEWVM
132
+ end
133
+
134
+ def additional_disks
135
+ return if config[:additional_disks].nil?
136
+
137
+ <<-EOH
138
+ AdditionalDisks = @("#{@additional_disk_objects.join('","')}")
139
+ EOH
140
+ end
141
+
142
+ def vm_details_ps
143
+ <<-DETAILS
144
+
145
+ Get-VmDetail -id "#{@state[:id]}" | ConvertTo-Json
146
+ DETAILS
147
+ end
148
+
149
+ def delete_vm_ps
150
+ <<-REMOVE
151
+
152
+ $null = Get-VM -ID "#{@state[:id]}" |
153
+ Stop-VM -Force -TurnOff -PassThru |
154
+ Remove-VM -Force
155
+ REMOVE
156
+ end
157
+
158
+ def set_vm_ipaddress_ps
159
+ <<-VMIP
160
+
161
+ while ((Get-VM -id "#{@state[:id]}").NetworkAdapters[0].Status -ne 'Ok'){
162
+ start-sleep 10
163
+ }
164
+
165
+ (Get-VM -id "#{@state[:id]}").NetworkAdapters |
166
+ Set-VMNetworkConfiguration -ipaddress "#{config[:ip_address]}" `
167
+ -subnet "#{config[:subnet]}" `
168
+ -gateway "#{config[:gateway]}" `
169
+ -dnsservers #{ruby_array_to_ps_array(config[:dns_servers])} |
170
+ ConvertTo-Json
171
+ VMIP
172
+ end
173
+
174
+ def vm_default_switch_ps
175
+ <<-VMSWITCH
176
+ Get-DefaultVMSwitch "#{config[:vm_switch]}" | ConvertTo-Json
177
+ VMSWITCH
178
+ end
179
+
180
+ def mount_vm_iso
181
+ <<-MOUNTISO
182
+ mount-vmiso -id "#{@state[:id]}" -Path #{config[:iso_path]}
183
+ MOUNTISO
184
+ end
185
+
186
+ def resize_vhd
187
+ <<-VMNOTE
188
+ Resize-VHD -Path "#{parent_vhd_path}" -SizeBytes #{config[:resize_vhd]}
189
+ VMNOTE
190
+ end
191
+
192
+ def set_vm_note
193
+ <<-VMNOTE
194
+ Set-VM -Name (Get-VM | Where-Object{ $_.ID -eq "#{@state[:id]}"}).Name -Note "#{config[:vm_note]}"
195
+ VMNOTE
196
+ end
197
+
198
+ def copy_vm_file_ps(source, dest)
199
+ <<-FILECOPY
200
+ Function CopyFile ($VM, [string]$SourcePath, [string]$DestPath) {
201
+ $p = @{ CreateFullPath = $true ; FileSource = 'Host'; Force = $true }
202
+ $VM |
203
+ Copy-VMFile -SourcePath $SourcePath -DestinationPath $DestPath @p
204
+ }
205
+
206
+ $sourceLocation = '#{source}'
207
+ $destinationLocation = '#{dest}'
208
+ $vmId = '#{@state[:id]}'
209
+ If (Test-Path $sourceLocation) {
210
+ $vm = Get-VM -ID $vmId
211
+ $service = 'Guest Service Interface'
212
+
213
+ If ((Get-VMIntegrationService -Name $service -VM $vm).Enabled -ne $true) {
214
+ Enable-VMIntegrationService -Name $service -VM $vm
215
+ Start-Sleep -Seconds 3
216
+ }
217
+
218
+ If ((Get-Item $sourceLocation) -is [System.IO.DirectoryInfo]) {
219
+ ForEach ($item in (Get-ChildItem -Path $sourceLocation -File)) {
220
+ $destFullPath = (Join-Path $destinationLocation $item.Name)
221
+ CopyFile $vm $item.FullName $destFullPath
222
+ }
223
+ }
224
+ Else {
225
+ CopyFile $vm $sourceLocation $destinationLocation
226
+ }
227
+ }
228
+ else {
229
+ Write-Error "Source file path does not exist: $sourceLocation"
230
+ }
231
+ FILECOPY
232
+ end
233
+
234
+ private
235
+
236
+ def ruby_array_to_ps_array(list)
237
+ return "@()" if list.nil? || list.empty?
238
+
239
+ list.to_s.tr("[]", "()").prepend("@")
240
+ end
241
+ end
242
+ end
243
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-hyperv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Murawski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-06 00:00:00.000000000 Z
11
+ date: 2020-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -117,6 +117,9 @@ files:
117
117
  - LICENSE
118
118
  - Rakefile
119
119
  - kitchen-hyperv.gemspec
120
+ - lib/kitchen/driver/hyperv.rb
121
+ - lib/kitchen/driver/hyperv_version.rb
122
+ - lib/kitchen/driver/powershell.rb
120
123
  - support/hyperv.ps1
121
124
  homepage: https://github.com/test-kitchen/kitchen-hyperv
122
125
  licenses: