vagrant-windows 1.6.0 → 1.7.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- 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|
|