FYI, I have a half-completed merge of this into our codebase sitting
around at the moment, but am tied up with other distractions (and
illness) that mean I probably won't land it for at least 48 hours.  If
anyone else wants to take over you probably won't miss much compared
to just taking the patch directly.

I had some infrastructure for more tests, such as adding the ifconfig
outputs as fixtures, but no actual test code to use them, plus the
patch in place.

Regards,
    Daniel

On Mon, Feb 7, 2011 at 13:12, Paul Berry <[email protected]> wrote:
> FYI, this patch is associated with ticket #2270
> (http://projects.puppetlabs.com/issues/2270)
>
> On Sat, Feb 5, 2011 at 7:16 AM, Cody Herriges <[email protected]>
> wrote:
>>
>>  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.
>>
>
> --
> 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.
>



-- 
⎋ Puppet Labs Developer – http://puppetlabs.com
✉ Daniel Pittman <[email protected]>
✆ Contact me via gtalk, email, or phone: +1 (877) 575-9775
♲ Made with 100 percent post-consumer electrons

-- 
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