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