Issue #22455 has been updated by Justin Holguin.

Category set to facter
Status changed from Unreviewed to Needs Decision
Assignee set to eric sorenson
Priority changed from High to Normal
Keywords set to facter, ruby

I was able to replicate this behavior with facter 1.7.3/ruby 1.8.7. 

----------------------------------------
Bug #22455: Changing a variable in a custom fact, after the fact changes the 
earlier set fact
https://projects.puppetlabs.com/issues/22455#change-98355

* Author: James Shubin
* Status: Needs Decision
* Priority: Normal
* Assignee: eric sorenson
* Category: facter
* Target version: 
* Affected Puppet version: 
* Keywords: facter, ruby
* Branch: 
----------------------------------------
Okay, I think I've totally earned my keep on this one. I was hitting an 
unbelievable condition while hacking on 
https://github.com/purpleidea/puppet-gluster *cough, plug*, and after a lot of 
head scratching I narrowed it down. I've come up with a demonstration test 
case/example. Look at the following fact:

<pre>
# XXX: demonstrate a surprising bug in puppet/facter

require 'facter'

value = 'hello'
Facter.add('foo') do
  setcode {
    value
  }
end

thing = {}
thing['a'] = 'puppet'
thing['b'] = 'works'

thing.keys.each do |x|
  value = thing[x]
  Facter.add('foo_'+x) do
    setcode {
      value     # bork
      # Facter::Util::Resolution.exec("/bin/echo -n '"+value+"'")       # bork!
      # thing[x]        # works as expected
    }
  end
end

value = 'BROKEN'        # shouldn't matter
</pre>

The issue is that if you use a variable in the setcode block, that variable 
*cannot* be changed without changing the earlier set value! In other words, you 
would expect:

<pre>
$ facter -p | grep foo
foo => hello
foo_a => puppet
foo_b => works
</pre>

but you actually get:

<pre>
$ facter -p | grep foo
foo => BROKEN
foo_a => BROKEN
foo_b => BROKEN
</pre>

FWIW:
<pre>
$ puppet --version
3.2.4
$ facter --version
1.7.2
</pre>

The workaround is to not reuse variables, and if you're creating facts in a 
loop, you have to do it in two steps, firstly create a dictionary of the fact 
names/values you want as a result, and then loop through that setting the facts.

The big issue is that this is highly unexpected in ruby code, and at best is 
not a documented gotcha. You can uncomment the various parts of my example to 
try different variations.

If this was an awesome catch, I guess I'd like some cool twitter followers 
@purpleidea or something :P

Cheers,
James



-- 
You have received this notification because you have either subscribed to it, 
or are involved in it.
To change your notification preferences, please click here: 
http://projects.puppetlabs.com/my/account

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Bugs" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/puppet-bugs.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to