diff --git a/lib/vagrant/util/powershell.rb b/lib/vagrant/util/powershell.rb index d685e0b56ea..7c96485eaf5 100644 --- a/lib/vagrant/util/powershell.rb +++ b/lib/vagrant/util/powershell.rb @@ -11,6 +11,8 @@ module Util class PowerShell # NOTE: Version checks are only on Major MINIMUM_REQUIRED_VERSION = 3 + # Number of seconds to wait while attempting to get powershell version + DEFAULT_VERSION_DETECTION_TIMEOUT = 30 LOGGER = Log4r::Logger.new("vagrant::util::powershell") # @return [String|nil] a powershell executable, depending on environment @@ -101,8 +103,15 @@ def self.version ].flatten version = nil + timeout = ENV["VAGRANT_POWERSHELL_VERSION_DETECTION_TIMEOUT"].to_i + if timeout < 1 + timeout = DEFAULT_VERSION_DETECTION_TIMEOUT + end begin - r = Subprocess.execute(*command, notify: [:stdout, :stderr], timeout: 10) {|io_name,data| version = data} + r = Subprocess.execute(*command, + notify: [:stdout, :stderr], + timeout: timeout, + ) {|io_name,data| version = data} rescue Vagrant::Util::Subprocess::TimeoutExceeded LOGGER.debug("Timeout exceeded while attempting to determine version of Powershell.") end @@ -183,6 +192,13 @@ def self.powerup_command(path, args, opts) Subprocess::Result.new(code, r_stdout, r_stderr) end end + + # @private + # Reset the cached values for platform. This is not considered a public + # API and should only be used for testing. + def self.reset! + instance_variables.each(&method(:remove_instance_variable)) + end end end end diff --git a/test/unit/vagrant/util/powershell_test.rb b/test/unit/vagrant/util/powershell_test.rb new file mode 100644 index 00000000000..d5760fc28dc --- /dev/null +++ b/test/unit/vagrant/util/powershell_test.rb @@ -0,0 +1,44 @@ +require File.expand_path("../../../base", __FILE__) + +require 'vagrant/util/powershell' + +describe Vagrant::Util::PowerShell do + include_context "unit" + describe ".version" do + before do + allow(described_class).to receive(:executable) + .and_return("powershell") + allow(Vagrant::Util::Subprocess).to receive(:execute) + end + + after do + described_class.version + described_class.reset! + end + + it "should execute powershell command" do + expect(Vagrant::Util::Subprocess).to receive(:execute).with("powershell", any_args) + end + + it "should use the default timeout" do + expect(Vagrant::Util::Subprocess).to receive(:execute).with(any_args, hash_including( + timeout: Vagrant::Util::PowerShell::DEFAULT_VERSION_DETECTION_TIMEOUT)) + end + + it "should use environment variable provided timeout" do + with_temp_env("VAGRANT_POWERSHELL_VERSION_DETECTION_TIMEOUT" => "1") do + expect(Vagrant::Util::Subprocess).to receive(:execute).with(any_args, hash_including( + timeout: 1)) + described_class.version + end + end + + it "should use default timeout when environment variable value is invalid" do + with_temp_env("VAGRANT_POWERSHELL_VERSION_DETECTION_TIMEOUT" => "invalid value") do + expect(Vagrant::Util::Subprocess).to receive(:execute).with(any_args, hash_including( + timeout: Vagrant::Util::PowerShell::DEFAULT_VERSION_DETECTION_TIMEOUT)) + described_class.version + end + end + end +end diff --git a/website/source/docs/other/environmental-variables.html.md b/website/source/docs/other/environmental-variables.html.md index d474faf9b0a..3eaaa33396b 100644 --- a/website/source/docs/other/environmental-variables.html.md +++ b/website/source/docs/other/environmental-variables.html.md @@ -227,3 +227,11 @@ Use the Ruby Resolv library in place of the libc resolver. Vagrant can optionally use the Ruby Resolv library in place of the libc resolver. This can be disabled setting this environment variable. + +## `VAGRANT_POWERSHELL_VERSION_DETECTION_TIMEOUT` + +Vagrant will use a default timeout when checking for the installed version +of PowerShell. Occasionally the default can be too low and Vagrant will report +being unable to detect the installed version of PowerShell. This environment +variable can be used to extend the timeout used during PowerShell version +detection.