describe LinuxAdmin::NetworkInterface do context "on redhat systems" do subject(:subj_success) do allow_any_instance_of(described_class).to receive(:ip_show).and_return(nil) allow(LinuxAdmin::Distros).to receive(:local).and_return(LinuxAdmin::Distros.rhel) described_class.dist_class(true) allow(File).to receive(:exist?).and_return(true) allow(File).to receive(:foreach).and_return("") described_class.new("eth0") end subject(:subj_failure) do allow_any_instance_of(described_class).to receive(:ip_show).and_return(nil) allow(LinuxAdmin::Distros).to receive(:local).and_return(LinuxAdmin::Distros.rhel) described_class.dist_class(true) allow(File).to receive(:exist?).and_return(false) described_class.new("eth0") end describe ".dist_class" do it "returns NetworkInterfaceRH" do allow(LinuxAdmin::Distros).to receive(:local).and_return(LinuxAdmin::Distros.rhel) expect(described_class.dist_class(true)).to eq(LinuxAdmin::NetworkInterfaceRH) end end describe ".new" do it "creates a NetworkInterfaceRH instance" do expect(subj_success).to be_an_instance_of(LinuxAdmin::NetworkInterfaceRH) end it "creates a NetworkInterfaceGeneric instance if the config file does not exist" do expect(subj_failure).to be_an_instance_of(LinuxAdmin::NetworkInterfaceGeneric) end end end context "on other linux systems" do subject do allow_any_instance_of(described_class).to receive(:ip_show).and_return(nil) allow(LinuxAdmin::Distros).to receive(:local).and_return(LinuxAdmin::Distros.generic) described_class.dist_class(true) described_class.new("eth0") end describe ".dist_class" do it "returns NetworkInterfaceGeneric" do allow(LinuxAdmin::Distros).to receive(:local).and_return(LinuxAdmin::Distros.generic) expect(described_class.dist_class(true)).to eq(LinuxAdmin::NetworkInterfaceGeneric) end end describe ".new" do it "creates a NetworkInterfaceGeneric instance" do expect(subject).to be_an_instance_of(LinuxAdmin::NetworkInterfaceGeneric) end end end context "on all systems" do IP_SHOW_ARGS = [ LinuxAdmin::Common.cmd("ip"), :params => %w(addr show eth0) ] IP_ROUTE_ARGS = [ LinuxAdmin::Common.cmd("ip"), :params => ['-4', 'route'] ] IP6_ROUTE_ARGS = [ LinuxAdmin::Common.cmd("ip"), :params => ['-6', 'route'] ] IFUP_ARGS = [ LinuxAdmin::Common.cmd("ifup"), :params => ["eth0"] ] IFDOWN_ARGS = [ LinuxAdmin::Common.cmd("ifdown"), :params => ["eth0"] ] IP_ADDR_OUT = <<-IP_OUT 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:ed:0e:8b brd ff:ff:ff:ff:ff:ff inet 192.168.1.9/24 brd 192.168.1.255 scope global dynamic eth0 valid_lft 1297sec preferred_lft 1297sec inet6 fe80::20c:29ff:feed:e8b/64 scope link valid_lft forever preferred_lft forever inet6 fd12:3456:789a:1::1/96 scope global valid_lft forever preferred_lft forever IP_OUT IP6_ADDR_OUT = <<-IP_OUT 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:ed:0e:8b brd ff:ff:ff:ff:ff:ff inet6 fe80::20c:29ff:feed:e8b/64 scope link valid_lft forever preferred_lft forever inet6 fd12:3456:789a:1::1/96 scope global valid_lft forever preferred_lft forever IP_OUT IP_ROUTE_OUT = <<-IP_OUT default via 192.168.1.1 dev eth0 proto static metric 100 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.9 metric 100 IP_OUT IP6_ROUTE_OUT = <<-IP_OUT default via d:e:a:d:b:e:e:f dev eth0 proto static metric 100 fc00:dead:beef:a::/64 dev virbr1 proto kernel metric 256 linkdown pref medium fe80::/64 dev eth0 proto kernel scope link metric 100 IP_OUT IP_NONE_ADDR_OUT = <<-IP_OUT.freeze 2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr1 state DOWN group default qlen 1000 link/ether 52:54:00:ce:b4:f4 brd ff:ff:ff:ff:ff:ff IP_OUT subject(:subj) do allow(LinuxAdmin::Distros).to receive(:local).and_return(LinuxAdmin::Distros.generic) described_class.dist_class(true) allow(AwesomeSpawn).to receive(:run!).with(*IP_SHOW_ARGS).and_return(result(IP_ADDR_OUT, 0)) allow(AwesomeSpawn).to receive(:run!).with(*IP_ROUTE_ARGS).and_return(result(IP_ROUTE_OUT, 0)) allow(AwesomeSpawn).to receive(:run!).with(*IP6_ROUTE_ARGS).and_return(result(IP6_ROUTE_OUT, 0)) described_class.new("eth0") end subject(:subj6) do allow(LinuxAdmin::Distros).to receive(:local).and_return(LinuxAdmin::Distros.generic) described_class.dist_class(true) allow(AwesomeSpawn).to receive(:run!).with(*IP_SHOW_ARGS).and_return(result(IP6_ADDR_OUT, 0)) allow(AwesomeSpawn).to receive(:run!).with(*IP_ROUTE_ARGS).and_return(result(IP_ROUTE_OUT, 0)) allow(AwesomeSpawn).to receive(:run!).with(*IP6_ROUTE_ARGS).and_return(result(IP6_ROUTE_OUT, 0)) described_class.new("eth0") end subject(:subj_no_net) do allow(LinuxAdmin::Distros).to receive(:local).and_return(LinuxAdmin::Distros.generic) described_class.dist_class(true) allow(AwesomeSpawn).to receive(:run!).with(*IP_SHOW_ARGS).and_return(result(IP_NONE_ADDR_OUT, 0)) allow(AwesomeSpawn).to receive(:run!).with(*IP_ROUTE_ARGS).and_return(result(IP_ROUTE_OUT, 0)) allow(AwesomeSpawn).to receive(:run!).with(*IP6_ROUTE_ARGS).and_return(result(IP6_ROUTE_OUT, 0)) described_class.new("eth0") end def result(output, exit_status) AwesomeSpawn::CommandResult.new("", output, "", exit_status) end describe "#reload" do it "raises when ip addr show fails" do subj awesome_error = AwesomeSpawn::CommandResultError.new("", nil) allow(AwesomeSpawn).to receive(:run!).with(*IP_SHOW_ARGS).and_raise(awesome_error) expect { subj.reload }.to raise_error(LinuxAdmin::NetworkInterfaceError) end it "raises when ip route fails" do subj awesome_error = AwesomeSpawn::CommandResultError.new("", nil) allow(AwesomeSpawn).to receive(:run!).with(*IP_SHOW_ARGS).and_return(result(IP_ADDR_OUT, 0)) allow(AwesomeSpawn).to receive(:run!).with(*IP_ROUTE_ARGS).and_raise(awesome_error) allow(AwesomeSpawn).to receive(:run!).with(*IP6_ROUTE_ARGS).and_raise(awesome_error) expect { subj.reload }.to raise_error(LinuxAdmin::NetworkInterfaceError) end it "doesn't blow up when given only ipv6 addresses" do subj6 allow(AwesomeSpawn).to receive(:run!).with(*IP_SHOW_ARGS).and_return(result(IP6_ADDR_OUT, 0)) allow(AwesomeSpawn).to receive(:run!).with(*IP_ROUTE_ARGS).and_return(result(IP_ROUTE_OUT, 0)) allow(AwesomeSpawn).to receive(:run!).with(*IP6_ROUTE_ARGS).and_return(result(IP6_ROUTE_OUT, 0)) expect { subj.reload }.to_not raise_error end end describe "#address" do it "returns an address" do expect(subj.address).to eq("192.168.1.9") end end describe "#address6" do it "returns the global address by default" do expect(subj.address6).to eq("fd12:3456:789a:1::1") end it "returns the link local address" do expect(subj.address6(:link)).to eq("fe80::20c:29ff:feed:e8b") end it "raises ArgumentError when given a bad scope" do expect { subj.address6(:garbage) }.to raise_error(ArgumentError) end end describe "#mac_address" do it "returns the correct MAC address" do expect(subj.mac_address).to eq("00:0c:29:ed:0e:8b") end end describe "#netmask" do it "returns the correct netmask" do expect(subj.netmask).to eq("255.255.255.0") end it 'does not blow-up, when no ip assigned' do expect(subj_no_net.netmask).to eq(nil) end end describe "#netmask6" do it "returns the correct global netmask" do expect(subj.netmask6).to eq("ffff:ffff:ffff:ffff:ffff:ffff::") end it "returns the correct link local netmask" do expect(subj.netmask6(:link)).to eq("ffff:ffff:ffff:ffff::") end it "raises ArgumentError when given a bad scope" do expect { subj.netmask6(:garbage) }.to raise_error(ArgumentError) end end describe '#prefix' do it 'returns the correct prefix' do expect(subj.prefix).to eq(24) end end describe '#prefix6' do it 'returns the correct global prefix length' do expect(subj.prefix6).to eq(96) end it 'returns the correct link local prefix length' do expect(subj.prefix6(:link)).to eq(64) end it 'raises ArgumentError when given a bad scope' do expect { subj.prefix6(:garbage) }.to raise_error(ArgumentError) end end describe "#gateway" do it "returns the correct gateway address" do expect(subj.gateway).to eq("192.168.1.1") end end describe '#gateway6' do it 'returns the correct default gateway for IPv6 routing' do expect(subj.gateway6).to eq('d:e:a:d:b:e:e:f') end end describe "#start" do it "returns true on success" do expect(AwesomeSpawn).to receive(:run).with(*IFUP_ARGS).and_return(result("", 0)) expect(subj.start).to be true end it "returns false on failure" do expect(AwesomeSpawn).to receive(:run).with(*IFUP_ARGS).and_return(result("", 1)) expect(subj.start).to be false end end describe "#stop" do it "returns true on success" do expect(AwesomeSpawn).to receive(:run).with(*IFDOWN_ARGS).and_return(result("", 0)) expect(subj.stop).to be true end it "returns false on failure" do expect(AwesomeSpawn).to receive(:run).with(*IFDOWN_ARGS).and_return(result("", 1)) expect(subj.stop).to be false end end end end