diff --git a/acceptance/tests/resource/cron/should_not_rewrite_with_trailing_whitespace.rb b/acceptance/tests/resource/cron/should_not_rewrite_with_trailing_whitespace.rb new file mode 100644 index 000000000..26fb87b62 --- /dev/null +++ b/acceptance/tests/resource/cron/should_not_rewrite_with_trailing_whitespace.rb @@ -0,0 +1,40 @@ +test_name "should not rewrite if the job has trailing whitespace" + +tmpuser = "pl#{rand(999999).to_i}" +tmpfile = "/tmp/cron-test-#{Time.new.to_i}" + +create_user = "user { '#{tmpuser}': ensure => present, managehome => false }" +delete_user = "user { '#{tmpuser}': ensure => absent, managehome => false }" + +agents.each do |host| + if host['platform'].include?('windows') + skip_test "Test not supported on this platform" + next + end + + step "ensure the user exist via puppet" + apply_manifest_on host, create_user + + step "apply the resource on the host using puppet resource" + on(host, puppet_resource("cron", "crontest", "user=#{tmpuser}", + "command='date > /dev/null '", "ensure=present")) do + assert_match(/created/, stdout, "Did not create crontab for #{tmpuser} on #{host}") + end + + step "verify that crontab -l contains what you expected" + run_cron_on(host, :list, tmpuser) do + assert_match(/\* \* \* \* \* date > .dev.null /, stdout, "Incorrect crontab for #{tmpuser} on #{host}") + end + + step "apply the resource again on the host using puppet resource and check nothing happened" + on(host, puppet_resource("cron", "crontest", "user=#{tmpuser}", + "command='date > /dev/null '", "ensure=present")) do + assert_no_match(/ensure: created/, stdout, "Rewrote the line with trailing space in crontab for #{tmpuser} on #{host}") + end + + step "remove the crontab file for that user" + run_cron_on(host, :remove, tmpuser) + + step "remove the user from the system" + apply_manifest_on host, delete_user +end diff --git a/test/ral/type/cron.rb b/test/ral/type/cron.rb deleted file mode 100755 index ae280e04f..000000000 --- a/test/ral/type/cron.rb +++ /dev/null @@ -1,505 +0,0 @@ -#!/usr/bin/env ruby - -require File.expand_path(File.dirname(__FILE__) + '/../../lib/puppettest') - -require 'puppettest' - -# Test cron job creation, modification, and destruction - -class TestCron < Test::Unit::TestCase - include PuppetTest - - def setup - super - - setme - - @crontype = Puppet::Type.type(:cron) - @provider = @crontype.defaultprovider - if @provider.respond_to?(:filetype=) - @provider.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram)) - end - @crontype = Puppet::Type.type(:cron) - end - - def teardown - super - @crontype.defaultprovider = nil - end - - def eachprovider - @crontype.suitableprovider.each do |provider| - yield provider - end - end - - # Back up the user's existing cron tab if they have one. - def cronback - tab = nil - assert_nothing_raised { - tab = Puppet::Type.type(:cron).filetype.read(@me) - } - - @currenttab = $CHILD_STATUS == 0 ? tab : nil - end - - # Restore the cron tab to its original form. - def cronrestore - assert_nothing_raised { - if @currenttab - @crontype.filetype.new(@me).write(@currenttab) - else - @crontype.filetype.new(@me).remove - end - } - end - - # Create a cron job with all fields filled in. - def mkcron(name, addargs = true) - cron = nil - command = "date > #{tmpdir()}/crontest#{name}" - args = nil - if addargs - args = { - :command => command, - :name => name, - :user => @me, - :minute => rand(59), - :month => "1", - :monthday => "1", - :hour => "1" - } - else - args = {:command => command, :name => name} - end - assert_nothing_raised { - cron = @crontype.new(args) - } - - cron - end - - # Run the cron through its paces -- install it then remove it. - def cyclecron(cron) - obj = Puppet::Type::Cron.cronobj(@me) - - text = obj.read - name = cron.name - comp = mk_catalog(name, cron) - - assert_events([:cron_created], comp) - cron.provider.class.prefetch - currentvalue = cron.retrieve - - assert(cron.insync?(currentvalue), "Cron is not in sync") - - assert_events([], comp) - - curtext = obj.read - text.split("\n").each do |line| - assert(curtext.include?(line), "Missing '#{line}'") - end - obj = Puppet::Type::Cron.cronobj(@me) - - cron[:ensure] = :absent - - assert_events([:cron_removed], comp) - - cron.provider.class.prefetch - currentvalue = cron.retrieve - - assert(cron.insync?(currentvalue), "Cron is not in sync") - assert_events([], comp) - end - - # Test that a cron job with spaces at the end doesn't get rewritten - def test_trailingspaces - eachprovider do |provider| - cron = nil - # make the cron - name = "yaytest" - command = "date > /dev/null " - assert_nothing_raised { - - cron = @crontype.new( - - :name => name, - :command => "date > /dev/null ", - :month => "May", - - :user => @me - ) - } - property = cron.send(:property, :command) - cron.provider.command = command - cron.provider.ensure = :present - cron.provider.user = @me - cron.provider.month = ["4"] - cron.provider.class.prefetch - currentvalue = cron.retrieve - assert(cron.parameter(:command).insync?(currentvalue[:command]), "Property :command is not considered in sync with value #{currentvalue[:command]}") - end - end - - def test_makeandretrievecron - %w{storeandretrieve a-name another-name more_naming SomeName}.each do |name| - cron = mkcron(name) - catalog = mk_catalog(name, cron) - trans = assert_events([:cron_created], catalog, name) - - cron.provider.class.prefetch - cron = nil - - assert(cron = catalog.resource(:cron, name), "Could not retrieve named cron") - assert_instance_of(Puppet::Type.type(:cron), cron) - end - end - - # Do input validation testing on all of the parameters. - def test_arguments - values = { - :monthday => { - :valid => [ 1, 13, "1" ], - :invalid => [ -1, 0, 32 ] - }, - :weekday => { - :valid => [ 0, 3, 6, "1", "tue", "wed", - "Wed", "MOnday", "SaTurday" ], - :invalid => [ -1, 8, "13", "tues", "teusday", "thurs" ] - }, - :hour => { - :valid => [ 0, 21, 23 ], - :invalid => [ -1, 24 ] - }, - :minute => { - :valid => [ 0, 34, 59 ], - :invalid => [ -1, 60 ] - }, - :month => { - :valid => [ 1, 11, 12, "mar", "March", "apr", "October", "DeCeMbEr" ], - :invalid => [ -1, 0, 13, "marc", "sept" ] - } - } - - cron = mkcron("valtesting") - values.each { |param, hash| - # We have to test the valid ones first, because otherwise the - # property will fail to create at all. - [:valid, :invalid].each { |type| - hash[type].each { |value| - case type - when :valid - assert_nothing_raised { - cron[param] = value - } - - assert_equal([value.to_s], cron.should(param), "Cron value was not set correctly") if value.is_a?(Integer) - when :invalid - assert_raise(Puppet::Error, "#{value} is incorrectly a valid #{param}") { - cron[param] = value - } - end - - if value.is_a?(Integer) - value = value.to_s - redo - end - } - } - } - end - - # Verify that comma-separated numbers are not resulting in rewrites - def test_comma_separated_vals_work - eachprovider do |provider| - cron = nil - assert_nothing_raised { - - cron = @crontype.new( - - :command => "/bin/date > /dev/null", - :minute => [0, 30], - :name => "crontest", - - :provider => provider.name - ) - } - - - cron.provider.ensure = :present - cron.provider.command = '/bin/date > /dev/null' - cron.provider.minute = %w{0 30} - cron.provider.class.prefetch - currentvalue = cron.retrieve - - currentvalue.each do |name, value| - # We're only interested in comparing minutes. - next unless name.to_s == "minute" - assert(cron.parameter(name).insync?(value), "Property #{name} is not considered in sync with value #{value.inspect}") - end - end - end - - def test_fieldremoval - cron = nil - assert_nothing_raised { - - cron = @crontype.new( - - :command => "/bin/date > /dev/null", - :minute => [0, 30], - :name => "crontest", - - :provider => :crontab - ) - } - - assert_events([:cron_created], cron) - cron.provider.class.prefetch - - cron[:minute] = :absent - assert_events([:minute_changed], cron) - - current_values = nil - assert_nothing_raised { - cron.provider.class.prefetch - current_values = cron.retrieve - } - assert_equal(:absent, current_values[cron.property(:minute)]) - end - - def test_listing - # Make a crontab cron for testing - provider = @crontype.provider(:crontab) - return unless provider.suitable? - - ft = provider.filetype - provider.filetype = :ram - cleanup { provider.filetype = ft } - - setme - - cron = @crontype.new( - :name => "testing", - :minute => [0, 30], - :command => "/bin/testing", - - :user => @me - ) - # Write it to our file - assert_apply(cron) - - crons = [] - assert_nothing_raised { - @crontype.instances.each do |cron| - crons << cron - end - } - - crons.each do |cron| - assert_instance_of(@crontype, cron, "Did not receive a real cron object") - - assert_instance_of( - String, cron.value(:user), - - "Cron user is not a string") - end - end - - def verify_failonnouser - assert_raise(Puppet::Error) do - @crontype.retrieve("nosuchuser") - end - end - - def test_divisionnumbers - cron = mkcron("divtest") - cron[:minute] = "*/5" - - assert_apply(cron) - - cron.provider.class.prefetch - currentvalue = cron.retrieve - - assert_equal(["*/5"], currentvalue[cron.property(:minute)]) - end - - def test_ranges - cron = mkcron("rangetest") - cron[:minute] = "2-4" - - assert_apply(cron) - - current_values = nil - assert_nothing_raised { - cron.provider.class.prefetch - current_values = cron.retrieve - } - - assert_equal(["2-4"], current_values[cron.property(:minute)]) - end - - - def provider_set(cron, param, value) - unless param =~ /=$/ - param = "#{param}=" - end - - cron.provider.send(param, value) - end - - def test_value - cron = mkcron("valuetesting", false) - - # First, test the normal properties - [:minute, :hour, :month].each do |param| - cron.newattr(param) - property = cron.property(param) - - assert(property, "Did not get #{param} property") - - assert_nothing_raised { - # property.is = :absent - provider_set(cron, param, :absent) - } - - val = "*" - assert_equal(val, cron.value(param)) - - # Make sure arrays work, too - provider_set(cron, param, ["1"]) - assert_equal(%w{1}, cron.value(param)) - - # Make sure values get comma-joined - provider_set(cron, param, %w{2 3}) - assert_equal(%w{2 3}, cron.value(param)) - - # Make sure "should" values work, too - cron[param] = "4" - assert_equal(%w{4}, cron.value(param)) - - cron[param] = ["4"] - assert_equal(%w{4}, cron.value(param)) - - cron[param] = ["4", "5"] - assert_equal(%w{4 5}, cron.value(param)) - - provider_set(cron, param, :absent) - assert_equal(%w{4 5}, cron.value(param)) - end - - Puppet[:trace] = false - - # Now make sure that :command works correctly - cron.delete(:command) - cron.newattr(:command) - property = cron.property(:command) - - assert_nothing_raised { - provider_set(cron, :command, :absent) - } - - param = :command - # Make sure arrays work, too - provider_set(cron, param, ["/bin/echo"]) - assert_equal("/bin/echo", cron.value(param)) - - # Make sure values are not comma-joined - provider_set(cron, param, %w{/bin/echo /bin/test}) - assert_equal("/bin/echo", cron.value(param)) - - # Make sure "should" values work, too - cron[param] = "/bin/echo" - assert_equal("/bin/echo", cron.value(param)) - - cron[param] = ["/bin/echo"] - assert_equal("/bin/echo", cron.value(param)) - - cron[param] = %w{/bin/echo /bin/test} - assert_equal("/bin/echo", cron.value(param)) - - provider_set(cron, param, :absent) - assert_equal("/bin/echo", cron.value(param)) - end - - def test_multiple_users - crons = [] - users = ["root", nonrootuser.name] - users.each do |user| - - cron = Puppet::Type.type(:cron).new( - - :name => "testcron-#{user}", - :user => user, - :command => "/bin/echo", - - :minute => [0,30] - ) - crons << cron - - assert_equal(cron.should(:user), cron.should(:target), - "Target was not set correctly for #{user}") - end - provider = crons[0].provider.class - - assert_apply(*crons) - - users.each do |user| - users.each do |other| - next if user == other - text = provider.target_object(other).read - - - assert( - text !~ /testcron-#{user}/, - - "#{user}'s cron job is in #{other}'s tab") - end - end - end - - # Make sure the user stuff defaults correctly. - def test_default_user - crontab = @crontype.provider(:crontab) - if crontab.suitable? - - inst = @crontype.new( - - :name => "something", :command => "/some/thing", - - :provider => :crontab) - assert_equal(Etc.getpwuid(Process.uid).name, inst.should(:user), "user did not default to current user with crontab") - assert_equal(Etc.getpwuid(Process.uid).name, inst.should(:target), "target did not default to current user with crontab") - - # Now make a new cron with a user, and make sure it gets copied - # over - - inst = @crontype.new( - :name => "yay", :command => "/some/thing", - - :user => "bin", :provider => :crontab) - - assert_equal( - "bin", inst.should(:target), - - "target did not default to user with crontab") - end - end - - # #705 - make sure extra spaces don't screw things up - def test_spaces_in_command - string = "echo multiple spaces" - cron = @crontype.new(:name => "space testing", :command => string) - assert_apply(cron) - - cron = @crontype.new(:name => "space testing", :command => string) - - # Now make sure that it's correctly in sync - cron.provider.class.prefetch("testing" => cron) - properties = cron.retrieve - assert_equal(string, properties[:command], "Cron did not pick up extra spaces in command") - assert(cron.parameter(:command).insync?(properties[:command]), "Command changed with multiple spaces") - end -end - -