From 96ab8f60c5d531cedb00307e4816af465f621b2a Mon Sep 17 00:00:00 2001 From: Shawn Neal Date: Wed, 23 Apr 2014 17:50:20 -0700 Subject: [PATCH 1/7] Added WinRM command filters These will be used to replace the guest side command_alias script that is sent with every communicator execute call. This avoids some uncessary remote calls to the guest, makes it unit testable, and allows larger PowerShell commands to be invoked. --- plugins/communicators/winrm/command_filter.rb | 47 +++++++++++++ .../winrm/command_filters/cat.rb | 27 +++++++ .../winrm/command_filters/chmod.rb | 21 ++++++ .../winrm/command_filters/chown.rb | 21 ++++++ .../communicators/winrm/command_filters/rm.rb | 28 ++++++++ .../winrm/command_filters/test.rb | 37 ++++++++++ .../winrm/command_filters/uname.rb | 31 ++++++++ .../winrm/command_filters/which.rb | 26 +++++++ .../winrm/command_filter_test.rb | 70 +++++++++++++++++++ 9 files changed, 308 insertions(+) create mode 100644 plugins/communicators/winrm/command_filter.rb create mode 100644 plugins/communicators/winrm/command_filters/cat.rb create mode 100644 plugins/communicators/winrm/command_filters/chmod.rb create mode 100644 plugins/communicators/winrm/command_filters/chown.rb create mode 100644 plugins/communicators/winrm/command_filters/rm.rb create mode 100644 plugins/communicators/winrm/command_filters/test.rb create mode 100644 plugins/communicators/winrm/command_filters/uname.rb create mode 100644 plugins/communicators/winrm/command_filters/which.rb create mode 100644 test/unit/plugins/communicators/winrm/command_filter_test.rb diff --git a/plugins/communicators/winrm/command_filter.rb b/plugins/communicators/winrm/command_filter.rb new file mode 100644 index 000000000..dcae3d1fc --- /dev/null +++ b/plugins/communicators/winrm/command_filter.rb @@ -0,0 +1,47 @@ +module VagrantPlugins + module CommunicatorWinRM + + # Handles loading and applying all available WinRM command filters + class CommandFilter + + @@cmd_filters = [ + "cat", + "chmod", + "chown", + "rm", + "test", + "uname", + "which" + ] + + # Filter the given Vagrant command to ensure compatibility with Windows + # + # @param [String] The Vagrant shell command + # @returns [String] Windows runnable command or empty string + def filter(command) + command_filters.each { |c| command = c.filter(command) if c.accept?(command) } + command + end + + # All the available Linux command filters + # + # @returns [Array] All Linux command filter instances + def command_filters + @command_filters ||= create_command_filters() + end + + private + + def create_command_filters + [].tap do |filters| + @@cmd_filters.each do |cmd| + require_relative "command_filters/#{cmd}" + class_name = "VagrantPlugins::CommunicatorWinRM::CommandFilters::#{cmd.capitalize}" + filters << Module.const_get(class_name).new + end + end + end + + end + end +end diff --git a/plugins/communicators/winrm/command_filters/cat.rb b/plugins/communicators/winrm/command_filters/cat.rb new file mode 100644 index 000000000..5d9cf8e01 --- /dev/null +++ b/plugins/communicators/winrm/command_filters/cat.rb @@ -0,0 +1,27 @@ +module VagrantPlugins + module CommunicatorWinRM + module CommandFilters + + # Handles the special case of determining the guest OS using cat + class Cat + + def filter(command) + # cat /etc/release | grep -i OmniOS + # cat /etc/redhat-release + # cat /etc/issue | grep 'Core Linux' + # cat /etc/release | grep -i SmartOS + '' + end + + def accept?(command) + # cat works in PowerShell, however we don't want to run Guest + # OS detection as this will fail on Windows because the lack of the + # grep command + command.start_with?('cat /etc/') + end + + end + + end + end +end diff --git a/plugins/communicators/winrm/command_filters/chmod.rb b/plugins/communicators/winrm/command_filters/chmod.rb new file mode 100644 index 000000000..a336f5dd4 --- /dev/null +++ b/plugins/communicators/winrm/command_filters/chmod.rb @@ -0,0 +1,21 @@ +module VagrantPlugins + module CommunicatorWinRM + module CommandFilters + + # Converts a *nix 'chmod' command to a PowerShell equivalent + class Chmod + + def filter(command) + # Not support on Windows, the communicator will skip this command + '' + end + + def accept?(command) + command.start_with?('chmod ') + end + + end + + end + end +end diff --git a/plugins/communicators/winrm/command_filters/chown.rb b/plugins/communicators/winrm/command_filters/chown.rb new file mode 100644 index 000000000..127731ff6 --- /dev/null +++ b/plugins/communicators/winrm/command_filters/chown.rb @@ -0,0 +1,21 @@ +module VagrantPlugins + module CommunicatorWinRM + module CommandFilters + + # Converts a *nix 'chown' command to a PowerShell equivalent + class Chown + + def filter(command) + # Not support on Windows, the communicator will skip this command + '' + end + + def accept?(command) + command.start_with?('chown ') + end + + end + + end + end +end diff --git a/plugins/communicators/winrm/command_filters/rm.rb b/plugins/communicators/winrm/command_filters/rm.rb new file mode 100644 index 000000000..a0078c83d --- /dev/null +++ b/plugins/communicators/winrm/command_filters/rm.rb @@ -0,0 +1,28 @@ +module VagrantPlugins + module CommunicatorWinRM + module CommandFilters + + # Converts a *nix 'rm' command to a PowerShell equivalent + class Rm + + def filter(command) + # rm -Rf /some/dir + # rm /some/dir + cmd_parts = command.strip.split(/\s+/) + dir = cmd_parts[1] + if dir == '-Rf' + dir = cmd_parts[2] + return "rm '#{dir}' -recurse -force" + end + return "rm '#{dir}' -force" + end + + def accept?(command) + command.start_with?('rm ') + end + + end + + end + end +end diff --git a/plugins/communicators/winrm/command_filters/test.rb b/plugins/communicators/winrm/command_filters/test.rb new file mode 100644 index 000000000..d837ece0c --- /dev/null +++ b/plugins/communicators/winrm/command_filters/test.rb @@ -0,0 +1,37 @@ +module VagrantPlugins + module CommunicatorWinRM + module CommandFilters + + # Converts a *nix 'test' command to a PowerShell equivalent + class Test + + def filter(command) + # test -d /tmp/dir + # test -f /tmp/afile + # test -L /somelink + # test -x /tmp/some.exe + + cmd_parts = command.strip.split(/\s+/) + if cmd_parts[1] == '-d' + # ensure it exists and is a directory + return "if ((Test-Path '#{cmd_parts[2]}') -and (get-item '#{cmd_parts[2]}').PSIsContainer) { exit 0 } exit 1" + elsif cmd_parts[1] == '-f' || cmd_parts[1] == '-x' + # ensure it exists and is a file + return "if ((Test-Path '#{cmd_parts[2]}') -and (!(get-item '#{cmd_parts[2]}').PSIsContainer)) { exit 0 } exit 1" + end + + # otherwise, just check for existence + return "if (Test-Path '#{cmd_parts[2]}') { exit 0 } exit 1" + end + + # if (Test-Path 'c:\windows' && (get-item 'c:\windows').PSIsContainer) { Write-Host 0 } Write-Host 1 + + def accept?(command) + command.start_with?('test ') + end + + end + + end + end +end diff --git a/plugins/communicators/winrm/command_filters/uname.rb b/plugins/communicators/winrm/command_filters/uname.rb new file mode 100644 index 000000000..4a8b0836d --- /dev/null +++ b/plugins/communicators/winrm/command_filters/uname.rb @@ -0,0 +1,31 @@ +module VagrantPlugins + module CommunicatorWinRM + module CommandFilters + + # Converts a *nix 'uname' command to a PowerShell equivalent + class Uname + + def filter(command) + # uname -s | grep 'Darwin' + # uname -s | grep VMkernel + # uname -s | grep 'FreeBSD' + # uname -s | grep 'Linux' + # uname -s | grep NetBSD + # uname -s | grep 'OpenBSD' + # uname -sr | grep SunOS | grep -v 5.11 + # uname -sr | grep 'SunOS 5.11' + + # uname is used to detect the guest type in Vagrant, so don't bother running + # to speed up OS detection + '' + end + + def accept?(command) + command.start_with?('uname ') + end + + end + + end + end +end diff --git a/plugins/communicators/winrm/command_filters/which.rb b/plugins/communicators/winrm/command_filters/which.rb new file mode 100644 index 000000000..cf046ca19 --- /dev/null +++ b/plugins/communicators/winrm/command_filters/which.rb @@ -0,0 +1,26 @@ +module VagrantPlugins + module CommunicatorWinRM + module CommandFilters + + # Converts a *nix 'which' command to a PowerShell equivalent + class Which + + def filter(command) + executable = command.strip.split(/\s+/)[1] + return <<-EOH + $command = [Array](Get-Command #{executable} -errorAction SilentlyContinue) + if ($null -eq $command) { exit 1 } + write-host $command[0].Definition + exit 0 + EOH + end + + def accept?(command) + command.start_with?('which ') + end + + end + + end + end +end diff --git a/test/unit/plugins/communicators/winrm/command_filter_test.rb b/test/unit/plugins/communicators/winrm/command_filter_test.rb new file mode 100644 index 000000000..71010154d --- /dev/null +++ b/test/unit/plugins/communicators/winrm/command_filter_test.rb @@ -0,0 +1,70 @@ +require File.expand_path("../../../../base", __FILE__) + +require Vagrant.source_root.join("plugins/communicators/winrm/command_filter") + +describe VagrantPlugins::CommunicatorWinRM::CommandFilter, :unit => true do + + describe '.command_filters' do + it 'initializes all command filters in command filters directory' do + expect(subject.command_filters()).not_to be_empty + end + end + + describe '.filter' do + it 'filters out uname commands' do + expect(subject.filter('uname -s stuff')).to eq('') + end + + it 'filters out which commands' do + expect(subject.filter('which ruby')).to include( + '[Array](Get-Command ruby -errorAction SilentlyContinue)') + end + + it 'filters out test -d commands' do + expect(subject.filter('test -d /tmp/dir')).to eq( + "if ((Test-Path '/tmp/dir') -and (get-item '/tmp/dir').PSIsContainer) { exit 0 } exit 1") + end + + it 'filters out test -f commands' do + expect(subject.filter('test -f /tmp/file.txt')).to eq( + "if ((Test-Path '/tmp/file.txt') -and (!(get-item '/tmp/file.txt').PSIsContainer)) { exit 0 } exit 1") + end + + it 'filters out test -x commands' do + expect(subject.filter('test -x /tmp/file.txt')).to eq( + "if ((Test-Path '/tmp/file.txt') -and (!(get-item '/tmp/file.txt').PSIsContainer)) { exit 0 } exit 1") + end + + it 'filters out other test commands' do + expect(subject.filter('test -L /tmp/file.txt')).to eq( + "if (Test-Path '/tmp/file.txt') { exit 0 } exit 1") + end + + it 'filters out rm -Rf commands' do + expect(subject.filter('rm -Rf /some/dir')).to eq( + "rm '/some/dir' -recurse -force") + end + + it 'filters out rm commands' do + expect(subject.filter('rm /some/dir')).to eq( + "rm '/some/dir' -force") + end + + it 'filters out chown commands' do + expect(subject.filter("chown -R root '/tmp/dir'")).to eq('') + end + + it 'filters out chmod commands' do + expect(subject.filter("chmod 0600 ~/.ssh/authorized_keys")).to eq('') + end + + it 'filters out certain cat commands' do + expect(subject.filter("cat /etc/release | grep -i OmniOS")).to eq('') + end + + it 'should not filter out other cat commands' do + expect(subject.filter("cat /tmp/somefile")).to eq('cat /tmp/somefile') + end + end + +end From 3efb4b1def4a28489af9fe27f02c6ab323c16500 Mon Sep 17 00:00:00 2001 From: Shawn Neal Date: Wed, 23 Apr 2014 18:05:53 -0700 Subject: [PATCH 2/7] Allow WinRM shell test less restrictive This will allow the shell class to append additional commands like exit $EXITCODE --- test/unit/plugins/communicators/winrm/shell_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/plugins/communicators/winrm/shell_test.rb b/test/unit/plugins/communicators/winrm/shell_test.rb index 79d6970d8..477108b97 100644 --- a/test/unit/plugins/communicators/winrm/shell_test.rb +++ b/test/unit/plugins/communicators/winrm/shell_test.rb @@ -15,19 +15,19 @@ describe VagrantPlugins::CommunicatorWinRM::WinRMShell do describe ".powershell" do it "should call winrm powershell" do - expect(session).to receive(:powershell).with("dir").and_return({ exitcode: 0 }) + expect(session).to receive(:powershell).with(/^dir.+/).and_return({ exitcode: 0 }) expect(subject.powershell("dir")[:exitcode]).to eq(0) end it "should raise auth error when exception message contains 401" do - expect(session).to receive(:powershell).with("dir").and_raise( + expect(session).to receive(:powershell).with(/^dir.+/).and_raise( StandardError.new("Oh no! a 401 SOAP error!")) expect { subject.powershell("dir") }.to raise_error( VagrantPlugins::CommunicatorWinRM::Errors::AuthError) end it "should raise an execution error when an exception occurs" do - expect(session).to receive(:powershell).with("dir").and_raise( + expect(session).to receive(:powershell).with(/^dir.+/).and_raise( StandardError.new("Oh no! a 500 SOAP error!")) expect { subject.powershell("dir") }.to raise_error( VagrantPlugins::CommunicatorWinRM::Errors::ExecutionError) From ac81841b014059195e95e182a177d4923ee57116 Mon Sep 17 00:00:00 2001 From: Shawn Neal Date: Wed, 23 Apr 2014 18:26:45 -0700 Subject: [PATCH 3/7] test command should expand environment variables '$Env:SystemRoot' does not expand "$Env:SystemRoot" does expand --- plugins/communicators/winrm/command_filters/test.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/communicators/winrm/command_filters/test.rb b/plugins/communicators/winrm/command_filters/test.rb index d837ece0c..76850be06 100644 --- a/plugins/communicators/winrm/command_filters/test.rb +++ b/plugins/communicators/winrm/command_filters/test.rb @@ -14,20 +14,20 @@ module VagrantPlugins cmd_parts = command.strip.split(/\s+/) if cmd_parts[1] == '-d' # ensure it exists and is a directory - return "if ((Test-Path '#{cmd_parts[2]}') -and (get-item '#{cmd_parts[2]}').PSIsContainer) { exit 0 } exit 1" + return "if ((Test-Path \"#{cmd_parts[2]}\") -and (get-item \"#{cmd_parts[2]}\").PSIsContainer) { exit 0 } exit 1" elsif cmd_parts[1] == '-f' || cmd_parts[1] == '-x' # ensure it exists and is a file - return "if ((Test-Path '#{cmd_parts[2]}') -and (!(get-item '#{cmd_parts[2]}').PSIsContainer)) { exit 0 } exit 1" + return "if ((Test-Path \"#{cmd_parts[2]}\") -and (!(get-item \"#{cmd_parts[2]}\").PSIsContainer)) { exit 0 } exit 1" end # otherwise, just check for existence - return "if (Test-Path '#{cmd_parts[2]}') { exit 0 } exit 1" + return "if (Test-Path \"#{cmd_parts[2]}\") { exit 0 } exit 1" end # if (Test-Path 'c:\windows' && (get-item 'c:\windows').PSIsContainer) { Write-Host 0 } Write-Host 1 def accept?(command) - command.start_with?('test ') + command.start_with?("test ") end end From 1525aa0f785d38c4b99c8db4599ed4732efa8bc4 Mon Sep 17 00:00:00 2001 From: Shawn Neal Date: Wed, 23 Apr 2014 20:37:15 -0700 Subject: [PATCH 4/7] Added WinRM grep command filter This is needed because isn't available on Windows and Vagrant guest detection attempts to use grep for some OSs. --- plugins/communicators/winrm/command_filter.rb | 1 + .../winrm/command_filters/grep.rb | 26 +++++++++++++++++++ .../winrm/command_filter_test.rb | 4 +++ 3 files changed, 31 insertions(+) create mode 100644 plugins/communicators/winrm/command_filters/grep.rb diff --git a/plugins/communicators/winrm/command_filter.rb b/plugins/communicators/winrm/command_filter.rb index dcae3d1fc..4b5e2ab5c 100644 --- a/plugins/communicators/winrm/command_filter.rb +++ b/plugins/communicators/winrm/command_filter.rb @@ -8,6 +8,7 @@ module VagrantPlugins "cat", "chmod", "chown", + "grep", "rm", "test", "uname", diff --git a/plugins/communicators/winrm/command_filters/grep.rb b/plugins/communicators/winrm/command_filters/grep.rb new file mode 100644 index 000000000..96ce32ca6 --- /dev/null +++ b/plugins/communicators/winrm/command_filters/grep.rb @@ -0,0 +1,26 @@ +module VagrantPlugins + module CommunicatorWinRM + module CommandFilters + + # Converts a *nix 'grep' command to a PowerShell equivalent + class Grep + + def filter(command) + # grep 'Fedora release [12][67890]' /etc/redhat-release + # grep Funtoo /etc/gentoo-release + # grep Gentoo /etc/gentoo-release + + # grep is often used to detect the guest type in Vagrant, so don't bother running + # to speed up OS detection + '' + end + + def accept?(command) + command.start_with?('grep ') + end + + end + + end + end +end \ No newline at end of file diff --git a/test/unit/plugins/communicators/winrm/command_filter_test.rb b/test/unit/plugins/communicators/winrm/command_filter_test.rb index 71010154d..f226b8e9d 100644 --- a/test/unit/plugins/communicators/winrm/command_filter_test.rb +++ b/test/unit/plugins/communicators/winrm/command_filter_test.rb @@ -15,6 +15,10 @@ describe VagrantPlugins::CommunicatorWinRM::CommandFilter, :unit => true do expect(subject.filter('uname -s stuff')).to eq('') end + it 'filters out grep commands' do + expect(subject.filter("grep 'Fedora release [12][67890]' /etc/redhat-release")).to eq("") + end + it 'filters out which commands' do expect(subject.filter('which ruby')).to include( '[Array](Get-Command ruby -errorAction SilentlyContinue)') From f44c795eed6e956b389b748445a500240797bf4c Mon Sep 17 00:00:00 2001 From: Shawn Neal Date: Wed, 23 Apr 2014 20:38:16 -0700 Subject: [PATCH 5/7] Integrated WinRM command filter into communicator *nix commands are now filtered out instead of being sent to the guest. This means the command_alias PowerShell script is no longer needed. Moved the PowerShell exit code helper to the WinRM shell and changed it to always return an exit code. --- plugins/communicators/winrm/communicator.rb | 25 +++++++------ .../winrm/scripts/command_alias.ps1 | 35 ------------------- plugins/communicators/winrm/shell.rb | 3 ++ 3 files changed, 15 insertions(+), 48 deletions(-) delete mode 100644 plugins/communicators/winrm/scripts/command_alias.ps1 diff --git a/plugins/communicators/winrm/communicator.rb b/plugins/communicators/winrm/communicator.rb index 850b0eba7..c806960e7 100644 --- a/plugins/communicators/winrm/communicator.rb +++ b/plugins/communicators/winrm/communicator.rb @@ -4,6 +4,7 @@ require "log4r" require_relative "helper" require_relative "shell" +require_relative "command_filter" module VagrantPlugins module CommunicatorWinRM @@ -16,9 +17,10 @@ module VagrantPlugins end def initialize(machine) - @machine = machine - @logger = Log4r::Logger.new("vagrant::communication::winrm") - @shell = nil + @machine = machine + @shell = nil + @logger = Log4r::Logger.new("vagrant::communication::winrm") + @cmd_filter = CommandFilter.new() @logger.info("Initializing WinRMCommunicator") end @@ -50,6 +52,10 @@ module VagrantPlugins end def execute(command, opts={}, &block) + # If this is a *nix command with no Windows equivilant, don't run it + command = @cmd_filter.filter(command) + return 0 if command.empty? + opts = { :error_check => true, :error_class => Errors::ExecutionError, @@ -58,12 +64,6 @@ module VagrantPlugins :shell => :powershell }.merge(opts || {}) - if opts[:shell] == :powershell - script = File.expand_path("../scripts/command_alias.ps1", __FILE__) - script = File.read(script) - command = script << "\r\n" << command << "\r\nexit $LASTEXITCODE" - end - output = shell.send(opts[:shell], command, &block) return output if opts[:shell] == :wql @@ -74,10 +74,9 @@ module VagrantPlugins alias_method :sudo, :execute def test(command, opts=nil) - @logger.info("Testing: #{command}") - - # HACK: to speed up Vagrant 1.2 OS detection, skip checking for *nix OS - return false unless (command =~ /^uname|^cat \/etc|^cat \/proc|grep 'Fedora/).nil? + # If this is a *nix command with no Windows equivilant, assume failure + command = @cmd_filter.filter(command) + return false if command.empty? opts = { :error_check => false }.merge(opts || {}) execute(command, opts) == 0 diff --git a/plugins/communicators/winrm/scripts/command_alias.ps1 b/plugins/communicators/winrm/scripts/command_alias.ps1 deleted file mode 100644 index 0955db6d8..000000000 --- a/plugins/communicators/winrm/scripts/command_alias.ps1 +++ /dev/null @@ -1,35 +0,0 @@ -function which { - $command = [Array](Get-Command $args[0] -errorAction SilentlyContinue) - if($null -eq $command) - { - exit 1 - } - write-host $command[0].Definition - exit 0 -} - -function test ([Switch] $d, [String] $path) { - if(Test-Path $path) - { - exit 0 - } - exit 1 -} - -function chmod { - exit 0 -} - -function chown { - exit 0 -} - -function mkdir ([Switch] $p, [String] $path) -{ - if(Test-Path $path) - { - exit 0 - } else { - New-Item $path -Type Directory -Force | Out-Null - } -} diff --git a/plugins/communicators/winrm/shell.rb b/plugins/communicators/winrm/shell.rb index 772c8944d..131c79141 100644 --- a/plugins/communicators/winrm/shell.rb +++ b/plugins/communicators/winrm/shell.rb @@ -52,6 +52,9 @@ module VagrantPlugins end def powershell(command, &block) + # ensure an exit code + command << "\r\n" + command << "if ($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 0 }" execute_shell(command, :powershell, &block) end From 4a2a147926c901201488af9e7e60ced41adc0127 Mon Sep 17 00:00:00 2001 From: Shawn Neal Date: Wed, 23 Apr 2014 21:15:05 -0700 Subject: [PATCH 6/7] Refactored WinRM test command filter --- .../winrm/command_filters/test.rb | 53 +++++++++++++++---- .../winrm/command_filter_test.rb | 24 ++++++--- 2 files changed, 58 insertions(+), 19 deletions(-) diff --git a/plugins/communicators/winrm/command_filters/test.rb b/plugins/communicators/winrm/command_filters/test.rb index 76850be06..23fddc8bf 100644 --- a/plugins/communicators/winrm/command_filters/test.rb +++ b/plugins/communicators/winrm/command_filters/test.rb @@ -12,24 +12,55 @@ module VagrantPlugins # test -x /tmp/some.exe cmd_parts = command.strip.split(/\s+/) - if cmd_parts[1] == '-d' - # ensure it exists and is a directory - return "if ((Test-Path \"#{cmd_parts[2]}\") -and (get-item \"#{cmd_parts[2]}\").PSIsContainer) { exit 0 } exit 1" - elsif cmd_parts[1] == '-f' || cmd_parts[1] == '-x' - # ensure it exists and is a file - return "if ((Test-Path \"#{cmd_parts[2]}\") -and (!(get-item \"#{cmd_parts[2]}\").PSIsContainer)) { exit 0 } exit 1" + flag = cmd_parts[1] + path = cmd_parts[2] + + if flag == '-d' + check_for_directory(path) + elsif flag == '-f' || flag == '-x' + check_for_file(path) + else + check_exists(path) end - - # otherwise, just check for existence - return "if (Test-Path \"#{cmd_parts[2]}\") { exit 0 } exit 1" end - # if (Test-Path 'c:\windows' && (get-item 'c:\windows').PSIsContainer) { Write-Host 0 } Write-Host 1 - def accept?(command) command.start_with?("test ") end + + private + + def check_for_directory(path) + <<-EOH + $p = "#{path}" + if ((Test-Path $p) -and (get-item $p).PSIsContainer) { + exit 0 + } + exit 1 + EOH + end + + def check_for_file(path) + <<-EOH + $p = "#{path}" + if ((Test-Path $p) -and (!(get-item $p).PSIsContainer)) { + exit 0 + } + exit 1 + EOH + end + + def check_exists(path) + <<-EOH + $p = "#{path}" + if (Test-Path $p) { + exit 0 + } + exit 1 + EOH + end + end end diff --git a/test/unit/plugins/communicators/winrm/command_filter_test.rb b/test/unit/plugins/communicators/winrm/command_filter_test.rb index f226b8e9d..e56d1cd10 100644 --- a/test/unit/plugins/communicators/winrm/command_filter_test.rb +++ b/test/unit/plugins/communicators/winrm/command_filter_test.rb @@ -25,23 +25,31 @@ describe VagrantPlugins::CommunicatorWinRM::CommandFilter, :unit => true do end it 'filters out test -d commands' do - expect(subject.filter('test -d /tmp/dir')).to eq( - "if ((Test-Path '/tmp/dir') -and (get-item '/tmp/dir').PSIsContainer) { exit 0 } exit 1") + expect(subject.filter('test -d /tmp/dir')).to include( + "$p = \"/tmp/dir\"") + expect(subject.filter('test -d /tmp/dir')).to include( + "if ((Test-Path $p) -and (get-item $p).PSIsContainer) {") end it 'filters out test -f commands' do - expect(subject.filter('test -f /tmp/file.txt')).to eq( - "if ((Test-Path '/tmp/file.txt') -and (!(get-item '/tmp/file.txt').PSIsContainer)) { exit 0 } exit 1") + expect(subject.filter('test -f /tmp/file.txt')).to include( + "$p = \"/tmp/file.txt\"") + expect(subject.filter('test -f /tmp/file.txt')).to include( + "if ((Test-Path $p) -and (!(get-item $p).PSIsContainer)) {") end it 'filters out test -x commands' do - expect(subject.filter('test -x /tmp/file.txt')).to eq( - "if ((Test-Path '/tmp/file.txt') -and (!(get-item '/tmp/file.txt').PSIsContainer)) { exit 0 } exit 1") + expect(subject.filter('test -x /tmp/file.txt')).to include( + "$p = \"/tmp/file.txt\"") + expect(subject.filter('test -x /tmp/file.txt')).to include( + "if ((Test-Path $p) -and (!(get-item $p).PSIsContainer)) {") end it 'filters out other test commands' do - expect(subject.filter('test -L /tmp/file.txt')).to eq( - "if (Test-Path '/tmp/file.txt') { exit 0 } exit 1") + expect(subject.filter('test -L /tmp/file.txt')).to include( + "$p = \"/tmp/file.txt\"") + expect(subject.filter('test -L /tmp/file.txt')).to include( + "if (Test-Path $p) {") end it 'filters out rm -Rf commands' do From ab51a786ff07a97fdf9789cb4109187bade62322 Mon Sep 17 00:00:00 2001 From: Shawn Neal Date: Wed, 23 Apr 2014 21:49:28 -0700 Subject: [PATCH 7/7] Extract execution_output method from WinRM comm execute --- plugins/communicators/winrm/communicator.rb | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/plugins/communicators/winrm/communicator.rb b/plugins/communicators/winrm/communicator.rb index c806960e7..fe1d66f92 100644 --- a/plugins/communicators/winrm/communicator.rb +++ b/plugins/communicators/winrm/communicator.rb @@ -65,11 +65,7 @@ module VagrantPlugins }.merge(opts || {}) output = shell.send(opts[:shell], command, &block) - - return output if opts[:shell] == :wql - exitcode = output[:exitcode] - raise_execution_error(opts, exitcode) if opts[:error_check] && exitcode != 0 - exitcode + execution_output(output, opts) end alias_method :sudo, :execute @@ -110,10 +106,21 @@ module VagrantPlugins ) end - def raise_execution_error(opts, exit_code) + # Handles the raw WinRM shell result and converts it to a + # standard Vagrant communicator result + def execution_output(output, opts) + if opts[:shell] == :wql + return output + elsif opts[:error_check] && output[:exitcode] != 0 + raise_execution_error(output, opts) + end + output[:exitcode] + end + + def raise_execution_error(output, opts) # The error classes expect the translation key to be _key, but that makes for an ugly # configuration parameter, so we set it here from `error_key` - msg = "Command execution failed with an exit code of #{exit_code}" + msg = "Command execution failed with an exit code of #{output[:exitcode]}" error_opts = opts.merge(:_key => opts[:error_key], :message => msg) raise opts[:error_class], error_opts end