From 88593d336164ea421cafe2a7ddcf3ce379f39a83 Mon Sep 17 00:00:00 2001 From: Adam Grare Date: Thu, 28 Jan 2021 10:56:28 -0500 Subject: [PATCH 1/4] Fix MiqEnvironment.local_ip_address to not prefer loopback `#local_ip_address` currently prefers loopback addresses since it filters out "private" addresses and not "loopback" addresses. IMO we should prefer public, then private, then loopback. --- lib/miq_environment.rb | 12 ++++++++++-- spec/lib/miq_environment_spec.rb | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/miq_environment.rb b/lib/miq_environment.rb index 9dddeb3ef32..56e3756fcb6 100644 --- a/lib/miq_environment.rb +++ b/lib/miq_environment.rb @@ -8,10 +8,18 @@ def self.fully_qualified_domain_name Socket.gethostbyname(Socket.gethostname).first end - # Return the local IP v4 address of the local host, ignoring private addresses. + # Return the local IP v4 address of the local host # def self.local_ip_address - Socket.ip_address_list.detect { |addr| addr.ipv4? && !addr.ipv4_private? }&.ip_address + ipv4_addrs = Socket.ip_address_list.select(&:ipv4?) + + # Prioritize "public" aka non-loopback non-private addresses first, then + # prefer private addresses, then take whatever we can get + local_addr = ipv4_addrs.detect { |ip| !ip.ipv4_loopback? && !ip.ipv4_private? } + local_addr ||= ipv4_addrs.detect { |ip| !ip.ipv4_loopback? } + local_addr ||= ipv4_addrs.first + + local_addr&.ip_address end class Command diff --git a/spec/lib/miq_environment_spec.rb b/spec/lib/miq_environment_spec.rb index 29db0179b57..56b62c6259d 100644 --- a/spec/lib/miq_environment_spec.rb +++ b/spec/lib/miq_environment_spec.rb @@ -15,7 +15,7 @@ end example "local_ip_address" do - expect(described_class.local_ip_address).to eq(`hostname -i`.chomp.split.first) + expect(described_class.local_ip_address).to be_in(Socket.ip_address_list.map(&:ip_address)) end end From 0cc1dde990a02500472ed4d4be7da85d9a3bc67d Mon Sep 17 00:00:00 2001 From: Adam Grare Date: Fri, 29 Jan 2021 10:36:41 -0500 Subject: [PATCH 2/4] Sort the ip addresses to ensure reliable returns --- lib/miq_environment.rb | 2 +- spec/models/miq_server/environment_manager_spec.rb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/miq_environment.rb b/lib/miq_environment.rb index 56e3756fcb6..311cac058f9 100644 --- a/lib/miq_environment.rb +++ b/lib/miq_environment.rb @@ -11,7 +11,7 @@ def self.fully_qualified_domain_name # Return the local IP v4 address of the local host # def self.local_ip_address - ipv4_addrs = Socket.ip_address_list.select(&:ipv4?) + ipv4_addrs = Socket.ip_address_list.select(&:ipv4?).sort_by(&:ip_address) # Prioritize "public" aka non-loopback non-private addresses first, then # prefer private addresses, then take whatever we can get diff --git a/spec/models/miq_server/environment_manager_spec.rb b/spec/models/miq_server/environment_manager_spec.rb index dc30e0f8e8e..61fa23b479a 100644 --- a/spec/models/miq_server/environment_manager_spec.rb +++ b/spec/models/miq_server/environment_manager_spec.rb @@ -2,14 +2,14 @@ RSpec.describe "Server Environment Management" do let(:mac_address) { 'a:1:b:2:c:3:d:4' } - let(:hostname) { Socket.gethostname } - let(:loopback) { '127.0.0.1' } + let(:hostname) { Socket.gethostbyname(Socket.gethostname).first } + let(:ip_address) { Socket.ip_address_list.select(&:ipv4?).sort_by(&:ip_address).detect(&:ipv4_private?)&.ip_address } context ".get_network_information" do it "when in non-production mode" do require "uuidtools" allow(UUIDTools::UUID).to receive(:mac_address).and_return(mac_address) - expect(MiqServer.get_network_information).to eq([loopback, hostname, mac_address]) + expect(MiqServer.get_network_information).to eq([ip_address, hostname, mac_address]) end end From 2b3e5c0ffa629b4a18559cd72b47ae873a95cb39 Mon Sep 17 00:00:00 2001 From: Adam Grare Date: Fri, 29 Jan 2021 10:46:29 -0500 Subject: [PATCH 3/4] Stub Socket.ip_address_list and .gethostbyname --- .../miq_server/environment_manager_spec.rb | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/spec/models/miq_server/environment_manager_spec.rb b/spec/models/miq_server/environment_manager_spec.rb index 61fa23b479a..e2ca6376054 100644 --- a/spec/models/miq_server/environment_manager_spec.rb +++ b/spec/models/miq_server/environment_manager_spec.rb @@ -1,14 +1,20 @@ require 'socket' RSpec.describe "Server Environment Management" do - let(:mac_address) { 'a:1:b:2:c:3:d:4' } - let(:hostname) { Socket.gethostbyname(Socket.gethostname).first } - let(:ip_address) { Socket.ip_address_list.select(&:ipv4?).sort_by(&:ip_address).detect(&:ipv4_private?)&.ip_address } - context ".get_network_information" do - it "when in non-production mode" do + let(:mac_address) { 'a:1:b:2:c:3:d:4' } + let(:hostname) { "localhost.localdomain" } + let(:ip_address) { "10.1.2.3" } + + before do require "uuidtools" allow(UUIDTools::UUID).to receive(:mac_address).and_return(mac_address) + allow(Socket).to receive(:gethostname).and_return("localhost") + allow(Socket).to receive(:gethostbyname).with("localhost").and_return([hostname]) + allow(Socket).to receive(:ip_address_list).and_return([Addrinfo.ip(ip_address)]) + end + + it "when in non-production mode" do expect(MiqServer.get_network_information).to eq([ip_address, hostname, mac_address]) end end From 16f82633a0b858d454b6814a161c65ec57356ca5 Mon Sep 17 00:00:00 2001 From: Adam Grare Date: Fri, 29 Jan 2021 10:56:46 -0500 Subject: [PATCH 4/4] Test the same address is returned --- spec/lib/miq_environment_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/spec/lib/miq_environment_spec.rb b/spec/lib/miq_environment_spec.rb index 56b62c6259d..eccebea7e10 100644 --- a/spec/lib/miq_environment_spec.rb +++ b/spec/lib/miq_environment_spec.rb @@ -17,6 +17,15 @@ example "local_ip_address" do expect(described_class.local_ip_address).to be_in(Socket.ip_address_list.map(&:ip_address)) end + + context "multiple private addresses" do + it "always returns the same address" do + allow(Socket).to receive(:ip_address_list).and_return([Addrinfo.ip("192.168.1.10"), Addrinfo.ip("10.1.2.3")]) + expect(described_class.local_ip_address).to eq("10.1.2.3") + allow(Socket).to receive(:ip_address_list).and_return([Addrinfo.ip("10.1.2.3"), Addrinfo.ip("192.168.1.10")]) + expect(described_class.local_ip_address).to eq("10.1.2.3") + end + end end context "Command" do