From be5ae9bc9e198a00f2a790992b663dda374006ba Mon Sep 17 00:00:00 2001 From: Josh Cooper Date: Wed, 22 Nov 2023 10:54:32 -0800 Subject: Convert ProcessOutput to String explicitly The `filetype` provider executes `crontab` using Puppet's execution API, which returns ProcessOutput objects that inherit from String. See puppetlabs/puppet@732d450 The provider later uses String#gsub to strip off the HEADER. In Ruby 2.7, the gsub method returns a new instance of ProcessOutput: irb(main):002:0> Puppet::Util::Execution::ProcessOutput.new("# HEADER\n0 4 * * * /etc/init.d/script.sh\n", 0).gsub(/# HEADER/, '').class => Puppet::Util::Execution::ProcessOutput If you later serialize the crontab entries to YAML using `puppet resource`, then puppet warns about serializing unknown data types: # puppet resource cron --to_yaml Warning: Cron[unmanaged:/etc/init.d/script.sh-1]['command'] contains a Puppet::Util::Execution::ProcessOutput value. It will be converted to the String '/etc/init.d/script.sh' This wasn't an issue with Ruby 3.2, because String#gsub always returns a String: irb(main):002:0> Puppet::Util::Execution::ProcessOutput.new("# HEADER\n0 4 * * * /etc/init.d/script.sh\n", 0).gsub(/# HEADER/, '').class => String This commit explicitly converts the ProcessOutput to a String so the provider behaves consistently on all Ruby versions. Fixes #61 --- lib/puppet/provider/cron/filetype.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'lib/puppet/provider/cron') diff --git a/lib/puppet/provider/cron/filetype.rb b/lib/puppet/provider/cron/filetype.rb index 455ec07..3badeff 100644 --- a/lib/puppet/provider/cron/filetype.rb +++ b/lib/puppet/provider/cron/filetype.rb @@ -50,7 +50,7 @@ class Puppet::Provider::Cron return '' end - Puppet::Util::Execution.execute("#{cmdbase} -l", failonfail: true, combine: true) + Puppet::Util::Execution.execute("#{cmdbase} -l", failonfail: true, combine: true).to_s rescue => detail case detail.to_s when %r{no crontab for} @@ -71,7 +71,7 @@ class Puppet::Provider::Cron cmd = "/bin/echo yes | #{cmd}" end - Puppet::Util::Execution.execute(cmd, failonfail: true, combine: true) + Puppet::Util::Execution.execute(cmd, failonfail: true, combine: true).to_s end # Overwrite a specific @path's cron tab; must be passed the @path name @@ -113,7 +113,7 @@ class Puppet::Provider::Cron return '' end - Puppet::Util::Execution.execute(['crontab', '-l'], cronargs) + Puppet::Util::Execution.execute(['crontab', '-l'], cronargs).to_s rescue => detail case detail.to_s when %r{can't open your crontab} @@ -129,7 +129,7 @@ class Puppet::Provider::Cron # Remove a specific @path's cron tab. def remove - Puppet::Util::Execution.execute(['crontab', '-r'], cronargs) + Puppet::Util::Execution.execute(['crontab', '-r'], cronargs).to_s rescue => detail raise FileReadError, _('Could not remove crontab for %{path}: %{detail}') % { path: @path, detail: detail }, detail.backtrace end @@ -144,7 +144,7 @@ class Puppet::Provider::Cron output_file.close # We have to chown the stupid file to the user. File.chown(Puppet::Util.uid(@path), nil, output_file.path) - Puppet::Util::Execution.execute(['crontab', output_file.path], cronargs) + Puppet::Util::Execution.execute(['crontab', output_file.path], cronargs).to_s rescue => detail raise FileReadError, _('Could not write crontab for %{path}: %{detail}') % { path: @path, detail: detail }, detail.backtrace ensure @@ -164,7 +164,7 @@ class Puppet::Provider::Cron return '' end - Puppet::Util::Execution.execute(['crontab', '-l'], cronargs) + Puppet::Util::Execution.execute(['crontab', '-l'], cronargs).to_s rescue => detail case detail.to_s when %r{open.*in.*directory} @@ -180,7 +180,7 @@ class Puppet::Provider::Cron # Remove a specific @path's cron tab. def remove - Puppet::Util::Execution.execute(['crontab', '-r'], cronargs) + Puppet::Util::Execution.execute(['crontab', '-r'], cronargs).to_s rescue => detail raise FileReadError, _('Could not remove crontab for %{path}: %{detail}') % { path: @path, detail: detail }, detail.backtrace end @@ -196,7 +196,7 @@ class Puppet::Provider::Cron output_file.close # We have to chown the stupid file to the user. File.chown(Puppet::Util.uid(@path), nil, output_file.path) - Puppet::Util::Execution.execute(['crontab', output_file.path], cronargs) + Puppet::Util::Execution.execute(['crontab', output_file.path], cronargs).to_s rescue => detail raise FileReadError, _('Could not write crontab for %{path}: %{detail}') % { path: @path, detail: detail }, detail.backtrace ensure -- cgit v1.2.3