require 'spec_helper' require 'puppet/provider/cron/filetype' # rubocop:disable RSpec/FilePath describe Puppet::Provider::Cron::FileType do shared_examples_for 'crontab provider' do let(:cron) { type.new('no_such_user') } let(:crontab) { File.read(my_fixture(crontab_output)) } let(:options) { { failonfail: true, combine: true } } let(:uid) { 'no_such_user' } let(:user_options) { options.merge(uid: uid) } it 'exists' do expect(type).not_to be_nil end # make Puppet::Util::SUIDManager return something deterministic, not the # uid of the user running the tests, except where overridden below. before :each do allow(Puppet::Util::SUIDManager).to receive(:uid).and_return 1234 end describe '#read' do before(:each) do allow(Puppet::Util).to receive(:uid).with(uid).and_return 9000 end it 'runs crontab -l as the target user' do expect(Puppet::Util::Execution).to receive(:execute).with(['crontab', '-l'], user_options).and_return(Puppet::Util::Execution::ProcessOutput.new(crontab, 0)) expect(cron.read).to eq(crontab) end it 'does not switch user if current user is the target user' do expect(Puppet::Util).to receive(:uid).with(uid).twice.and_return 9000 expect(Puppet::Util::SUIDManager).to receive(:uid).and_return 9000 expect(Puppet::Util::Execution).to receive(:execute).with(['crontab', '-l'], options).and_return(Puppet::Util::Execution::ProcessOutput.new(crontab, 0)) expect(cron.read).to eq(crontab) end it 'treats an absent crontab as empty' do expect(Puppet::Util::Execution).to receive(:execute).with(['crontab', '-l'], user_options).and_raise(Puppet::ExecutionFailure, absent_crontab) expect(cron.read).to eq('') end it "treats a nonexistent user's crontab as empty" do expect(Puppet::Util).to receive(:uid).with(uid).and_return nil expect(cron.read).to eq('') end it 'returns empty if the user is not authorized to use cron' do expect(Puppet::Util::Execution).to receive(:execute).with(['crontab', '-l'], user_options).and_raise(Puppet::ExecutionFailure, unauthorized_crontab) expect(cron.read).to eq('') end end describe '#remove' do it 'runs crontab -r as the target user' do expect(Puppet::Util::Execution).to receive(:execute).with(['crontab', '-r'], user_options) cron.remove end it 'does not switch user if current user is the target user' do expect(Puppet::Util).to receive(:uid).with(uid).and_return 9000 expect(Puppet::Util::SUIDManager).to receive(:uid).and_return 9000 expect(Puppet::Util::Execution).to receive(:execute).with(['crontab', '-r'], options) cron.remove end end describe '#write' do let!(:tmp_cron) { Tempfile.new('puppet_crontab_spec') } let!(:tmp_cron_path) { tmp_cron.path } before :each do allow(Puppet::Util).to receive(:uid).with(uid).and_return 9000 allow(Tempfile).to receive(:new).with("puppet_#{name}", encoding: Encoding.default_external).and_return tmp_cron end after :each do allow(File).to receive(:chown).and_call_original end it 'runs crontab as the target user on a temporary file' do expect(File).to receive(:chown).with(9000, nil, tmp_cron_path) expect(Puppet::Util::Execution).to receive(:execute).with(['crontab', tmp_cron_path], user_options) expect(tmp_cron).to receive(:print).with("foo\n") cron.write "foo\n" expect(Puppet::FileSystem).not_to exist(tmp_cron_path) end it 'does not switch user if current user is the target user' do expect(Puppet::Util::SUIDManager).to receive(:uid).and_return 9000 expect(File).to receive(:chown).with(9000, nil, tmp_cron_path) expect(Puppet::Util::Execution).to receive(:execute).with(['crontab', tmp_cron_path], options) expect(tmp_cron).to receive(:print).with("foo\n") cron.write "foo\n" expect(Puppet::FileSystem).not_to exist(tmp_cron_path) end end end describe 'the suntab filetype', unless: Puppet::Util::Platform.windows? do let(:type) { described_class.filetype(:suntab) } let(:name) { type.name } let(:crontab_output) { 'suntab_output' } # possible crontab output was taken from here: # https://docs.oracle.com/cd/E19082-01/819-2380/sysrescron-60/index.html let(:absent_crontab) do 'crontab: can\'t open your crontab file' end let(:unauthorized_crontab) do 'crontab: you are not authorized to use cron. Sorry.' end it_behaves_like 'crontab provider' end describe 'the aixtab filetype', unless: Puppet::Util::Platform.windows? do let(:type) { described_class.filetype(:aixtab) } let(:name) { type.name } let(:crontab_output) { 'aixtab_output' } let(:absent_crontab) do '0481-103 Cannot open a file in the /var/spool/cron/crontabs directory.' end let(:unauthorized_crontab) do '0481-109 You are not authorized to use the cron command.' end it_behaves_like 'crontab provider' end end