I''m trying to create a bunch of Facter facts in a loop. The code inside is evaluated at some weird time, *out of order*, and I don''t know enough Ruby to fix it. The goal is to get access to user homedirs, because I can''t figure out any other way to do that in Puppet. Here''s a few tries: passwd = IO.readlines(''/etc/passwd'') passwd.each do |line| line =~ /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/ Facter.add("home_#{$1}") do setcode do #{$6} end end end This ends up with every home_$user fact having the same homedir listed as the liste user in /etc/passwd. passwd = IO.readlines(''/etc/passwd'') homes = Array.new index = 0 passwd.each do |line| line =~ /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/ homes.push $6 Facter.add("home_#{$1}") do setcode do puts "stuff: "+", "+index.to_s+", "+homes[index] index += 1 homes[index-1] end end end This ends up with home_$user fact having a randomly selected, but distinct homedir. Help? -Robin -- They say: "The first AIs will be built by the military as weapons." And I''m thinking: "Does it even occur to you to try for something other than the default outcome?" -- http://shorl.com/tydruhedufogre http://www.digitalkingdom.org/~rlpowell/ *** http://www.lojban.org/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
On Sat, Jan 03, 2009 at 05:12:24PM -0800, Jos Backus wrote:> Untested: > > On Sat, Jan 03, 2009 at 04:55:41PM -0800, Robin Lee Powell wrote: > > > > > > I''m trying to create a bunch of Facter facts in a loop. The code > > inside is evaluated at some weird time, *out of order*, and I don''t > > know enough Ruby to fix it. The goal is to get access to user > > homedirs, because I can''t figure out any other way to do that in > > Puppet. > > > > Here''s a few tries: > > > > passwd = IO.readlines(''/etc/passwd'') > > passwd.each do |line| > > line =~ /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/ > > Facter.add("home_#{$1}") do > > Try: $1.dup > > > setcode do > > #{$6} > > Try: $6.dupWhat I end up with is: passwd = IO.readlines(''/etc/passwd'') passwd.each do |line| line =~ /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/ Facter.add("home_#{$1.dup}") do setcode do $6.dup end end end which does exactly the same thing: home_backup => /var/run/dbus home_bin => /var/run/dbus home_daemon => /var/run/dbus home_debian-exim => /var/run/dbus home_games => /var/run/dbus home_gnats => /var/run/dbus home_irc => /var/run/dbus home_libuuid => /var/run/dbus etc, etc. /var/run/dbus is the home of the last /etc/passwd entry. -Robin -- They say: "The first AIs will be built by the military as weapons." And I''m thinking: "Does it even occur to you to try for something other than the default outcome?" -- http://shorl.com/tydruhedufogre http://www.digitalkingdom.org/~rlpowell/ *** http://www.lojban.org/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
On Sat, Jan 03, 2009 at 10:52:19PM -0800, Jos Backus wrote:> Btw, rather than parsing /etc/passwd yourself, why not let the Etc > module do the work for you? > > Etc.passwd do |pwent| > Facter.add("home_#{pwent.name}") do > setcode do > pwent.dir > end > end > endBecause I had no idea it existed. That works fine; thank you! -Robin -- They say: "The first AIs will be built by the military as weapons." And I''m thinking: "Does it even occur to you to try for something other than the default outcome?" -- http://shorl.com/tydruhedufogre http://www.digitalkingdom.org/~rlpowell/ *** http://www.lojban.org/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
On Sat, Jan 03, 2009 at 05:13:01PM -0800, Robin Lee Powell wrote:> What I end up with is: > > passwd = IO.readlines(''/etc/passwd'') > passwd.each do |line| > line =~ /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/ > Facter.add("home_#{$1.dup}") doThe dup isn''t actually needed here as the dereference happens instantly with interpolation (to_s is called and a new String instance is returned).> setcode do > $6.dupHere I wasn''t sure but apparently it''s irrelevant here, too. Sorry, don''t know enough about Facter in order to be able to help you further. Btw, rather than parsing /etc/passwd yourself, why not let the Etc module do the work for you? Etc.passwd do |pwent| Facter.add("home_#{pwent.name}") do setcode do pwent.dir end end end> end > end > end > > which does exactly the same thing: > > home_backup => /var/run/dbus > home_bin => /var/run/dbus[snip]> /var/run/dbus is the home of the last /etc/passwd entry.-- Jos Backus jos at catnook.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
you could use something like that (didnt tested): File.open(''/etc/passwd'').each do |line| l=line.split('':'') Facter.add("home_#{l[0]}") do setcode do l[5] end end end Cheers, Ohad On Sun, Jan 4, 2009 at 8:55 AM, Robin Lee Powell < rlpowell@digitalkingdom.org> wrote:> > > I''m trying to create a bunch of Facter facts in a loop. The code > inside is evaluated at some weird time, *out of order*, and I don''t > know enough Ruby to fix it. The goal is to get access to user > homedirs, because I can''t figure out any other way to do that in > Puppet. > > Here''s a few tries: > > passwd = IO.readlines(''/etc/passwd'') > passwd.each do |line| > line =~ /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/ > Facter.add("home_#{$1}") do > setcode do > #{$6} > end > end > end > > This ends up with every home_$user fact having the same homedir > listed as the liste user in /etc/passwd. > > passwd = IO.readlines(''/etc/passwd'') > > homes = Array.new > index = 0 > > passwd.each do |line| > line =~ /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/ > homes.push $6 > Facter.add("home_#{$1}") do > setcode do > puts "stuff: "+", "+index.to_s+", "+homes[index] > index += 1 > homes[index-1] > end > end > end > > This ends up with home_$user fact having a randomly selected, but > distinct homedir. > > Help? > > -Robin > > -- > They say: "The first AIs will be built by the military as weapons." > And I''m thinking: "Does it even occur to you to try for something > other than the default outcome?" -- http://shorl.com/tydruhedufogre > http://www.digitalkingdom.org/~rlpowell/<http://www.digitalkingdom.org/%7Erlpowell/>*** > http://www.lojban.org/ > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
On Jan 3, 2009, at 6:55 PM, Robin Lee Powell wrote:> > > I''m trying to create a bunch of Facter facts in a loop. The code > inside is evaluated at some weird time, *out of order*, and I don''t > know enough Ruby to fix it. The goal is to get access to user > homedirs, because I can''t figure out any other way to do that in > Puppet. > > Here''s a few tries: > > passwd = IO.readlines(''/etc/passwd'') > passwd.each do |line| > line =~ /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/ > Facter.add("home_#{$1}") do > setcode do > #{$6} > end > end > endThe problem here is that the block passed to ''setcode'' isn''t run until later, at which point $6 is set to the last user''s homedir. Try this: Facter.add("...") do homedir = $6 # dereference immediately setcode { homedir } end This works because ''homedir'' is local to each fact definition, whereas $6 is global. At least, it *should* work. :) Yes, I know you already found a solution, but this is more a ruby question than a Puppet/Facter question, and I figure it''s worth pointing out the correct solution. -- Health is merely the slowest possible rate at which one can die. --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://madstop.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
On Thu, Jan 08, 2009 at 12:41:14AM -0600, Luke Kanies wrote:> The problem here is that the block passed to ''setcode'' isn''t run until > later, at which point $6 is set to the last user''s homedir. Try this: > > Facter.add("...") do > homedir = $6 # dereference immediately > setcode { homedir } > end > > This works because ''homedir'' is local to each fact definition, whereas > $6 is global. At least, it *should* work. :)I figured the $6.dup would create a local copy. Guess it works differently for globals, or I''m missing something obvious. I didn''t actually look at what setcode does, but that explains it.> Yes, I know you already found a solution, but this is more a ruby > question than a Puppet/Facter question, and I figure it''s worth > pointing out the correct solution.Thanks Luke. -- Jos Backus jos at catnook.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
On Jan 8, 2009, at 3:58 PM, Jos Backus wrote:> > On Thu, Jan 08, 2009 at 12:41:14AM -0600, Luke Kanies wrote: >> The problem here is that the block passed to ''setcode'' isn''t run >> until >> later, at which point $6 is set to the last user''s homedir. Try >> this: >> >> Facter.add("...") do >> homedir = $6 # dereference immediately >> setcode { homedir } >> end >> >> This works because ''homedir'' is local to each fact definition, >> whereas >> $6 is global. At least, it *should* work. :) > > I figured the $6.dup would create a local copy. Guess it works > differently for > globals, or I''m missing something obvious. I didn''t actually look at > what > setcode does, but that explains it.It does create a local copy -- but it only creates the local copy after $6 has been set to a single value (the last one). Remember that the setcode block is lazy-evaluated; it''s evaluated when the fact value is asked for, rather than when the fact is defined. This is partially why I recommend fact values be calculated dynamically rather than having a setup block that statically calculates a bunch of values and defines facts with those values; if the value changes over time (e.g., you hot-plug a disk and facter is counting disks) then dynamically calculated values are right but values only calculated on startup are wrong. -- I had a linguistics professor who said that it''s man''s ability to use language that makes him the dominant species on the planet. That may be. But I think there''s one other thing that separates us from animals. We aren''t afraid of vacuum cleaners. --Jeff Stilson --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://madstop.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
On Fri, Jan 09, 2009 at 12:16:10PM -0600, Luke Kanies wrote:> It does create a local copy -- but it only creates the local copy > after $6 has been set to a single value (the last one). Remember that > the setcode block is lazy-evaluated; it''s evaluated when the fact > value is asked for, rather than when the fact is defined.Okay. Because $6 is a global variable there''s only one value associated with it, and it is that value that is referenced when the setcode block is called. In the case of the `local'' variable below, the block/closure "remembers" its instance value from the time of the definition but in the case of the `$global'' variable there is only one instance, whose value at the end is common to all closures. The following code demonstrates the difference: lizzy:/tmp% cat x class Foo def setcode(&block) @block = block end def value @block.call end end a = [] 3.times do |i| a << f = Foo.new local, $global = i, i f.setcode do [local, $global] end end a.each do |elem| p elem.value end lizzy:/tmp% ruby x [0, 2] [1, 2] [2, 2] lizzy:/tmp% Hope I got that right. Thanks again, Luke. -- Jos Backus jos at catnook.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
One point of clarification, $1 and the other $n variables that get set from a regex are NOT globals. They are dynamically scoped. Run something like this to prove it: #!/usr/bin/env ruby def test_scope "in:the:scope:of:a:silly:method:kthx" =~ /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/ puts $7 end "a:test:to:prove:dynamic:scope:for:regex" =~ /(.*):(.*):(.*):(.*):(.*):(.*):(.*)/ puts $7 test_scope puts $7 you will get: regex kthx regex But $almostanythingelse IS global... ahh, Ruby... On Fri, Jan 9, 2009 at 11:29 PM, Jos Backus <jos@catnook.com> wrote:> > On Fri, Jan 09, 2009 at 12:16:10PM -0600, Luke Kanies wrote: > > It does create a local copy -- but it only creates the local copy > > after $6 has been set to a single value (the last one). Remember that > > the setcode block is lazy-evaluated; it''s evaluated when the fact > > value is asked for, rather than when the fact is defined. > > Okay. Because $6 is a global variable there''s only one value associated > with > it, and it is that value that is referenced when the setcode block is > called. > In the case of the `local'' variable below, the block/closure "remembers" > its > instance value from the time of the definition but in the case of the > `$global'' variable there is only one instance, whose value at the end is > common to all closures. > > The following code demonstrates the difference: > > lizzy:/tmp% cat x > class Foo > def setcode(&block) > @block = block > end > def value > @block.call > end > end > > a = [] > > 3.times do |i| > a << f = Foo.new > local, $global = i, i > f.setcode do > [local, $global] > end > end > > a.each do |elem| > p elem.value > end > lizzy:/tmp% ruby x > [0, 2] > [1, 2] > [2, 2] > lizzy:/tmp% > > Hope I got that right. Thanks again, Luke. > > -- > Jos Backus > jos at catnook.com > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
On Sat, Jan 10, 2009 at 02:24:59PM -0700, Andrew Shafer wrote:> One point of clarification, $1 and the other $n variables that get set from > a regex are NOT globals. > > They are dynamically scoped.Oh right, apologies getting that wrong (late, long day). They are also thread-local. Thanks for correcting me Andrew.> But $almostanythingelse IS global... ahh, Ruby...Yeah. One of the (few) places where Ruby compromised in order to be Perl-compatible. Personally I wish these fake $-variables would just go away. They seem like a wart on Ruby''s otherwise pretty clean syntax. -- Jos Backus jos at catnook.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
On Jan 10, 2009, at 1:24 PM, Andrew Shafer wrote:> One point of clarification, $1 and the other $n variables that get > set from a regex are NOT globals. > > They are dynamically scoped.I believe the term for this in ruby is ''thread local''. Adam --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---
Anything derived from $~ is actually dynamically scoped. If it was just thread local (which it is also) then the third puts would be the same as the second one. On Sat, Jan 10, 2009 at 3:24 PM, Adam Jacob <adam@hjksolutions.com> wrote:> > On Jan 10, 2009, at 1:24 PM, Andrew Shafer wrote: > > > One point of clarification, $1 and the other $n variables that get > > set from a regex are NOT globals. > > > > They are dynamically scoped. > > I believe the term for this in ruby is ''thread local''. > > Adam > > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en -~----------~----~----~----~------~----~------~--~---