Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/linux_admin/distro.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ def self.ubuntu
@ubuntu ||= Distro.new(:ubuntu, nil, ['ubuntu'], LinuxAdmin::Deb)
end

def self.mac
@mac ||= Distro.new(:mac, "/etc/mach_init.d")
end

def self.all
@distros ||= [rhel, fedora, ubuntu, generic]
@distros ||= [rhel, fedora, ubuntu, mac, generic]
end

def self.local
Expand Down
21 changes: 15 additions & 6 deletions lib/linux_admin/network_interface.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def self.dist_class(clear_cache = false)
@dist_class ||= begin
if [Distros.rhel, Distros.fedora].include?(Distros.local)
NetworkInterfaceRH
elsif Distros.mac == Distros.local
NetworkInterfaceMac
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this can all be:

case(Distros.local)
when Distros.rhel, Distros.fedora
  NetworkInterfaceRH
when Distros.mac
  NetworkInterfaceMac
else
  NetworkInterfaceGeneric
end

I think it's nicer than the array include followed by ==

else
NetworkInterfaceGeneric
end
Expand Down Expand Up @@ -45,19 +47,16 @@ def initialize(interface)
# @raise [NetworkInterfaceError] if network information cannot be retrieved
def reload
@network_conf = {}
return false unless (ip_output = ip_show)
return unless (ip_output = ip_show)

parse_ip4(ip_output)
parse_ip6(ip_output, :global)
parse_ip6(ip_output, :link)

@network_conf[:mac] = parse_ip_output(ip_output, %r{link/ether}, 1)

ip_route_res = run!(cmd("ip"), :params => ["route"])
@network_conf[:gateway] = parse_ip_output(ip_route_res.output, /^default/, 2) if ip_route_res.success?
true
rescue AwesomeSpawn::CommandResultError => e
raise NetworkInterfaceError.new(e.message, e.result)
@network_conf[:gateway] = parse_ip_output(ip_route, /^default/, 2)
self
end

# Retrieve the IPv4 address assigned to the interface
Expand Down Expand Up @@ -154,6 +153,16 @@ def ip_show
raise NetworkInterfaceError.new(e.message, e.result)
end

# Runs the command `ip route`
#
# @return [String] The command output
# @raise [NetworkInterfaceError] if the command fails
def ip_route
run!(cmd("ip"), :params => ["route"]).output
rescue AwesomeSpawn::CommandResultError => e
raise NetworkInterfaceError.new(e.message, e.result)
end

# Parses the IPv4 information from the output of `ip addr show <device>`
#
# @param ip_output [String] The command output
Expand Down
35 changes: 35 additions & 0 deletions lib/linux_admin/network_interface/network_interface_mac.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require 'socket'

module LinuxAdmin
class NetworkInterfaceMac < NetworkInterface
# Determine the ip address of a ipv4 (non loopback) interface
# NOTE: currently ignores the interface name
#
# @return [String] The command output
# @raise [NetworkInterfaceError] if the command fails
def ip_show
socket = Socket.ip_address_list.detect { |intf| intf.ipv4? && !intf.ipv4_loopback? }
if socket
socket.ip_address
else
raise NetworkInterfaceError.new("could not find ipv4 interface", 4)
end
end

# Determine the Runs the command `ip route`
#
# @return [String] The command output
# @raise [NetworkInterfaceError] if the command fails
def ip_route
gateway = run!(cmd("route"), :params => %w(-n get default)).output
.split("\n").detect { |l| l =~ /gateway/ }.split(":").last.strip
"default via #{gateway} dev #{@interface}"
rescue AwesomeSpawn::CommandResultError => e
raise NetworkInterfaceError.new(e.message, e.result)
end

def parse_conf
# currently a noop
end
end
end
4 changes: 3 additions & 1 deletion lib/linux_admin/time_date.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ class TimeDate
TimeCommandError = Class.new(StandardError)

def self.system_timezone_detailed
result = run(cmd(COMMAND), :params => ["status"])
result = run!(cmd(COMMAND), :params => ["status"])
result.output.split("\n").each do |l|
return l.split(':')[1].strip if l =~ /Time.*zone/
end
rescue AwesomeSpawn::CommandResultError, AwesomeSpawn::NoSuchFileError
Time.now.zone
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't the same result as what we would get from timedatectl.
I'm not sure if that matters, but I don't know of a good way to convert between the America/New_York style and EST

end

def self.system_timezone
Expand Down
22 changes: 14 additions & 8 deletions spec/distro_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,29 @@

context "/etc/redhat-release exists" do
it "returns Distros.rhel" do
exists("/etc/fedora-release" => false, "/etc/redhat-release" => true)
exists("/etc/fedora-release" => false, "/etc/redhat-release" => true, "/etc/mach_init.d" => false)
expect(subject).to eq(LinuxAdmin::Distros.rhel)
end
end

context "/etc/fedora-release exists" do
it "returns Distros.fedora" do
exists("/etc/fedora-release" => true, "/etc/redhat-release" => false)
exists("/etc/fedora-release" => true, "/etc/redhat-release" => false, "/etc/mach_init.d" => false)
expect(subject).to eq(LinuxAdmin::Distros.fedora)
end
end
end

it "returns Distros.generic" do
etc_issue_contains('')
exists("/etc/fedora-release" => false, "/etc/redhat-release" => false)
expect(subject).to eq(LinuxAdmin::Distros.generic)
context "/etc/mach_init.d exists" do
it "returns Distros.mac" do
exists("/etc/fedora-release" => false, "/etc/redhat-release" => false, "/etc/mach_init.d" => true)
expect(subject).to eq(LinuxAdmin::Distros.mac)
end
end

it "returns Distros.generic" do
exists("/etc/fedora-release" => false, "/etc/redhat-release" => false, "/etc/mach_init.d" => false)
expect(subject).to eq(LinuxAdmin::Distros.generic)
end
end
end

Expand All @@ -63,7 +69,7 @@
LinuxAdmin::Distros.local.info 'ruby'
end

it "dispatches to ubuntu lookup mechanism" do
it "dispatches to generic lookup mechanism" do
stub_distro(LinuxAdmin::Distros.generic)
expect { LinuxAdmin::Distros.local.info 'ruby' }.not_to raise_error
end
Expand Down
17 changes: 17 additions & 0 deletions spec/network_interface/network_interface_mac_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
describe LinuxAdmin::NetworkInterfaceMac do
it "raises exception if none found" do
expect(Socket).to receive(:ip_address_list).and_return([])
expect { described_class.new("eth0") }.to raise_error(LinuxAdmin::NetworkInterfaceError)
end

it "returns the ip of the first ipv4 non loopback device" do
expect(Socket).to receive(:ip_address_list).at_least(:once).and_return([
double(:ipv4? => false, :ipv4_loopback? => false, :ip_address => "::1"),
double(:ipv4? => true, :ipv4_loopback? => true, :ip_address => "127.0.0.1"),
double(:ipv4? => true, :ipv4_loopback? => false, :ip_address => "192.168.10.10"),
])
expect_any_instance_of(described_class).to receive(:ip_route).and_return("1921.68.1.1")
ip = described_class.new("eth0")
expect(ip.ip_show).to eq("192.168.10.10")
end
end
22 changes: 22 additions & 0 deletions spec/network_interface_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,28 @@
end
end

context "on mac" do
subject do
allow_any_instance_of(LinuxAdmin::NetworkInterfaceMac).to receive(:ip_show).and_return(nil)
allow(LinuxAdmin::Distros).to receive(:local).and_return(LinuxAdmin::Distros.mac)
described_class.dist_class(true)
described_class.new("eth0")
end

describe ".dist_class" do
it "returns NetworkInterfaceMac" do
allow(LinuxAdmin::Distros).to receive(:local).and_return(LinuxAdmin::Distros.mac)
expect(described_class.dist_class(true)).to eq(LinuxAdmin::NetworkInterfaceMac)
end
end

describe ".new" do
it "creates a NetworkInterfaceMac instance" do
expect(subject).to be_an_instance_of(LinuxAdmin::NetworkInterfaceMac)
end
end
end

context "on other linux systems" do
subject do
allow_any_instance_of(described_class).to receive(:ip_show).and_return(nil)
Expand Down