kitchen-hyperv 0.5.4 → 0.5.5

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: 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: