On Friday, February 1, 2013 8:16:12 AM UTC-6, Bernhard Schmidt wrote:
>
> --- 
> require 'facter' 
> require 'facter/util/ip' 
>
> if not FileTest.exists?("/usr/sbin/lldpctl") 
>   nil 
> end 
>


That last bit probably doesn't do what you want.  That is to say, it 
evaluates to nil in every case (implicitly when the condition is not 
satisfied), and has no effect on anything else in the fact implementation.  
Perhaps you meant to put the rest of the body in an 'else' clause?  Or, 
reverse the sense of the test and put everything else inside the condition?

 

>
> config = Hash[] 
> output = Facter::Util::Resolution.exec("/usr/sbin/lldpctl -f keyvalue") 
>
> if output == "" 
>   nil 
> end



Again, a not-what-you-intended conditional statement.  In this case, it's 
probably altogether unnecessary.

 

>
> for line in output.split("\n") do 
>   # Drop Multiline 
>   if line =~ /^lldp/ 
>     key, value = line.split('=') 
>     prefix, int, key2 = key.split('.', 3) 
>     if not config.has_key?(int) 
>       config[int] = Hash[] 
>     end 
>     config[int][key2] = value 
>   end 
> end 
>


More idiomatic Ruby might be:

# This hash automatically creates appropriate new
# entries as needed:
config = Hash.new { |h, k| h[k] = Hash.new }

output.lines.grep(/^lldp/).each do |line|
    # note the 'chomp':
    key, value = line.chomp.split('=') 
    prefix, int, key2 = key.split('.', 3) 
    config[int][key2] = value 
end

Other than the "chomp", however, I don't think that will change the results.



> for interface in config.keys do 
>   Facter.add("lldp_neighbor_" + Facter::Util::IP.alphafy(interface)) do 
>     setcode do 
>       device = config[interface].fetch('chassis.name', "") 
>       ifdescr = config[interface].fetch('port.descr', "") 
>       ifalias = config[interface].fetch('port.ifalias', "") 


      if device != "" 
>         if ifalias != "" 
>           device + " " + ifalias 
>         else 
>           device + " "  + ifdescr 
>         end 
>       end 
>     end 
>   end 
> end 
>


More idiomatic:

config.each_pair do | interface, props | 
  Facter.add("lldp_neighbor_" + Facter::Util::IP.alphafy(interface)) do 
    setcode do 
      device = props.fetch('chassis.name', "") 
      if device != ""
        # note: although clean and concise, this is not 100%
        # equivalent to the original if 'port.ifalias' can be present but
        # empty:
        device + ' ' + props.fetch('port.ifalias', props['port.descr']) 
      else
        # default value when device is empty
        'no config'
      end 
    end 
  end 
end

I think that might solve your problem, too.  Here's what I think is 
happening to you: your 'for' loop runs, setting variable 'interface' in 
turn to each key of the 'config' hash.  At each iteration, it creates a 
block of code that Facter will execute (later) to determine the value of 
one fact.  Ruby blocks are closures, so where yours later reference the 
value of 'interface' they are getting the then-current value in the context 
where the block was created.  By that time, that's the value after the 
iteration is done (apparently the last key iterated).

I think the rewritten version will solve that problem because at each 
iteration, the values of the key and (inner) hash are captured as distinct 
local variables ('interface' and 'props'), very much as if the block passed 
to 'each_pair' were an independent function.  This is a Ruby subtlety, so 
you have chosen a good example to attempt to expand your understanding of 
Ruby.


John

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to puppet-users+unsubscr...@googlegroups.com.
To post to this group, send email to puppet-users@googlegroups.com.
Visit this group at http://groups.google.com/group/puppet-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to