From c7721f619b0c583adece274262810060eba59def Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Tue, 13 Nov 2018 14:59:48 -0800 Subject: [PATCH] Update VirtualBox driver ssh_port helper Be more restrictive when matching the port forward used for SSH. Allow matching simply on the guest port, but also include extra matching criteria for cases where multiple results may be returned. --- .../virtualbox/driver/version_5_0.rb | 19 +++++-- .../virtualbox/driver/version_5_0_test.rb | 53 +++++++++++++++++++ 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/plugins/providers/virtualbox/driver/version_5_0.rb b/plugins/providers/virtualbox/driver/version_5_0.rb index e8522e7ac..aff0607ee 100644 --- a/plugins/providers/virtualbox/driver/version_5_0.rb +++ b/plugins/providers/virtualbox/driver/version_5_0.rb @@ -689,12 +689,21 @@ module VagrantPlugins def ssh_port(expected_port) @logger.debug("Searching for SSH port: #{expected_port.inspect}") - # Look for the forwarded port only by comparing the guest port - read_forwarded_ports.each do |_, _, hostport, guestport| - return hostport if guestport == expected_port - end + # Look for the forwarded port. Valid based on the guest port, but will do + # scoring based matching to determine best value when multiple results are + # available. + matches = read_forwarded_ports.map do |_, name, hostport, guestport, host_ip| + next if guestport != expected_port + match = [0, hostport] + match[0] += 1 if name == "ssh" + match[0] += 1 if name.downcase == "ssh" + match[0] += 1 if host_ip == "127.0.0.1" + match + end.compact - nil + result = matches.sort_by(&:first).last + + result.last if result end def resume diff --git a/test/unit/plugins/providers/virtualbox/driver/version_5_0_test.rb b/test/unit/plugins/providers/virtualbox/driver/version_5_0_test.rb index 1e833afcc..2cc124027 100644 --- a/test/unit/plugins/providers/virtualbox/driver/version_5_0_test.rb +++ b/test/unit/plugins/providers/virtualbox/driver/version_5_0_test.rb @@ -79,4 +79,57 @@ describe VagrantPlugins::ProviderVirtualBox::Driver::Version_5_0 do end end end + + describe "#ssh_port" do + let(:forwards) { + [[1, "ssh", 2222, 22, "127.0.0.1"], + [1, "ssh", 8080, 80, ""]] + } + + before { allow(subject).to receive(:read_forwarded_ports).and_return(forwards) } + + it "should return the host port" do + expect(subject.ssh_port(22)).to eq(2222) + end + + context "when multiple matches are available" do + let(:forwards) { + [[1, "ssh", 2222, 22, "127.0.0.1"], + [1, "", 2221, 22, ""]] + } + + it "should choose localhost port forward" do + expect(subject.ssh_port(22)).to eq(2222) + end + + context "when multiple named matches are available" do + let(:forwards) { + [[1, "ssh", 2222, 22, "127.0.0.1"], + [1, "SSH", 2221, 22, "127.0.0.1"]] + } + + it "should choose lowercased name forward" do + expect(subject.ssh_port(22)).to eq(2222) + end + end + end + + context "when only ports are defined" do + let(:forwards) { + [[1, "", 2222, 22, ""]] + } + + it "should return the host port" do + expect(subject.ssh_port(22)).to eq(2222) + end + end + + context "when no matches are available" do + let(:forwards) { [] } + + it "should return nil" do + expect(subject.ssh_port(22)).to be_nil + end + end + end end