vagrant-windows 1.6.0 → 1.7.0.pre.1
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 +4 -4
- data/.travis.yml +0 -1
- data/CHANGELOG.md +7 -1
- data/Gemfile +5 -1
- data/README.md +3 -1
- data/lib/vagrant-windows/communication/command_filters/cat.rb +27 -0
- data/lib/vagrant-windows/communication/command_filters/chmod.rb +21 -0
- data/lib/vagrant-windows/communication/command_filters/chown.rb +21 -0
- data/lib/vagrant-windows/communication/command_filters/rm.rb +28 -0
- data/lib/vagrant-windows/communication/command_filters/test.rb +37 -0
- data/lib/vagrant-windows/communication/command_filters/uname.rb +36 -0
- data/lib/vagrant-windows/communication/command_filters/which.rb +26 -0
- data/lib/vagrant-windows/communication/linux_command_filter.rb +44 -0
- data/lib/vagrant-windows/communication/winrmcommunicator.rb +19 -12
- data/lib/vagrant-windows/communication/winrmfilemanager.rb +166 -0
- data/lib/vagrant-windows/communication/winrmshell.rb +4 -23
- data/lib/vagrant-windows/errors.rb +5 -1
- data/lib/vagrant-windows/monkey_patches/plugins/provisioners/chef/provisioner/chef_client.rb +2 -5
- data/lib/vagrant-windows/monkey_patches/plugins/provisioners/chef/provisioner/chef_solo.rb +2 -5
- data/lib/vagrant-windows/monkey_patches/plugins/provisioners/shell/provisioner.rb +13 -6
- data/lib/vagrant-windows/provisioners/chef_command_builder.rb +7 -53
- data/lib/vagrant-windows/scripts/elevated_shell.ps1.erb +95 -0
- data/lib/vagrant-windows/version.rb +1 -1
- data/locales/en.yml +7 -0
- data/spec/vagrant-windows/chef_command_builder_spec.rb +7 -53
- data/spec/vagrant-windows/guestnetwork_spec.rb +3 -3
- data/spec/vagrant-windows/linux_command_filter_spec.rb +73 -0
- data/spec/vagrant-windows/winrmcommunicator_spec.rb +55 -6
- data/spec/vagrant-windows/winrmshell_spec.rb +3 -3
- metadata +16 -8
- data/lib/vagrant-windows/scripts/cheftask.ps1.erb +0 -48
- data/lib/vagrant-windows/scripts/cheftask.xml.erb +0 -45
- data/lib/vagrant-windows/scripts/cheftaskrun.ps1.erb +0 -18
- data/lib/vagrant-windows/scripts/command_alias.ps1 +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e0d8f67d7fd5775bc1dfffb01aee0f766c5c512
|
4
|
+
data.tar.gz: fd24bde9a3b09754acb450f2995a61c0292a7294
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 081a4d22f0f528b6672009678de4c7558c24059036a62c5d8e595073de8cc4566c38f72c78bacd3a67d5a9da6b2a2b8d96a356dc26b391adf8bb59c11a75ec57
|
7
|
+
data.tar.gz: c11a66f853413fc9ca9970ce767c1a71ddd3c0193766a9cf7980b9aeb5af67dfff414720e1ea3e4116b0072925353bd780d300bbe94ab75f59372b23319f1d8e
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -76,4 +76,10 @@
|
|
76
76
|
|
77
77
|
1.6.0
|
78
78
|
- Added chef-client provisioner support and extracted shared code from chef-solo provisioner
|
79
|
-
- WinRM communicator download support
|
79
|
+
- WinRM communicator download support
|
80
|
+
|
81
|
+
1.7.0
|
82
|
+
- Added recursive directory upload on communicator, similar to core Vagrant SCP functionality.
|
83
|
+
- Redesigned elevated command execution in Chef to make it reusable
|
84
|
+
- Shell provisioner now runs elevated by default unless privileged is false
|
85
|
+
- Removed *nix command alias PS script and created extensible linux command filter system
|
data/Gemfile
CHANGED
@@ -7,6 +7,10 @@ group :development do
|
|
7
7
|
# We depend on Vagrant for development, but we don't add it as a
|
8
8
|
# gem dependency because we expect to be installed within the
|
9
9
|
# Vagrant environment itself using `vagrant plugin`.
|
10
|
-
gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git", :tag => 'v1.
|
10
|
+
gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git", :tag => 'v1.5.2'
|
11
11
|
gem "mocha", :require => false
|
12
12
|
end
|
13
|
+
|
14
|
+
group :plugins do
|
15
|
+
gem "vagrant-windows", path: '.'
|
16
|
+
end
|
data/README.md
CHANGED
@@ -13,7 +13,9 @@ This [Vagrant](http://www.vagrantup.com/) plugin allows you to standup Windows g
|
|
13
13
|
|
14
14
|
## Installation
|
15
15
|
|
16
|
-
|
16
|
+
Vagrant 1.6 will natively support Windows guests, this plugin should not be used with Vagrant 1.6 or later.
|
17
|
+
|
18
|
+
- For Vagrant 1.1 -> 1.5 execute `vagrant plugin install vagrant-windows`.
|
17
19
|
- For Vagrant 1.0 execute `vagrant plugin install vagrant-windows --plugin-version 0.1.2`.
|
18
20
|
|
19
21
|
## Creating a Base Box
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module VagrantWindows
|
2
|
+
module Communication
|
3
|
+
module CommandFilters
|
4
|
+
|
5
|
+
# Handles the special case of determining the guest OS using cat
|
6
|
+
class Cat
|
7
|
+
|
8
|
+
def filter(command)
|
9
|
+
# cat /etc/release | grep -i OmniOS
|
10
|
+
# cat /etc/redhat-release
|
11
|
+
# cat /etc/issue | grep 'Core Linux'
|
12
|
+
# cat /etc/release | grep -i SmartOS
|
13
|
+
''
|
14
|
+
end
|
15
|
+
|
16
|
+
def accept?(command)
|
17
|
+
# cat works in PowerShell, however we don't want to run Guest
|
18
|
+
# OS detection as this will fail on Windows because the lack of the
|
19
|
+
# grep command
|
20
|
+
command.start_with?('cat /etc/')
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module VagrantWindows
|
2
|
+
module Communication
|
3
|
+
module CommandFilters
|
4
|
+
|
5
|
+
# Converts a *nix 'chmod' command to a PowerShell equivalent
|
6
|
+
class Chmod
|
7
|
+
|
8
|
+
def filter(command)
|
9
|
+
# Not support on Windows, the communicator will skip this command
|
10
|
+
''
|
11
|
+
end
|
12
|
+
|
13
|
+
def accept?(command)
|
14
|
+
command.start_with?('chmod ')
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module VagrantWindows
|
2
|
+
module Communication
|
3
|
+
module CommandFilters
|
4
|
+
|
5
|
+
# Converts a *nix 'chown' command to a PowerShell equivalent
|
6
|
+
class Chown
|
7
|
+
|
8
|
+
def filter(command)
|
9
|
+
# Not support on Windows, the communicator will skip this command
|
10
|
+
''
|
11
|
+
end
|
12
|
+
|
13
|
+
def accept?(command)
|
14
|
+
command.start_with?('chown ')
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module VagrantWindows
|
2
|
+
module Communication
|
3
|
+
module CommandFilters
|
4
|
+
|
5
|
+
# Converts a *nix 'rm' command to a PowerShell equivalent
|
6
|
+
class Rm
|
7
|
+
|
8
|
+
def filter(command)
|
9
|
+
# rm -Rf /some/dir
|
10
|
+
# rm /some/dir
|
11
|
+
cmd_parts = command.strip.split(/\s+/)
|
12
|
+
dir = cmd_parts[1]
|
13
|
+
if dir == '-Rf'
|
14
|
+
dir = cmd_parts[2]
|
15
|
+
return "rm '#{dir}' -recurse -force"
|
16
|
+
end
|
17
|
+
return "rm '#{dir}' -force"
|
18
|
+
end
|
19
|
+
|
20
|
+
def accept?(command)
|
21
|
+
command.start_with?('rm ')
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module VagrantWindows
|
2
|
+
module Communication
|
3
|
+
module CommandFilters
|
4
|
+
|
5
|
+
# Converts a *nix 'test' command to a PowerShell equivalent
|
6
|
+
class Test
|
7
|
+
|
8
|
+
def filter(command)
|
9
|
+
# test -d /tmp/dir
|
10
|
+
# test -f /tmp/afile
|
11
|
+
# test -L /somelink
|
12
|
+
# test -x /tmp/some.exe
|
13
|
+
|
14
|
+
cmd_parts = command.strip.split(/\s+/)
|
15
|
+
if cmd_parts[1] == '-d'
|
16
|
+
# ensure it exists and is a directory
|
17
|
+
return "if ((Test-Path '#{cmd_parts[2]}') -and (get-item '#{cmd_parts[2]}').PSIsContainer) { exit 0 } exit 1"
|
18
|
+
elsif cmd_parts[1] == '-f' || cmd_parts[1] == '-x'
|
19
|
+
# ensure it exists and is a file
|
20
|
+
return "if ((Test-Path '#{cmd_parts[2]}') -and (!(get-item '#{cmd_parts[2]}').PSIsContainer)) { exit 0 } exit 1"
|
21
|
+
end
|
22
|
+
|
23
|
+
# otherwise, just check for existence
|
24
|
+
return "if (Test-Path '#{cmd_parts[2]}') { exit 0 } exit 1"
|
25
|
+
end
|
26
|
+
|
27
|
+
# if (Test-Path 'c:\windows' && (get-item 'c:\windows').PSIsContainer) { Write-Host 0 } Write-Host 1
|
28
|
+
|
29
|
+
def accept?(command)
|
30
|
+
command.start_with?('test ')
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# cat /etc/release | grep -i OmniOS
|
2
|
+
# cat /etc/redhat-release
|
3
|
+
# cat /etc/issue | grep 'Core Linux'
|
4
|
+
# cat /etc/release | grep -i SmartOS
|
5
|
+
|
6
|
+
module VagrantWindows
|
7
|
+
module Communication
|
8
|
+
module CommandFilters
|
9
|
+
|
10
|
+
# Converts a *nix 'uname' command to a PowerShell equivalent
|
11
|
+
class Uname
|
12
|
+
|
13
|
+
def filter(command)
|
14
|
+
# uname -s | grep 'Darwin'
|
15
|
+
# uname -s | grep VMkernel
|
16
|
+
# uname -s | grep 'FreeBSD'
|
17
|
+
# uname -s | grep 'Linux'
|
18
|
+
# uname -s | grep NetBSD
|
19
|
+
# uname -s | grep 'OpenBSD'
|
20
|
+
# uname -sr | grep SunOS | grep -v 5.11
|
21
|
+
# uname -sr | grep 'SunOS 5.11'
|
22
|
+
|
23
|
+
# uname is used to detect the guest type in Vagrant, so don't bother running
|
24
|
+
# to speed up OS detection
|
25
|
+
''
|
26
|
+
end
|
27
|
+
|
28
|
+
def accept?(command)
|
29
|
+
command.start_with?('uname ')
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module VagrantWindows
|
2
|
+
module Communication
|
3
|
+
module CommandFilters
|
4
|
+
|
5
|
+
# Converts a *nix 'which' command to a PowerShell equivalent
|
6
|
+
class Which
|
7
|
+
|
8
|
+
def filter(command)
|
9
|
+
executable = command.strip.split(/\s+/)[1]
|
10
|
+
return <<-EOH
|
11
|
+
$command = [Array](Get-Command #{executable} -errorAction SilentlyContinue)
|
12
|
+
if ($null -eq $command) { exit 1 }
|
13
|
+
write-host $command[0].Definition
|
14
|
+
exit 0
|
15
|
+
EOH
|
16
|
+
end
|
17
|
+
|
18
|
+
def accept?(command)
|
19
|
+
command.start_with?('which ')
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module VagrantWindows
|
2
|
+
module Communication
|
3
|
+
|
4
|
+
# Handles loading all available Linix command filters and applying them
|
5
|
+
# to specified command
|
6
|
+
class LinuxCommandFilter
|
7
|
+
|
8
|
+
# Filter the given Vagrant command to ensure compatibility with Windows
|
9
|
+
#
|
10
|
+
# @param [String] The Vagrant shell command
|
11
|
+
# @returns [String] Windows runnable command or empty string
|
12
|
+
def filter(command)
|
13
|
+
win_friendly_cmd = command
|
14
|
+
command_filters.each do |cmd_filter|
|
15
|
+
win_friendly_cmd = cmd_filter.filter(win_friendly_cmd) if cmd_filter.accept?(win_friendly_cmd)
|
16
|
+
end
|
17
|
+
win_friendly_cmd
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
# All the available Linux command filters
|
22
|
+
#
|
23
|
+
# @returns [Array] All Linux command filter instances
|
24
|
+
def command_filters
|
25
|
+
@command_filters ||= create_command_filters()
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates all the available Linux command filters
|
29
|
+
#
|
30
|
+
# @returns [Array] All Linux command filter instances
|
31
|
+
def create_command_filters
|
32
|
+
filters = []
|
33
|
+
Dir[File.join(File.dirname(__FILE__), '/command_filters/*.rb')].each do |file|
|
34
|
+
require file
|
35
|
+
clazz = File.basename(file, '.*').capitalize
|
36
|
+
filters << Module.const_get("VagrantWindows::Communication::CommandFilters::#{clazz}").new
|
37
|
+
end
|
38
|
+
filters
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -2,7 +2,9 @@ require 'timeout'
|
|
2
2
|
require 'log4r'
|
3
3
|
require_relative 'winrmshell_factory'
|
4
4
|
require_relative 'winrmshell'
|
5
|
+
require_relative 'winrmfilemanager'
|
5
6
|
require_relative 'winrmfinder'
|
7
|
+
require_relative 'linux_command_filter'
|
6
8
|
require_relative '../errors'
|
7
9
|
require_relative '../windows_machine'
|
8
10
|
|
@@ -18,7 +20,7 @@ module VagrantWindows
|
|
18
20
|
def initialize(machine)
|
19
21
|
@windows_machine = VagrantWindows::WindowsMachine.new(machine)
|
20
22
|
@winrm_shell_factory = WinRMShellFactory.new(@windows_machine, WinRMFinder.new(@windows_machine))
|
21
|
-
|
23
|
+
@linux_cmd_filter = LinuxCommandFilter.new()
|
22
24
|
@logger = Log4r::Logger.new("vagrant_windows::communication::winrmcommunicator")
|
23
25
|
@logger.debug("initializing WinRMCommunicator")
|
24
26
|
end
|
@@ -45,14 +47,20 @@ module VagrantWindows
|
|
45
47
|
end
|
46
48
|
|
47
49
|
def execute(command, opts={}, &block)
|
50
|
+
# If this is a *nix command with no Windows equivilant, don't run it
|
51
|
+
win_friendly_cmd = @linux_cmd_filter.filter(command)
|
52
|
+
if (win_friendly_cmd.empty?)
|
53
|
+
return { :exitcode => 0, :stderr => '', :stdout => '' }
|
54
|
+
end
|
55
|
+
|
48
56
|
opts = {
|
49
57
|
:error_check => true,
|
50
58
|
:error_class => VagrantWindows::Errors::WinRMExecutionError,
|
51
59
|
:error_key => :winrm_execution_error,
|
52
|
-
:command =>
|
60
|
+
:command => win_friendly_cmd,
|
53
61
|
:shell => :powershell
|
54
62
|
}.merge(opts || {})
|
55
|
-
exit_status = do_execute(
|
63
|
+
exit_status = do_execute(win_friendly_cmd, opts[:shell], &block)
|
56
64
|
if opts[:error_check] && exit_status != 0
|
57
65
|
raise_execution_error(opts, exit_status)
|
58
66
|
end
|
@@ -61,22 +69,21 @@ module VagrantWindows
|
|
61
69
|
alias_method :sudo, :execute
|
62
70
|
|
63
71
|
def test(command, opts=nil)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
72
|
+
# If this is a *nix command with no Windows equivilant, don't run it
|
73
|
+
win_friendly_cmd = @linux_cmd_filter.filter(command)
|
74
|
+
if (win_friendly_cmd.empty?)
|
75
|
+
return false
|
76
|
+
end
|
68
77
|
|
69
78
|
opts = { :error_check => false }.merge(opts || {})
|
70
|
-
execute(
|
79
|
+
execute(win_friendly_cmd, opts) == 0
|
71
80
|
end
|
72
81
|
|
73
82
|
def upload(from, to)
|
74
|
-
@logger.debug("Uploading: #{from} to #{to}")
|
75
83
|
winrmshell.upload(from, to)
|
76
84
|
end
|
77
85
|
|
78
86
|
def download(from, to)
|
79
|
-
@logger.debug("Downloading: #{from} to #{to}")
|
80
87
|
winrmshell.download(from, to)
|
81
88
|
end
|
82
89
|
|
@@ -87,7 +94,7 @@ module VagrantWindows
|
|
87
94
|
def winrmshell
|
88
95
|
@winrmshell ||= @winrm_shell_factory.create_winrm_shell()
|
89
96
|
end
|
90
|
-
|
97
|
+
|
91
98
|
|
92
99
|
protected
|
93
100
|
|
@@ -95,7 +102,7 @@ module VagrantWindows
|
|
95
102
|
if shell.eql? :cmd
|
96
103
|
winrmshell.cmd(command, &block)[:exitcode]
|
97
104
|
else
|
98
|
-
command
|
105
|
+
command << "\r\nexit $LASTEXITCODE"
|
99
106
|
winrmshell.powershell(command, &block)[:exitcode]
|
100
107
|
end
|
101
108
|
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'winrm'
|
3
|
+
require_relative 'winrmshell'
|
4
|
+
require_relative '../errors'
|
5
|
+
|
6
|
+
module VagrantWindows
|
7
|
+
module Communication
|
8
|
+
|
9
|
+
# Manages the file system on the remote guest allowing for file tranfer
|
10
|
+
# between the guest and host.
|
11
|
+
class WinRMFileManager
|
12
|
+
|
13
|
+
def initialize(winrm_shell)
|
14
|
+
@logger = Log4r::Logger.new("vagrant_windows::communication::winrmfilemanager")
|
15
|
+
@winrm_shell = winrm_shell
|
16
|
+
end
|
17
|
+
|
18
|
+
# Uploads the given file or directory from the host to the guest (recursively).
|
19
|
+
#
|
20
|
+
# @param [String] The source file or directory path on the host
|
21
|
+
# @param [String] The destination file or directory path on the host
|
22
|
+
def upload(host_src_file_path, guest_dest_file_path)
|
23
|
+
@logger.debug("Upload: #{host_src_file_path} -> #{guest_dest_file_path}")
|
24
|
+
if File.directory?(host_src_file_path)
|
25
|
+
upload_directory(host_src_file_path, guest_dest_file_path)
|
26
|
+
else
|
27
|
+
upload_file(host_src_file_path, guest_dest_file_path)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Downloads the given file from the guest to the host.
|
32
|
+
# NOTE: This currently only supports single file download
|
33
|
+
#
|
34
|
+
# @param [String] The source file path on the guest
|
35
|
+
# @param [String] The destination file path on the host
|
36
|
+
def download(guest_src_file_path, host_dest_file_path)
|
37
|
+
@logger.debug("#{guest_src_file_path} -> #{host_dest_file_path}")
|
38
|
+
output = @winrm_shell.powershell("[System.convert]::ToBase64String([System.IO.File]::ReadAllBytes(\"#{guest_src_file_path}\"))")
|
39
|
+
contents = output[:data].map!{|line| line[:stdout]}.join.gsub("\\n\\r", '')
|
40
|
+
out = Base64.decode64(contents)
|
41
|
+
IO.binwrite(host_dest_file_path, out)
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# Recursively uploads the given directory from the host to the guest
|
48
|
+
#
|
49
|
+
# @param [String] The source file or directory path on the host
|
50
|
+
# @param [String] The destination file or directory path on the host
|
51
|
+
def upload_directory(host_src_file_path, guest_dest_file_path)
|
52
|
+
glob_patt = File.join(host_src_file_path, '**/*')
|
53
|
+
Dir.glob(glob_patt).select { |f| !File.directory?(f) }.each do |host_file_path|
|
54
|
+
guest_file_path = guest_file_path(host_src_file_path, guest_dest_file_path, host_file_path)
|
55
|
+
upload_file(host_file_path, guest_file_path)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Uploads the given file, but only if the target file doesn't exist
|
60
|
+
# or its MD5 checksum doens't match the host's source checksum.
|
61
|
+
#
|
62
|
+
# @param [String] The source file path on the host
|
63
|
+
# @param [String] The destination file path on the guest
|
64
|
+
def upload_file(host_src_file_path, guest_dest_file_path)
|
65
|
+
if should_upload_file?(host_src_file_path, guest_dest_file_path)
|
66
|
+
tmp_file_path = upload_to_temp_file(host_src_file_path)
|
67
|
+
decode_temp_file(tmp_file_path, guest_dest_file_path)
|
68
|
+
else
|
69
|
+
@logger.debug("Up to date: #{guest_dest_file_path}")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Uploads the given file to a new temp file on the guest
|
74
|
+
#
|
75
|
+
# @param [String] The source file path on the host
|
76
|
+
# @return [String] The temp file path on the guest
|
77
|
+
def upload_to_temp_file(host_src_file_path)
|
78
|
+
tmp_file_path = File.join(guest_temp_dir, "winrm-upload-#{rand()}")
|
79
|
+
@logger.debug("Uploading '#{host_src_file_path}' to temp file '#{tmp_file_path}'")
|
80
|
+
base64_host_file = Base64.encode64(IO.binread(host_src_file_path)).gsub("\n",'')
|
81
|
+
base64_host_file.chars.to_a.each_slice(8000-tmp_file_path.size) do |chunk|
|
82
|
+
out = @winrm_shell.cmd("echo #{chunk.join} >> \"#{tmp_file_path}\"")
|
83
|
+
raise_upload_error_if_failed(out, host_src_file_path, tmp_file_path)
|
84
|
+
end
|
85
|
+
tmp_file_path
|
86
|
+
end
|
87
|
+
|
88
|
+
# Moves and decodes the given file temp file on the guest to its
|
89
|
+
# permanent location
|
90
|
+
#
|
91
|
+
# @param [String] The source base64 encoded temp file path on the guest
|
92
|
+
# @param [String] The destination file path on the guest
|
93
|
+
def decode_temp_file(guest_tmp_file_path, guest_dest_file_path)
|
94
|
+
@logger.debug("Decoding temp file '#{guest_tmp_file_path}' to '#{guest_dest_file_path}'")
|
95
|
+
out = @winrm_shell.powershell <<-EOH
|
96
|
+
$tmp_file_path = [System.IO.Path]::GetFullPath('#{guest_tmp_file_path}')
|
97
|
+
$dest_file_path = [System.IO.Path]::GetFullPath('#{guest_dest_file_path}')
|
98
|
+
|
99
|
+
if (Test-Path $dest_file_path) {
|
100
|
+
rm $dest_file_path
|
101
|
+
}
|
102
|
+
else {
|
103
|
+
$dest_dir = ([System.IO.Path]::GetDirectoryName($dest_file_path))
|
104
|
+
New-Item -ItemType directory -Force -Path $dest_dir
|
105
|
+
}
|
106
|
+
|
107
|
+
$base64_string = Get-Content $tmp_file_path
|
108
|
+
$bytes = [System.Convert]::FromBase64String($base64_string)
|
109
|
+
[System.IO.File]::WriteAllBytes($dest_file_path, $bytes)
|
110
|
+
EOH
|
111
|
+
raise_upload_error_if_failed(out, guest_tmp_file_path, guest_dest_file_path)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Checks to see if the target file on the guest is missing or out of date.
|
115
|
+
#
|
116
|
+
# @param [String] The source file path on the host
|
117
|
+
# @param [String] The destination file path on the guest
|
118
|
+
# @return [Boolean] True if the file is missing or out of date
|
119
|
+
def should_upload_file?(host_src_file_path, guest_dest_file_path)
|
120
|
+
local_md5 = Digest::MD5.file(host_src_file_path).hexdigest
|
121
|
+
cmd = <<-EOH
|
122
|
+
$dest_file_path = [System.IO.Path]::GetFullPath('#{guest_dest_file_path}')
|
123
|
+
|
124
|
+
if (Test-Path $dest_file_path) {
|
125
|
+
$crypto_provider = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
|
126
|
+
try {
|
127
|
+
$file = [System.IO.File]::Open($dest_file_path, [System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
|
128
|
+
$guest_md5 = ([System.BitConverter]::ToString($crypto_provider.ComputeHash($file))).Replace("-","").ToLower()
|
129
|
+
}
|
130
|
+
finally {
|
131
|
+
$file.Dispose()
|
132
|
+
}
|
133
|
+
if ($guest_md5 -eq '#{local_md5}') {
|
134
|
+
exit 0
|
135
|
+
}
|
136
|
+
}
|
137
|
+
exit 1
|
138
|
+
EOH
|
139
|
+
@winrm_shell.powershell(cmd)[:exitcode] == 1
|
140
|
+
end
|
141
|
+
|
142
|
+
# Creates a guest file path equivalent from a host file path
|
143
|
+
#
|
144
|
+
# @param [String] The base host directory we're going to copy from
|
145
|
+
# @param [String] The base guest directory we're going to copy to
|
146
|
+
# @param [String] A full path to a file on the host underneath host_base_dir
|
147
|
+
# @return [String] The guest file path equivalent
|
148
|
+
def guest_file_path(host_base_dir, guest_base_dir, host_file_path)
|
149
|
+
rel_path = File.dirname(host_file_path[host_base_dir.length, host_file_path.length])
|
150
|
+
File.join(guest_base_dir, rel_path, File.basename(host_file_path))
|
151
|
+
end
|
152
|
+
|
153
|
+
def guest_temp_dir
|
154
|
+
@guest_temp ||= (@winrm_shell.cmd('echo %TEMP%'))[:data][0][:stdout].chomp
|
155
|
+
end
|
156
|
+
|
157
|
+
def raise_upload_error_if_failed(out, from, to)
|
158
|
+
raise Errors::WinRMFileTransferError,
|
159
|
+
:from => from,
|
160
|
+
:to => to,
|
161
|
+
:message => out.inspect if out[:exitcode] != 0
|
162
|
+
end
|
163
|
+
|
164
|
+
end #class
|
165
|
+
end
|
166
|
+
end
|
@@ -56,35 +56,16 @@ module VagrantWindows
|
|
56
56
|
def wql(query)
|
57
57
|
execute_wql(query)
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
def upload(from, to)
|
61
|
-
|
62
|
-
file_name = (cmd("echo %TEMP%\\winrm-upload-#{rand()}"))[:data][0][:stdout].chomp
|
63
|
-
powershell <<-EOH
|
64
|
-
if(Test-Path #{to}) {
|
65
|
-
rm #{to}
|
66
|
-
}
|
67
|
-
EOH
|
68
|
-
Base64.encode64(IO.binread(from)).gsub("\n",'').chars.to_a.each_slice(8000-file_name.size) do |chunk|
|
69
|
-
out = cmd("echo #{chunk.join} >> \"#{file_name}\"")
|
70
|
-
end
|
71
|
-
powershell <<-EOH
|
72
|
-
mkdir $([System.IO.Path]::GetDirectoryName(\"#{to}\"))
|
73
|
-
$base64_string = Get-Content \"#{file_name}\"
|
74
|
-
$bytes = [System.Convert]::FromBase64String($base64_string)
|
75
|
-
$new_file = [System.IO.Path]::GetFullPath(\"#{to}\")
|
76
|
-
[System.IO.File]::WriteAllBytes($new_file,$bytes)
|
77
|
-
EOH
|
61
|
+
WinRMFileManager.new(self).upload(from, to)
|
78
62
|
end
|
79
63
|
|
80
64
|
def download(from, to)
|
81
|
-
|
82
|
-
output = powershell("[System.convert]::ToBase64String([System.IO.File]::ReadAllBytes(\"#{from}\"))")
|
83
|
-
contents = output[:data].map!{|line| line[:stdout]}.join.gsub("\\n\\r", '')
|
84
|
-
out = Base64.decode64(contents)
|
85
|
-
IO.binwrite(to, out)
|
65
|
+
WinRMFileManager.new(self).download(from, to)
|
86
66
|
end
|
87
67
|
|
68
|
+
|
88
69
|
protected
|
89
70
|
|
90
71
|
def execute_shell(command, shell=:powershell, &block)
|
data/lib/vagrant-windows/monkey_patches/plugins/provisioners/chef/provisioner/chef_client.rb
CHANGED
@@ -34,11 +34,8 @@ module VagrantPlugins
|
|
34
34
|
end
|
35
35
|
|
36
36
|
#################### START - monkey patched code ####################
|
37
|
-
|
38
|
-
@windows_machine, @config, :client)
|
39
|
-
|
40
|
-
command_builder.prepare_for_chef_run()
|
41
|
-
command = command_builder.run_chef_command()
|
37
|
+
command = ::VagrantWindows::Provisioners::ChefCommandBuilder.new(
|
38
|
+
@windows_machine, @config, :client).run_chef_command()
|
42
39
|
###################### END - monkey patched code ####################
|
43
40
|
|
44
41
|
@config.attempts.times do |attempt|
|
@@ -32,11 +32,8 @@ module VagrantPlugins
|
|
32
32
|
def run_chef_solo_on_windows
|
33
33
|
|
34
34
|
#################### START - monkey patched code ####################
|
35
|
-
|
36
|
-
@windows_machine, @config, :solo)
|
37
|
-
|
38
|
-
command_builder.prepare_for_chef_run()
|
39
|
-
command = command_builder.run_chef_command()
|
35
|
+
command = ::VagrantWindows::Provisioners::ChefCommandBuilder.new(
|
36
|
+
@windows_machine, @config, :solo).run_chef_command()
|
40
37
|
###################### END - monkey patched code ####################
|
41
38
|
|
42
39
|
@config.attempts.times do |attempt|
|
@@ -34,12 +34,19 @@ module VagrantPlugins
|
|
34
34
|
end
|
35
35
|
comm.upload(path.to_s, fixed_upload_path)
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
# if powershell script we need to bypass the execution policy
|
38
|
+
command = "#{win_friendly_path(fixed_upload_path)}#{args}"
|
39
|
+
command = "powershell -executionpolicy bypass -file #{command}" if
|
40
|
+
File.extname(fixed_upload_path).downcase == '.ps1'
|
41
|
+
|
42
|
+
# for priviliged scripts we need wrap it in a scheduled task
|
43
|
+
if config.privileged
|
44
|
+
command = VagrantWindows.load_script_template('elevated_shell.ps1', :options => {
|
45
|
+
:command => command,
|
46
|
+
:username => windows_machine.winrm_config.username,
|
47
|
+
:password => windows_machine.winrm_config.password
|
48
|
+
})
|
49
|
+
end
|
43
50
|
|
44
51
|
# Execute it with sudo
|
45
52
|
comm.sudo(command) do |type, data|
|