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

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

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Normal
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: PUP 7.0.0, PUP 6.20.0
    • Component/s: None
    • Labels:
    • Template:
      PUP Bug Template
    • Team:
      Coremunity
    • Sprint:
      Platform Core KANBAN
    • Method Found:
      Needs Assessment
    • Release Notes:
      Bug Fix
    • Release Notes Summary:
      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.
    • QA Risk Assessment:
      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

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

              Dates

              Created:
              Updated:
              Resolved:

                Zendesk Support