The following patch provides an ipaddress6 fact to report IP addresses
  that follow the IPv6 standard, RFC 2460.  Basic code structure was modeled
  after the already current ipaddress facts available in facter core and are
  not intended to make large behaviour changes to the way facter functions when
  discovering IP addresses.  Intial support is only for FreeBSD, Linux, SunOS,
  and Darwin.  The only platforms I had available for testing at the time, more
  support coming soon.

  Another minor change in the patch is a replacement of %x with the
  Facter::Util::Resolution.exec method for ease of rspec mocking.
---
 lib/facter/interfaces.rb |    2 +-
 lib/facter/ipaddress6.rb |  130 ++++++++++++++++++++++++++++++++++++++++++++++
 lib/facter/util/ip.rb    |   19 ++++---
 3 files changed, 142 insertions(+), 9 deletions(-)
 create mode 100644 lib/facter/ipaddress6.rb

diff --git a/lib/facter/interfaces.rb b/lib/facter/interfaces.rb
index 1239215..4fbaef1 100644
--- a/lib/facter/interfaces.rb
+++ b/lib/facter/interfaces.rb
@@ -22,7 +22,7 @@ Facter::Util::IP.get_interfaces.each do |interface|
     # Make a fact for each detail of each interface.  Yay.
     #   There's no point in confining these facts, since we wouldn't be able 
to create
     # them if we weren't running on a supported platform.
-    %w{ipaddress macaddress netmask}.each do |label|
+    %w{ipaddress ipaddress6 macaddress netmask}.each do |label|
         Facter.add(label + "_" + Facter::Util::IP.alphafy(interface)) do
             setcode do
                 Facter::Util::IP.get_interface_value(interface, label)
diff --git a/lib/facter/ipaddress6.rb b/lib/facter/ipaddress6.rb
new file mode 100644
index 0000000..30d0e74
--- /dev/null
+++ b/lib/facter/ipaddress6.rb
@@ -0,0 +1,130 @@
+# Cody Herriges <[email protected]>
+#
+# Used the ipaddress fact that is already part of
+# Facter as a template.
+
+
+# Uses ruby's own resolv class which queries DNS and /etc/hosts.
+# The closest thing to a default/primary IPv6 addresses is
+# assumed to be the AAAA that you have published via DNS or
+# an /etc/host entry.
+Facter.add(:ipaddress6, :timeout => 2) do
+  setcode do
+    require 'resolv'
+
+    begin
+      if fqdn = Facter.value(:fqdn)
+        ip = nil
+        Resolv.getaddresses(fqdn).each { |str|
+          str = str.to_s
+          if str =~ /(?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4}/ and str != 
"::1"
+            ip = str
+          end
+        }
+
+      ip
+
+      else
+        nil
+      end
+      rescue Resolv::ResolvError
+        nil
+      rescue NoMethodError # i think this is a bug in resolv.rb?
+        nil
+    end
+  end
+end
+
+# Uses the OS' host command to do a DNS lookup.
+Facter.add(:ipaddress6, :timeout => 2) do
+  setcode do
+  if fqdn = Facter.value(:fqdn)
+    ip = nil
+    host = nil
+    if host = Facter::Util::Resolution.exec("host -t AAAA #{fqdn}")
+      host.scan(/((?>[0-9,a-f,A-F]{0,4}\:{1,2})+[0-9,a-f,A-F]{0,4}&)/).each { 
|str|
+      str = str.to_s
+      unless str =~ /fe80.*/ or str == "::1"
+       ip = str
+      end
+    }
+    else
+      nil
+    end
+    ip
+  else
+    nil
+  end
+  end
+end
+
+# OS dependant code that parses the output of various networking
+# tools and currently not very intelligent. Returns the first
+# non-loopback and non-linklocal address found in the ouput unless
+# a default route can be mapped to a routeable interface. Guessing
+# an interface is currently only possible with BSD type systems
+# to many assumptions have to be made on other platforms to make
+# this work with the current code. Most code ported or modeled
+# after the ipaddress fact for the sake of similar functionality
+# and familiar mechanics.
+Facter.add(:ipaddress6) do
+  confine :kernel => :linux
+  setcode do
+    ip = nil
+    output = Facter::Util::Resolution.exec("/sbin/ifconfig")
+
+    output.scan(/inet6 addr: 
((?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/).each { |str|
+      str = str.to_s
+      unless str =~ /fe80.*/ or str == "::1"
+        ip = str
+      end
+    }
+
+    ip
+
+  end
+end
+
+Facter.add(:ipaddress6) do
+  confine :kernel => %w{SunOS}
+  setcode do
+    output = Facter::Util::Resolution.exec("/usr/sbin/ifconfig -a")
+    ip = nil
+
+    output.scan(/inet6 ((?>[0-9,a-f,A-F]*\:{0,2})+[0-9,a-f,A-F]{0,4})/).each { 
|str|
+      str = str.to_s
+      unless str =~ /fe80.*/ or str == "::1"
+        ip = str
+      end
+    }
+
+    ip
+
+  end
+end
+
+Facter.add(:ipaddress6) do
+  confine :kernel => %w{Darwin FreeBSD OpenBSD}
+  setcode do
+    interout = Facter::Util::Resolution.exec("/usr/sbin/netstat -rn -f inet6")
+    interface = 
interout.scan(/^default\s+fe80\S+\s+[A-Z]+\s+\d\s+\d+\s+([a-z]+\d)/).to_s
+    if interface != ''
+      output = Facter::Util::Resolution.exec("/sbin/ifconfig #{interface}")
+    else
+      puts "Unable to find a default route interface, using first non-loopback 
address"
+      output = Facter::Util::Resolution.exec("/sbin/ifconfig -a")
+    end
+    ip = nil
+
+    output.scan(/inet6 ((?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/).each { 
|str|
+      str = str.to_s
+      unless str =~ /fe80.*/ or str == "::1"
+        ip = str
+      end
+      }
+
+      ip
+
+  end
+end
+
diff --git a/lib/facter/util/ip.rb b/lib/facter/util/ip.rb
index 366303c..50fae51 100644
--- a/lib/facter/util/ip.rb
+++ b/lib/facter/util/ip.rb
@@ -6,17 +6,20 @@ module Facter::Util::IP
     REGEX_MAP = {
         :linux => {
             :ipaddress  => /inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/,
+            :ipaddress6 => /inet6 addr: 
((?![fe80|::1])(?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/,
             :macaddress => 
/(?:ether|HWaddr)\s+(\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2}:\w{1,2})/,
             :netmask    => /Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/
         },
         :bsd   => {
             :aliases    => [:openbsd, :netbsd, :freebsd, :darwin],
             :ipaddress  => /inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/,
+            :ipaddress6 => /inet6 
((?![fe80|::1])(?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/,
             :macaddress => 
/(?:ether|lladdr)\s+(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w)/,
             :netmask    => /netmask\s+0x(\w{8})/
         },
         :sunos => {
             :ipaddress  => /inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/,
+            :ipaddress6 => /inet6 
((?![fe80|::1])(?>[0-9,a-f,A-F]*\:{1,2})+[0-9,a-f,A-F]{0,4})/,
             :macaddress => 
/(?:ether|lladdr)\s+(\w?\w:\w?\w:\w?\w:\w?\w:\w?\w:\w?\w)/,
             :netmask    => /netmask\s+(\w{8})/
         },
@@ -62,11 +65,11 @@ module Facter::Util::IP
     def self.get_all_interface_output
         case Facter.value(:kernel)
         when 'Linux', 'OpenBSD', 'NetBSD', 'FreeBSD', 'Darwin'
-            output = %x{/sbin/ifconfig -a}
+            output = Facter::Util::Resolution.exec("/sbin/ifconfig -a")
         when 'SunOS'
-            output = %x{/usr/sbin/ifconfig -a}
+            output = Facter::Util::Resolution.exec("/usr/sbin/ifconfig -a")
         when 'HP-UX'
-            output = %x{/bin/netstat -i}
+            output = Facter::Util::Resolution.exec("/bin/netstat -i")
         end
         output
     end
@@ -75,13 +78,13 @@ module Facter::Util::IP
         output = ""
         case Facter.value(:kernel)
         when 'Linux', 'OpenBSD', 'NetBSD', 'FreeBSD', 'Darwin'
-            output = %x{/sbin/ifconfig #{interface}}
+            output = Facter::Util::Resolution.exec("/sbin/ifconfig 
#{interface}")
         when 'SunOS'
-            output = %x{/usr/sbin/ifconfig #{interface}}
+            output = Facter::Util::Resolution.exec("/usr/sbin/ifconfig 
#{interface}")
         when 'HP-UX'
            mac = ""
-           ifc = %x{/usr/sbin/ifconfig #{interface}}
-           %x{/usr/sbin/lanscan}.scan(/(\dx\S+).*UP\s+(\w+\d+)/).each {|i| mac 
= i[0] if i.include?(interface) }
+           ifc = Facter::Util::Resolution.exec("/usr/sbin/ifconfig 
#{interface}")
+           
Facter::Util::Resolution.exec("/usr/sbin/lanscan").scan(/(\dx\S+).*UP\s+(\w+\d+)/).each
 {|i| mac = i[0] if i.include?(interface) }
            mac = mac.sub(/0x(\S+)/,'\1').scan(/../).join(":")
            output = ifc + "\n" + mac
         end
@@ -105,7 +108,7 @@ module Facter::Util::IP
             return nil
         end
         regex = /SLAVE[,>].* (bond[0-9]+)/
-            ethbond = regex.match(%x{/sbin/ip link show #{interface}})
+            ethbond = regex.match(Facter::Util::Resolution.exec("/sbin/ip link 
show #{interface}"))
         if ethbond
             device = ethbond[1]
         else
-- 
1.7.4

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to