aboutsummaryrefslogtreecommitdiff
path: root/spec/acceptance/tests/resource/cron/should_only_fail_associated_resources_on_file_read_error_spec.rb
diff options
context:
space:
mode:
authorEnis Inan <enis.inan@puppet.com>2018-12-13 02:11:39 -0800
committerEnis Inan <enis.inan@puppet.com>2019-01-09 08:48:20 -0800
commita369886d68aa84a14defd3e594aa75cab71da328 (patch)
treea75646ceb991ba89bd5652391dd7896953173b46 /spec/acceptance/tests/resource/cron/should_only_fail_associated_resources_on_file_read_error_spec.rb
parente76bd24dcb33ab71440633303124ea99d59b7783 (diff)
downloadpuppet-cron_core-a369886d68aa84a14defd3e594aa75cab71da328.tar.gz
puppet-cron_core-a369886d68aa84a14defd3e594aa75cab71da328.tar.bz2
(MODULES-7789) Port over the PUP-9217 changes
PUP-9217 introduced the :raise_prefetch_errors option to the ParsedFile provider base class that, when set, will fail any resources associated with a failed prefetch target. Thus, when a file read error does occur, Puppet will fail all of the resources associated with the failed crontab (target). This means that the failed crontab will not be overwritten, thus fixing the issue described in the ticket. For more details, please refer to https://github.com/puppetlabs/puppet/commit/5b0fa987e5b7b27839e424ff16d59c7bf081c73a
Diffstat (limited to 'spec/acceptance/tests/resource/cron/should_only_fail_associated_resources_on_file_read_error_spec.rb')
-rw-r--r--spec/acceptance/tests/resource/cron/should_only_fail_associated_resources_on_file_read_error_spec.rb115
1 files changed, 115 insertions, 0 deletions
diff --git a/spec/acceptance/tests/resource/cron/should_only_fail_associated_resources_on_file_read_error_spec.rb b/spec/acceptance/tests/resource/cron/should_only_fail_associated_resources_on_file_read_error_spec.rb
new file mode 100644
index 0000000..3e06d0c
--- /dev/null
+++ b/spec/acceptance/tests/resource/cron/should_only_fail_associated_resources_on_file_read_error_spec.rb
@@ -0,0 +1,115 @@
+require 'spec_helper_acceptance'
+
+RSpec.context 'when Puppet cannot read a crontab file' do
+ let(:username) { "pl#{rand(999_999).to_i}" }
+ let(:failed_username) { "pl#{rand(999_999).to_i}" }
+
+ before(:each) do
+ step 'Create the users' do
+ compatible_agents.each do |agent|
+ user_present(agent, username)
+ user_present(agent, failed_username)
+ end
+ end
+ end
+
+ after(:each) do
+ step 'Teardown -- Erase the users' do
+ compatible_agents.each do |agent|
+ run_cron_on(agent, :remove, username)
+ user_absent(agent, username)
+
+ user_absent(agent, failed_username)
+ end
+ end
+ end
+
+ compatible_agents.each do |agent|
+ it "should only fail the associated resources on #{agent}" do
+ crontab_exe = nil
+ step 'Find the crontab executable' do
+ crontab_exe = on(agent, 'which crontab').stdout.chomp
+ end
+
+ stub_crontab_bin_dir = nil
+ stub_crontab_exe = nil
+ step 'Create the stub crontab executable that triggers the read error for the failed user' do
+ stub_crontab_bin_dir = agent.tmpdir('stub_crontab_bin_dir')
+ stub_crontab_exe = "#{stub_crontab_bin_dir}/crontab"
+
+ # On Linux and OSX, we read a user's crontab by running crontab -u <username>,
+ # where the crontab command is run as root. However on AIX/Solaris, we read a
+ # user's crontab by running the crontab command as that user. Thus our mock
+ # crontab executable needs to check if we're reading our failed user's crontab
+ # (Linux and OSX) OR running crontab as our failed user (AIX and Solaris) before
+ # triggering the FileReadError
+ stub_crontab_exe_script = <<-SCRIPT
+#!/usr/bin/env bash
+ if [[ "$@" =~ #{failed_username} || "`id`" =~ #{failed_username} ]]; then
+ echo "Mocking a FileReadError for the #{failed_username} user's crontab!"
+ exit 1
+fi
+ #{crontab_exe} $@
+SCRIPT
+
+ create_remote_file(agent, stub_crontab_exe, stub_crontab_exe_script)
+ on(agent, "chmod 777 #{stub_crontab_bin_dir}")
+ on(agent, "chmod 777 #{stub_crontab_exe}")
+ end
+
+ path_env_var = nil
+ step 'Get the value of the PATH environment variable' do
+ path_env_var = on(agent, 'echo $PATH').stdout.chomp
+ end
+
+ puppet_result = nil
+ step 'Add some cron entries with Puppet' do
+ # We delete our mock crontab executable here to ensure that Cron[second_entry]'s
+ # evaluation fails because of the FileReadError raised in the prefetch
+ # step. Otherwise, Cron[second_entry]'s evaluation will fail at the write step
+ # because Puppet would still be invoking our mock crontab executable, which would
+ # pass the test on an agent that swallows FileReadErrors in the cron provider's
+ # prefetch step.
+ manifest = [
+ cron_manifest('first_entry', command: 'ls', user: username),
+ file_manifest(stub_crontab_exe, ensure: :absent),
+ cron_manifest('second_entry', command: 'ls', user: failed_username),
+ ].join("\n\n")
+ manifest_file = agent.tmpfile('crontab_overwrite_manifest')
+ create_remote_file(agent, manifest_file, manifest)
+
+ # We need to run a script here instead of a command because:
+ # * We need to cd into a directory that our user can access. Otherwise, bash will
+ # fail to execute stub_crontab_exe on AIX and Solaris because we run crontab
+ # as the given user, and the given user does not have access to Puppet's cwd.
+ #
+ # * We also need to pass-in our PATH to Puppet since it contains stub_crontab_bin_dir.
+ apply_crontab_overwrite_manifest = agent.tmpfile('apply_crontab_overwrite_manifest')
+ script = <<-SCRIPT
+ #!/usr/bin/env bash
+ cd #{stub_crontab_bin_dir} && puppet apply #{manifest_file}
+ SCRIPT
+ create_remote_file(agent, apply_crontab_overwrite_manifest, script)
+ on(agent, "chmod a+x #{apply_crontab_overwrite_manifest}")
+
+ puppet_result = on(agent, "bash #{apply_crontab_overwrite_manifest}", environment: { PATH: "#{stub_crontab_bin_dir}:#{path_env_var}" })
+ end
+
+ step 'Verify that Puppet fails a Cron resource associated with an unreadable crontab file' do
+ assert_match(%r{Cron.*second_entry}, puppet_result.stderr, 'Puppet does not fail a Cron resource associated with an unreadable crontab file')
+ end
+
+ step 'Verify that Puppet does not fail a Cron resource associated with a readable crontab file' do
+ assert_no_match(%r{Cron.*first_entry}, puppet_result.stderr, 'Puppet fails a Cron resource associated with a readable crontab file')
+ end
+
+ step 'Verify that Puppet successfully evaluates a Cron resource associated with a readable crontab file' do
+ assert_match(%r{Cron.*first_entry}, puppet_result.stdout, 'Puppet fails to evaluate a Cron resource associated with a readable crontab file')
+ end
+
+ step 'Verify that Puppet did update the readable crontab file with the Cron resource' do
+ assert_matching_arrays(['* * * * * ls'], crontab_entries_of(agent, username), 'Puppet fails to update a readable crontab file with the specified Cron entry')
+ end
+ end
+ end
+end