Skip to content

Commit

Permalink
guests/linux: Properly sort interface name types
Browse files Browse the repository at this point in the history
Add failing networking interface list sorting test with example
provided by #7883. Update sorting logic to properly handle different
types and differing array lengths.

Fixes #7883
  • Loading branch information
chrisroberts committed Oct 10, 2016
1 parent e2b18fc commit a897028
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
20 changes: 19 additions & 1 deletion plugins/guests/linux/cap/network_interfaces.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ def self.network_interfaces(machine, path = "/sbin/ip")
@@logger.debug("Unsorted list: #{ifaces.inspect}")
# Break out integers from strings and sort the arrays to provide
# a natural sort for the interface names
# NOTE: Devices named with a hex value suffix will _not_ be sorted
# as expected. This is generally seen with veth* devices, and proper ordering
# is currently not required
ifaces = ifaces.map do |iface|
iface.scan(/(.+?)(\d+)/).flatten.map do |iface_part|
if iface_part.to_i.to_s == iface_part
Expand All @@ -31,7 +34,22 @@ def self.network_interfaces(machine, path = "/sbin/ip")
iface_part
end
end
end.sort.map(&:join)
end
ifaces = ifaces.sort do |lhs, rhs|
result = 0
slice_length = [rhs.size, lhs.size].min
slice_length.times do |idx|
if(lhs[idx].is_a?(rhs[idx].class))
result = lhs[idx] <=> rhs[idx]
elsif(lhs[idx].is_a?(String))
result = 1
else
result = -1
end
break if result != 0
end
result
end.map(&:join)
@@logger.debug("Sorted list: #{ifaces.inspect}")
# Extract ethernet devices and place at start of list
resorted_ifaces = []
Expand Down
10 changes: 8 additions & 2 deletions test/unit/plugins/guests/linux/cap/network_interfaces_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,15 @@
end

it "does not include ethernet devices aliases within prefix device listing" do
expect(comm).to receive(:sudo).and_yield(:stdout, "eth1\neth2\ndocker0\nbridge0\neth0\neth0:0")
expect(comm).to receive(:sudo).and_yield(:stdout, "eth1\neth2\ndocker0\nbridge0\neth0\ndocker1\neth0:0")
result = cap.network_interfaces(machine)
expect(result).to eq(["eth0", "eth1", "eth2", "bridge0", "docker0", "eth0:0"])
expect(result).to eq(["eth0", "eth1", "eth2", "bridge0", "docker0", "docker1", "eth0:0"])
end

it "properly sorts non-consistent device name formats" do
expect(comm).to receive(:sudo).and_yield(:stdout, "eth0\neth1\ndocker0\nveth437f7f9\nveth06b3e44\nveth8bb7081")
result = cap.network_interfaces(machine)
expect(result).to eq(["eth0", "eth1", "docker0", "veth8bb7081", "veth437f7f9", "veth06b3e44"])
end
end
end

0 comments on commit a897028

Please sign in to comment.