facter 3 and at_exit

42 views
Skip to first unread message

Clay Caviness

unread,
Apr 1, 2016, 4:58:10 PM4/1/16
to puppet-users
I've come across an issue with facter 3, when using at_exit. Basically, any at_exit blocks that refer to anything not in the top-level namespace (pardon my terminology) trigger an 'uninitialized constant' NameError. I think this is a namespace issue of some sort, but it's beyond my ken.

To recreate:
Create uninitialized.rb:
require 'facter'
at_exit { Facter.warn('Facter.warn at exit') }
at_exit { puts 'puts at exit' }
Facter.add('uninitialized_constant') do
  setcode do
    'foo'
  end
end

Run facter:
facter -p uninitialized_constant facterversion
facterversion => 3.1.4
uninitialized_constant => foo
puts at exit
/private/var/puppet/lib/facter/unint.rb:3:in `block in <top (required)>': uninitialized constant Facter (NameError)

Note that the 'puts' at_exit works, but not the one using Facter.warn.

This works fine in facter 2:
$ sudo facter -p uninitialized_constant facterversion
facterversion => 2.4.4
uninitialized_constant => foo
puts at exit
Facter.warn at exit


Peter Huene

unread,
Apr 1, 2016, 5:33:38 PM4/1/16
to puppet...@googlegroups.com
Hi Clay,

On Fri, Apr 1, 2016 at 1:57 PM, Clay Caviness <cl...@boobah.com> wrote:
I've come across an issue with facter 3, when using at_exit. Basically, any at_exit blocks that refer to anything not in the top-level namespace (pardon my terminology) trigger an 'uninitialized constant' NameError. I think this is a namespace issue of some sort, but it's beyond my ken.

To recreate:
Create uninitialized.rb:
require 'facter'
at_exit { Facter.warn('Facter.warn at exit') }
at_exit { puts 'puts at exit' }
Facter.add('uninitialized_constant') do
  setcode do
    'foo'
  end
end

Run facter:
facter -p uninitialized_constant facterversion
facterversion => 3.1.4
uninitialized_constant => foo
puts at exit
/private/var/puppet/lib/facter/unint.rb:3:in `block in <top (required)>': uninitialized constant Facter (NameError)

Note that the 'puts' at_exit works, but not the one using Facter.warn.

This is caused by how custom facts are resolved in Facter 3: namely that custom facts are resolved all at once and no further calls from Ruby into Facter's native implementation are expected when all resolutions have completed.  The Facter module removes itself from the Ruby runtime after all resolutions complete, but before the Ruby runtime is shutdown (when at_exit callbacks would occur).  This is why your at_exit callbacks can't find the Facter module; it's no longer there at that point.

Looking things over, I believe it doesn't need to be implemented this way. The Facter module could outlive the Ruby runtime, allowing at_exit callbacks to still make use of Facter.  This would require that the native implementation not attempt to clean up explicit GC registrations made from the module, which should be entirely unnecessary anyway since the Ruby runtime has (in theory at least) destroyed the GC heap when the Ruby runtime is shutdown.

I haven't seen at_exit used in a custom fact before, so I'm interested in your use case.  Given that I consider this behavior to be an implementation bug in Facter, would you mind opening a JIRA ticket at https://tickets.puppetlabs.com (project should be "FACT" for Facter) and detailing the use case?

Thanks!
 

This works fine in facter 2:
$ sudo facter -p uninitialized_constant facterversion
facterversion => 2.4.4
uninitialized_constant => foo
puts at exit
Facter.warn at exit


--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/CANU2HrfPkoYcZcEWUioiTbyeN-60KfceZx3d1UX5XzdL3atSqg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Clay Caviness

unread,
Apr 1, 2016, 5:43:17 PM4/1/16
to puppet...@googlegroups.com
On Fri, Apr 1, 2016 at 5:33 PM Peter Huene <peter...@puppetlabs.com> wrote:
This is caused by how custom facts are resolved in Facter 3: namely that custom facts are resolved all at once and no further calls from Ruby into Facter's native implementation are expected when all resolutions have completed.  The Facter module removes itself from the Ruby runtime after all resolutions complete, but before the Ruby runtime is shutdown (when at_exit callbacks would occur).  This is why your at_exit callbacks can't find the Facter module; it's no longer there at that point.


Ah, interesting. Thanks.
 
Looking things over, I believe it doesn't need to be implemented this way. The Facter module could outlive the Ruby runtime, allowing at_exit callbacks to still make use of Facter.  This would require that the native implementation not attempt to clean up explicit GC registrations made from the module, which should be entirely unnecessary anyway since the Ruby runtime has (in theory at least) destroyed the GC heap when the Ruby runtime is shutdown.

I haven't seen at_exit used in a custom fact before, so I'm interested in your use case.  Given that I consider this behavior to be an implementation bug in Facter, would you mind opening a JIRA ticket at https://tickets.puppetlabs.com (project should be "FACT" for Facter) and detailing the use case?


We're using https://github.com/google/macops/blob/master/facter/cache.rb in order to have some caching for long-resolving facts.

We have an at_exit call there to save the cached facts if they've changed.

I'll raise a ticket. 

Clay Caviness

unread,
Apr 1, 2016, 5:53:11 PM4/1/16
to puppet...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages