Affects Version/s: PUP 5.5.1
Fix Version/s: PUP 6.0.0
Release Notes:Bug Fix
Release Notes Summary:Fix an issue running in JRuby where we didn't store autoloaded paths in the same way that the JRuby implementation did, leading to a bug where a type or provider could get loaded more than once.
NOTE: If you have found your way to this issue based on troubleshooting an issue with the file_concat module, please see
SERVER-40 for an easy workaround.
This issue was uncovered by
There is a difference in how Kernel.load() and require interact when referencing the same Ruby file – at least the file type – under an MRI puppet master vs. Puppet Server, both running 3.7.1 core Ruby Puppet code and 1.9-based Ruby.
During settings initialization, both masters will perform a:
This causes the Puppet::Type::File type to be defined, as well as several related types, e.g., Puppet::Type::File::Owner, by virtue of "file.rb" doing require 'puppet/type/file/*' calls.
Assuming a custom module which includes a require 'puppet/type/file' call in some Ruby code is in place, the behavior when that line is exercised under MRI Ruby Puppet vs. Puppet Server during a catalog request differs.
Under the MRI Ruby Puppet master, the file require call does not result in the "file.rb" file being re-executed.
Under Puppet Server, however, the file require call does result in the "file.rb" file being re-executed. The Puppet::Type::File type is subsequently redefined, causing the subordinate types like Puppet::Type::File::Owner to no longer be defined. The "file.rb" file executes the require 'puppet/type/file/... calls again but because JRuby's loader interprets the associated files as already having been executed, the files are not executed again and the Puppet::Type::File::* types are not redefined. Any subsequent attempts to reference these subordinate types in code would, therefore, result in an error.
I suspect this may be showing a difference between how the caching behind Kernel.load() and Kernel.require() is linked under MRI Ruby vs. JRuby 1.9. This will probably involve further research into the loaders for those respective runtimes.
To demonstrate this problem, I created the following custom function and placed it under "<confdir>/<modules>/<modname>/lib/puppet/parser/functions/owner_defed_after_require.rb" on the server:
On the same server, I stored the following at "<confdir>/manifests/site.pp":
When I performed a catalog request to the master, I saw "true" for the owner_defed_after_require message in the response for the MRI Ruby master vs. "false" for the same message in the response for the Puppet Server master.