diff --git a/CHANGELOG.md b/CHANGELOG.md index c55af6f71..67ee987ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,11 @@ BUG FIXES: - synced\_folders/rsync: Don't append args infinitely, clear out arg list on each run. [GH-3864] +PLUGIN AUTHOR CHANGES: + + - Providers can now implement the `winrm_info` provider capability + to get proper info for `vagrant rdp` to function. + ## 1.6.2 (May 12, 2014) IMPROVEMENTS: diff --git a/plugins/communicators/winrm/communicator.rb b/plugins/communicators/winrm/communicator.rb index 37ce216fa..3de84b67b 100644 --- a/plugins/communicators/winrm/communicator.rb +++ b/plugins/communicators/winrm/communicator.rb @@ -102,15 +102,13 @@ module VagrantPlugins # This creates anew WinRMShell based on the information we know # about this machine. def create_shell - host_address = Helper.winrm_address(@machine) - host_port = Helper.winrm_port( - @machine, host_address == "127.0.0.1") + winrm_info = Helper.winrm_info(@machine) WinRMShell.new( - host_address, + winrm_info[:host], @machine.config.winrm.username, @machine.config.winrm.password, - port: host_port, + port: winrm_info[:port], timeout_in_seconds: @machine.config.winrm.timeout, max_tries: @machine.config.winrm.max_tries, ) @@ -121,7 +119,7 @@ module VagrantPlugins # run on the guest as a true local admin without any of the restrictions # that WinRM puts in place. # - # @return The path to elevated_shell.ps1 on the guest + # @return The path to elevated_shell.ps1 on the guest def create_elevated_shell_script(command) path = File.expand_path("../scripts/elevated_shell.ps1", __FILE__) script = Vagrant::Util::TemplateRenderer.render(path, options: { diff --git a/plugins/communicators/winrm/helper.rb b/plugins/communicators/winrm/helper.rb index 91349153f..9a0674621 100644 --- a/plugins/communicators/winrm/helper.rb +++ b/plugins/communicators/winrm/helper.rb @@ -4,6 +4,25 @@ module VagrantPlugins # communicator. This is extracted into a module so that we can # easily unit test these methods. module Helper + # Returns the host and port to access WinRM. + # + # This asks the provider via the `winrm_info` capability if it + # exists, otherwise defaulting to its own heuristics. + # + # @param [Vagrant::Machine] machine + # @return [Hash] + def self.winrm_info(machine) + info = {} + if machine.provider.capability?(:winrm_info) + info = machine.provider.capability(:winrm_info) + raise Errors::WinRMNotReady if !info + end + + info[:host] ||= winrm_address(machine) + info[:port] ||= winrm_port(machine, info[:host] == "127.0.0.1") + return info + end + # Returns the address to access WinRM. This does not contain # the port. # diff --git a/test/unit/plugins/communicators/winrm/helper_test.rb b/test/unit/plugins/communicators/winrm/helper_test.rb index e7031a5dc..a14318019 100644 --- a/test/unit/plugins/communicators/winrm/helper_test.rb +++ b/test/unit/plugins/communicators/winrm/helper_test.rb @@ -38,6 +38,59 @@ describe VagrantPlugins::CommunicatorWinRM::Helper do end end + describe ".winrm_info" do + before do + machine.provider.stub(:capability?). + with(:winrm_info).and_return(false) + subject.stub(winrm_address: nil) + subject.stub(winrm_port: nil) + end + + it "returns default info if no capability" do + subject.stub(winrm_address: "bar") + subject.stub(winrm_port: 45) + + result = subject.winrm_info(machine) + expect(result[:host]).to eq("bar") + expect(result[:port]).to eq(45) + end + + it "raises an exception if capability returns nil" do + machine.provider.stub(:capability?). + with(:winrm_info).and_return(true) + machine.provider.stub(:capability).with(:winrm_info).and_return(nil) + + expect { subject.winrm_info(machine) }. + to raise_error(VagrantPlugins::CommunicatorWinRM::Errors::WinRMNotReady) + end + + it "returns the proper information if set" do + machine.provider.stub(:capability?). + with(:winrm_info).and_return(true) + machine.provider.stub(:capability).with(:winrm_info).and_return({ + host: "foo", + port: 12, + }) + + result = subject.winrm_info(machine) + expect(result[:host]).to eq("foo") + expect(result[:port]).to eq(12) + end + + it "defaults information if capability doesn't set it" do + machine.provider.stub(:capability?). + with(:winrm_info).and_return(true) + machine.provider.stub(:capability).with(:winrm_info).and_return({}) + + subject.stub(winrm_address: "bar") + subject.stub(winrm_port: 45) + + result = subject.winrm_info(machine) + expect(result[:host]).to eq("bar") + expect(result[:port]).to eq(45) + end + end + describe ".winrm_port" do it "returns the configured port if no guest port set" do machine.config.winrm.port = 22 @@ -46,6 +99,14 @@ describe VagrantPlugins::CommunicatorWinRM::Helper do expect(subject.winrm_port(machine)).to eq(22) end + it "returns the configured guest port if non local" do + machine.config.winrm.port = 22 + machine.config.winrm.guest_port = 2222 + machine.config.vm.network "forwarded_port", host: 1234, guest: 2222 + + expect(subject.winrm_port(machine, false)).to eq(2222) + end + it "returns a forwarded port that matches the guest port" do machine.config.winrm.port = 22 machine.config.winrm.guest_port = 2222