Details
-
Bug
-
Status: Resolved
-
Normal
-
Resolution: Fixed
-
None
-
None
-
Coremunity
-
Platform Core KANBAN
-
Needs Assessment
-
Bug Fix
-
Fixes a rubygems caching issue that could prevent the agent from applying a catalog if a gem is managed using the native package manager, such as yum or apt.
-
Needs Assessment
Description
If a gem is managed by a native package manager (rpm, etc), and it is updated during a puppet run, it is possible for rubygems to be left in a bad state causing the run to fail.
This can be reproduced using:
require 'fileutils' |
require 'rubygems' |
if File.exist?("/tmp/thor-1.0.1.gemspec") |
FileUtils.mv("/tmp/thor-1.0.1.gemspec", "/opt/puppetlabs/puppet/lib/ruby/gems/2.5.0/specifications/thor-1.0.1.gemspec") |
end
|
Gem.clear_paths
|
begin
|
require 'msgpack' |
rescue LoadError => e |
end
|
FileUtils.mv("/opt/puppetlabs/puppet/lib/ruby/gems/2.5.0/specifications/thor-1.0.1.gemspec", "/tmp/thor-1.0.1.gemspec") |
Gem::Specification.latest_specs
|
Rubygems monkey patches Kernel.require so that if the gem fails to load, it will try to activate it. This has the side effect of caching the stub specifications for all gems.
If the gemspec is then removed via rpm upgrade, then the cached stub specification will refer to a gemspec that no longer exists.
If we later try to load the full specifications (such as when autoloading a terminus), then rubygems will raise:
/opt/puppetlabs/puppet/lib/ruby/2.5.0/rubygems/specification.rb:743:in `_all': pid: 9272 nil spec! included in [...#<Gem::StubSpecification:0x0000000001bf0bc0 @extension_dir=nil, @full_gem_path=nil, @gem_dir=nil, @ignored=nil, @loaded_from="/opt/puppetlabs/puppet/lib/ruby/gems/2.5.0/specifications/thor-1.0.1.gemspec", @data=#<Gem::StubSpecification::StubLine:0x0000000001c44810 @name="thor", @version=#<Gem::Version "1.0.1">...]
|
It can also be reproduced in puppet using:
require 'fileutils' |
require 'puppet' |
|
if File.exist?("/tmp/thor-1.0.1.gemspec") |
FileUtils.mv("/tmp/thor-1.0.1.gemspec", "/opt/puppetlabs/puppet/lib/ruby/gems/2.5.0/specifications/thor-1.0.1.gemspec") |
end
|
|
Puppet.initialize_settings
|
Puppet[:log_level] = 'debug' |
|
Puppet.features.msgpack?
|
FileUtils.mv("/opt/puppetlabs/puppet/lib/ruby/gems/2.5.0/specifications/thor-1.0.1.gemspec", "/tmp/thor-1.0.1.gemspec") |
Puppet::FileBucket::File.indirection.terminus(:rest) |