Uploaded image for project: 'Puppet'
  1. Puppet
  2. PUP-10719

Puppet's feature detection can leave rubygems in a bad state

    XMLWordPrintable

Details

    • Bug
    • Status: Resolved
    • Normal
    • Resolution: Fixed
    • None
    • PUP 7.0.0, PUP 6.20.0
    • 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)
      

      Attachments

        Activity

          People

            Unassigned Unassigned
            josh Josh Cooper
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Zendesk Support