Skip to content

Commit

Permalink
(#15001) Add spec examples for ipaddress fact
Browse files Browse the repository at this point in the history
Without this patch we don't have an example behaviors for the ipaddress
fact.  This patch addresses the problem by adding two examples for the
facts parsing the output of ifconfig.  These examples slightly refactor
the ipaddress fact confined to Linux in order to take advantage of the
stubbed method returning the output of the ifconfig command.

Fixture data for ifconfig output is included for Ubuntu 12.04 and Fedora
17.  The notable difference with Fedora 17 is that Net Tools 1.60
removes the "addr" substring from the interface description.
  • Loading branch information
Jeff McCune committed Dec 18, 2012
1 parent ae34893 commit 0e514b8
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 12 deletions.
19 changes: 7 additions & 12 deletions lib/facter/ipaddress.rb
Expand Up @@ -22,23 +22,18 @@
# checking this is a useful IP address.
#

require 'facter/util/ip'

Facter.add(:ipaddress) do
confine :kernel => :linux
setcode do
ip = nil
output = %x{/sbin/ifconfig 2>/dev/null}

output.split(/^\S/).each { |str|
if str =~ /inet (?:addr:)?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
tmp = $1
unless tmp =~ /^127\./
ip = tmp
break
end
if output = Facter::Util::IP.get_ifconfig
regexp = /inet (?:addr:)?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
if match = regexp.match(output)
match[1] unless /^127/.match(match[1])
end
}

ip
end
end
end

Expand Down
8 changes: 8 additions & 0 deletions lib/facter/util/ip.rb
Expand Up @@ -96,6 +96,14 @@ def self.get_all_interface_output
output
end

##
# get_ifconfig simply delegates to the ifconfig command.
#
# @return [String] the output of `/sbin/ifconfig 2>/dev/null` or nil
def self.get_ifconfig
Facter::Util::Resolution.exec("/sbin/ifconfig 2>/dev/null")
end

##
# hpux_netstat_in is a delegate method that allows us to stub netstat -in
# without stubbing exec.
Expand Down
19 changes: 19 additions & 0 deletions spec/fixtures/unit/ipaddress/ifconfig_net_tools_1.60.txt
@@ -0,0 +1,19 @@
em1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 131.252.209.153 netmask 255.255.255.0 broadcast 192.168.76.255
inet6 2610:10:20:209:212:3fff:febe:2201 prefixlen 128 scopeid 0x0<global>
inet6 fe80::221:ccff:fe4b:297d prefixlen 64 scopeid 0x20<link>
ether 00:21:cc:4b:29:7d txqueuelen 1000 (Ethernet)
RX packets 27222144 bytes 31247414760 (29.1 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 10259038 bytes 7784519352 (7.2 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 20 memory 0xd2600000-d2620000

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 16436
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 0 (Local Loopback)
RX packets 257371 bytes 37104110 (35.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 257371 bytes 37104110 (35.3 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
16 changes: 16 additions & 0 deletions spec/fixtures/unit/ipaddress/ifconfig_ubuntu_1204.txt
@@ -0,0 +1,16 @@
eth0 Link encap:Ethernet HWaddr 42:01:0a:57:50:6e
inet addr:10.87.80.110 Bcast:10.87.80.110 Mask:255.255.255.255
UP BROADCAST RUNNING MULTICAST MTU:1460 Metric:1
RX packets:1609444 errors:0 dropped:0 overruns:0 frame:0
TX packets:1479569 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:673812693 (673.8 MB) TX bytes:221186872 (221.1 MB)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:5435415 errors:0 dropped:0 overruns:0 frame:0
TX packets:5435415 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:734540224 (734.5 MB) TX bytes:734540224 (734.5 MB)

32 changes: 32 additions & 0 deletions spec/unit/ipaddress_spec.rb
@@ -0,0 +1,32 @@
#! /usr/bin/env ruby

require 'spec_helper'
require 'facter/util/ip'

shared_examples_for "ifconfig output" do |platform, address, fixture|
it "correctly on #{platform}" do
Facter::Util::IP.stubs(:get_ifconfig).returns(my_fixture_read(fixture))
subject.value.should == address
end
end

RSpec.configure do |config|
config.alias_it_should_behave_like_to :example_behavior_for, "parses"
end

describe "The ipaddress fact" do
subject do
Facter.collection.loader.load(:ipaddress)
Facter.fact(:ipaddress)
end
context "on Linux" do
before :each do
Facter.fact(:kernel).stubs(:value).returns("Linux")
end

example_behavior_for "ifconfig output",
"Ubuntu 12.04", "10.87.80.110", "ifconfig_ubuntu_1204.txt"
example_behavior_for "ifconfig output",
"Fedora 17", "131.252.209.153", "ifconfig_net_tools_1.60.txt"
end
end

2 comments on commit 0e514b8

@jgn
Copy link

@jgn jgn commented on 0e514b8 Mar 15, 2013

Choose a reason for hiding this comment

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

I've been trying to isolate a problem on one of my systems, and the refactoring here for linux seems wrong.

Here is the documentation (at http://docs.puppetlabs.com/facter/1.6/core_facts.html#ipaddress):

On the Unixes does an ifconfig, and returns the first non 127.0.0.0/8 subnetted IP it finds.

Here is an example of the output from my ifconfig command:

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:9031461 errors:0 dropped:0 overruns:0 frame:0
          TX packets:9031461 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3205490447 (2.9 GiB)  TX bytes:3205490447 (2.9 GiB)

venet0    Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:127.0.0.1  P-t-P:127.0.0.1  Bcast:0.0.0.0  Mask:255.255.255.255
          UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1
          RX packets:38161277 errors:0 dropped:0 overruns:0 frame:0
          TX packets:24601924 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3847964603 (3.5 GiB)  TX bytes:5770630041 (5.3 GiB)

venet0:1  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:10.0.222.20  P-t-P:10.0.222.20  Bcast:10.0.222.20  Mask:255.255.255.255
          UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1

Notice that the value of ipaddress that is supposed to be captured is: 10.0.222.20

Now look at the refactoring of the ipaddress fact for Linux.

BEFORE, it split the output and checked every line for a regexp match; and then ignored matches for the loop back address (127...).

AFTER, there is no split.

This means that ONLY the first match would EVER be considered. There is no way that the refactored code can get to the inet address on venet0:1 (in my example).

Here's an example irb session following the code:

irb(main):001:0> output = `ifconfig`; nil
irb(main):002:0> regexp = /inet (?:addr:)?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
irb(main):003:0> match = regexp.match(output)
=> #<MatchData "inet addr:127.0.0.1" 1:"127.0.0.1">
irb(main):004:0> match[1] unless /^127/.match(match[1])
=> nil

You will see this failure more clearly if you add another fixture for ipconfig output (for example, used what I've pasted in above).

In your fixture, the very first interface has a non-127.0.0.1 address. Here's the fixture:

eth0      Link encap:Ethernet  HWaddr 42:01:0a:57:50:6e
          inet addr:10.87.80.110  Bcast:10.87.80.110  Mask:255.255.255.255
          UP BROADCAST RUNNING MULTICAST  MTU:1460  Metric:1
          RX packets:1609444 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1479569 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:673812693 (673.8 MB)  TX bytes:221186872 (221.1 MB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:5435415 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5435415 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:734540224 (734.5 MB)  TX bytes:734540224 (734.5 MB)

@jeffmccune
Copy link

Choose a reason for hiding this comment

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

@jgn Thanks for taking the time to troubleshoot this issue. Would you mind submitting a pull request that fixes this problem for you? If not, could you file an issue at http://projects.puppetlabs.com/projects/facter and add me as a watcher?

Thanks,
-Jeff

Please sign in to comment.