The puppetserver_gem package provider fails to list the correct gem list in puppetserver when there is a gem installed with `puppet_gem` and added by a `require` during the agent run or apply. In this scenario, the gem is listed as already installed by the puppetserver_gem provider when it is not installed in the puppetserver gem space. Logs The gem is only installed into the puppet gem space
# puppetserver gem list aws-sdk-s3 |
|
*** LOCAL GEMS *** |
|
# /opt/puppetlabs/puppet/bin/gem list aws-sdk-s3 |
|
*** LOCAL GEMS *** |
|
aws-sdk-s3 (1.112.0)
|
Running the agent or apply shows the gem is prefetched in the puppetserver_gem provider
# puppet apply install.pp --debug |& grep aws-sdk-s3 |
Debug: /Package[aws-sdk-s3]: Provider puppetserver_gem does not support features targetable; not managing attribute command |
Debug: /Package[aws-sdk-s3]: Provider puppetserver_gem does not support features install_only; not managing attribute install_only |
Debug: /Package[aws-sdk-s3]: Provider puppetserver_gem does not support features virtual_packages; not managing attribute allow_virtual |
Debug: Puppet::Type::Package::ProviderPuppetserver_gem: Prefetched instance: aws-sdk-s3 via command: default
|
Reproduction
- On a 7.x Puppetserver - PE 2021.4.0 in this example
- Install the gem using the `puppet_gem` provider: puppet resource package aws-sdk-s3 ensure=installed provider=puppet_gem
- Add the following fact into the environment and ensure it is downloaded with puppet plugin download
Facter.add(:testing) do |
setcode do |
require 'aws-sdk-s3' |
Aws::S3::GEM_VERSION |
end |
end
|
- Apply the following manifest to observe that the puppetserver_gem package is not installed
package{'aws-sdk-s3': |
ensure => installed, |
provider => puppetserver_gem |
}
|
Potential Fix This looks to be an issue due to the puppetserver_gem not forking the gem list command, so the loaded gems are listed in these lines.
If I replace those lines with one that uses the /opt/puppetlabs/puppet/bin/gem command, the issue no longer appears. For example:
output = execute_gem_command(Puppet::Type::Package::ProviderPuppet_gem.provider_command, ["list","--local"], gem_env) |
gem_list = output.lines.reject { |gem| gem =~ / \(default\: / }
|
There is a significant difference in the number of gems listed between the two outputs.
# The current implementation |
> sio_out.string.lines.reject { |gem| gem =~ / \(default\: / }.length |
=> 56 |
# Shelling out to `gem` |
> output.lines.reject { |gem| gem =~ / \(default\: / }.length |
=> 25
|
This aligns with the `puppetserver gem list` and `gem list` commands.
# puppetserver gem list |grep -v default | wc -l |
25 |
# /opt/puppetlabs/puppet/bin/gem list |grep -v default | wc -l |
56
|
|