From c4422d7c70312de67266e368316da40cbaca6cff Mon Sep 17 00:00:00 2001 From: Shawn Neal Date: Tue, 16 Dec 2014 08:20:01 -0800 Subject: [PATCH 1/2] Fix guest autodetection when running windows guests so Vagrant doesn't think the guest is Ubuntu --- plugins/communicators/winrm/communicator.rb | 33 +++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/plugins/communicators/winrm/communicator.rb b/plugins/communicators/winrm/communicator.rb index 7609f16b3..e815b4514 100644 --- a/plugins/communicators/winrm/communicator.rb +++ b/plugins/communicators/winrm/communicator.rb @@ -79,12 +79,21 @@ module VagrantPlugins alias_method :sudo, :execute def test(command, opts=nil) - # If this is a *nix command with no Windows equivilant, assume failure + # If this is a *nix command (which we know about) 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 + opts = { + command: command, + elevated: false, + error_check: false, + }.merge(opts || {}) + + # If we're passed a *nix command which PS can't parse we get exit code + # 0, but output in stderr. We need to check both exit code and stderr. + output = shell.send(:powershell, command) + return output[:exitcode] == 0 && flatten_stderr(output).length == 0 end def upload(from, to) @@ -156,8 +165,8 @@ module VagrantPlugins def raise_execution_error(output, opts) # WinRM can return multiple stderr and stdout entries error_opts = opts.merge( - stdout: output[:data].collect { |e| e[:stdout] }.join, - stderr: output[:data].collect { |e| e[:stderr] }.join + stdout: flatten_stdout(output), + stderr: flatten_stderr(output) ) # Use a different error message key if the caller gave us one, @@ -167,6 +176,20 @@ module VagrantPlugins # Raise the error, use the type the caller gave us or the comm default raise opts[:error_class], error_opts end + + + # TODO: Replace with WinRM Output class when WinRM 1.3 is released + def flatten_stderr(output) + output[:data].map do | line | + line[:stderr] + end.compact.join + end + + def flatten_stdout(output) + output[:data].map do | line | + line[:flatten_stdout] + end.compact.join + end end #WinRM class end end From f7a344fe958e02762312f4215485c2e453040c05 Mon Sep 17 00:00:00 2001 From: Shawn Neal Date: Tue, 16 Dec 2014 09:20:51 -0800 Subject: [PATCH 2/2] Added test to ensure comm test method checks stderr --- .../plugins/communicators/winrm/communicator_test.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/unit/plugins/communicators/winrm/communicator_test.rb b/test/unit/plugins/communicators/winrm/communicator_test.rb index 1433f4317..095e2753a 100644 --- a/test/unit/plugins/communicators/winrm/communicator_test.rb +++ b/test/unit/plugins/communicators/winrm/communicator_test.rb @@ -75,15 +75,23 @@ describe VagrantPlugins::CommunicatorWinRM::Communicator do describe ".test" do it "returns true when exit code is zero" do - expect(shell).to receive(:powershell).with(kind_of(String)).and_return({ exitcode: 0 }) + output = { exitcode: 0, data:[{ stderr: '' }] } + expect(shell).to receive(:powershell).with(kind_of(String)).and_return(output) expect(subject.test("test -d c:/windows")).to be_true end it "returns false when exit code is non-zero" do - expect(shell).to receive(:powershell).with(kind_of(String)).and_return({ exitcode: 1 }) + output = { exitcode: 1, data:[{ stderr: '' }] } + expect(shell).to receive(:powershell).with(kind_of(String)).and_return(output) expect(subject.test("test -d /tmp/foobar")).to be_false end + it "returns false when stderr contains output" do + output = { exitcode: 0, data:[{ stderr: 'this is an error' }] } + expect(shell).to receive(:powershell).with(kind_of(String)).and_return(output) + expect(subject.test("[-x stuff] && foo")).to be_false + end + it "returns false when command is testing for linux OS" do expect(subject.test("uname -s | grep Debian")).to be_false end