diff --git a/spec/integration/provider/cron/crontab_spec.rb b/spec/integration/provider/cron/crontab_spec.rb index a88eb1c76..e75523cac 100644 --- a/spec/integration/provider/cron/crontab_spec.rb +++ b/spec/integration/provider/cron/crontab_spec.rb @@ -1,252 +1,241 @@ #!/usr/bin/env ruby require 'spec_helper' require 'puppet/file_bucket/dipper' +require 'puppet_spec/compiler' describe Puppet::Type.type(:cron).provider(:crontab), '(integration)', :unless => Puppet.features.microsoft_windows? do include PuppetSpec::Files + include PuppetSpec::Compiler before :each do Puppet::Type.type(:cron).stubs(:defaultprovider).returns described_class Puppet::FileBucket::Dipper.any_instance.stubs(:backup) # Don't backup to filebucket # I don't want to execute anything described_class.stubs(:filetype).returns Puppet::Util::FileType::FileTypeFlat described_class.stubs(:default_target).returns crontab_user1 # I don't want to stub Time.now to get a static header because I don't know # where Time.now is used elsewhere, so just go with a very simple header described_class.stubs(:header).returns "# HEADER: some simple\n# HEADER: header\n" FileUtils.cp(my_fixture('crontab_user1'), crontab_user1) FileUtils.cp(my_fixture('crontab_user2'), crontab_user2) end after :each do described_class.clear end let :crontab_user1 do tmpfile('cron_integration_specs') end let :crontab_user2 do tmpfile('cron_integration_specs') end - def run_in_catalog(*resources) - catalog = Puppet::Resource::Catalog.new - catalog.host_config = false - resources.each do |resource| - resource.expects(:err).never - catalog.add_resource(resource) - end - - # the resources are not properly contained and generated resources - # will end up with dangling edges without this stubbing: - catalog.stubs(:container_of).returns resources[0] - catalog.apply - end - def expect_output(fixture_name) File.read(crontab_user1).should == File.read(my_fixture(fixture_name)) end describe "when managing a cron entry" do it "should be able to purge unmanaged entries" do - resource = Puppet::Type.type(:cron).new( - :name => 'only managed entry', - :ensure => :present, - :command => '/bin/true', - :target => crontab_user1, - :user => crontab_user1 - ) - resources = Puppet::Type.type(:resources).new( - :name => 'cron', - :purge => 'true' - ) - run_in_catalog(resource, resources) + apply_with_error_check(<<-MANIFEST) + cron { + 'only managed entry': + ensure => 'present', + command => '/bin/true', + target => '#{crontab_user1}', + } + resources { 'cron': purge => 'true' } + MANIFEST expect_output('purged') end describe "with ensure absent" do it "should do nothing if entry already absent" do - resource = Puppet::Type.type(:cron).new( - :name => 'no_such_entry', - :ensure => :absent, - :target => crontab_user1, - :user => crontab_user1 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'no_such_entry': + ensure => 'absent', + target => '#{crontab_user1}', + } + MANIFEST expect_output('crontab_user1') end it "should remove the resource from crontab if present" do - resource = Puppet::Type.type(:cron).new( - :name => 'My daily failure', - :ensure => :absent, - :target => crontab_user1, - :user => crontab_user1 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'My daily failure': + ensure => 'absent', + target => '#{crontab_user1}', + } + MANIFEST expect_output('remove_named_resource') end it "should remove a matching cronentry if present" do - resource = Puppet::Type.type(:cron).new( - :name => 'no_such_named_resource_in_crontab', - :ensure => :absent, - :minute => [ '17-19', '22' ], - :hour => [ '0-23/2' ], - :weekday => 'Tue', - :command => '/bin/unnamed_regular_command', - :target => crontab_user1, - :user => crontab_user1 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'no_such_named_resource_in_crontab': + ensure => absent, + minute => [ '17-19', '22' ], + hour => [ '0-23/2' ], + weekday => 'Tue', + command => '/bin/unnamed_regular_command', + target => '#{crontab_user1}', + } + MANIFEST expect_output('remove_unnamed_resource') end end describe "with ensure present" do context "and no command specified" do it "should work if the resource is already present" do - resource = Puppet::Type.type(:cron).new( - :name => 'My daily failure', - :special => 'daily', - :target => crontab_user1, - :user => crontab_user1 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'My daily failure': + special => 'daily', + target => '#{crontab_user1}', + } + MANIFEST expect_output('crontab_user1') end it "should fail if the resource needs creating" do - resource = Puppet::Type.type(:cron).new( - :name => 'Entirely new resource', - :special => 'daily', - :target => crontab_user1, - :user => crontab_user1 - ) - resource.expects(:err).with(regexp_matches(/no command/)) - run_in_catalog(resource) + manifest = <<-MANIFEST + cron { + 'Entirely new resource': + special => 'daily', + target => '#{crontab_user1}', + } + MANIFEST + apply_compiled_manifest(manifest) do |res| + if res.ref == 'Cron[Entirely new resource]' + res.expects(:err).with(regexp_matches(/no command/)) + else + res.expects(:err).never + end + end end end it "should do nothing if entry already present" do - resource = Puppet::Type.type(:cron).new( - :name => 'My daily failure', - :special => 'daily', - :command => '/bin/false', - :target => crontab_user1, - :user => crontab_user1 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'My daily failure': + special => 'daily', + command => '/bin/false', + target => '#{crontab_user1}', + } + MANIFEST expect_output('crontab_user1') end it "should work correctly when managing 'target' but not 'user'" do - resource = Puppet::Type.type(:cron).new( - :name => 'My daily failure', - :special => 'daily', - :command => '/bin/false', - :target => crontab_user1 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'My daily failure': + special => 'daily', + command => '/bin/false', + target => '#{crontab_user1}', + } + MANIFEST expect_output('crontab_user1') end it "should do nothing if a matching entry already present" do - resource = Puppet::Type.type(:cron).new( - :name => 'no_such_named_resource_in_crontab', - :ensure => :present, - :minute => [ '17-19', '22' ], - :hour => [ '0-23/2' ], - :command => '/bin/unnamed_regular_command', - :target => crontab_user1, - :user => crontab_user1 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'no_such_named_resource_in_crontab': + ensure => present, + minute => [ '17-19', '22' ], + hour => [ '0-23/2' ], + command => '/bin/unnamed_regular_command', + target => '#{crontab_user1}', + } + MANIFEST expect_output('crontab_user1') end it "should add a new normal entry if currently absent" do - resource = Puppet::Type.type(:cron).new( - :name => 'new entry', - :ensure => :present, - :minute => '12', - :weekday => 'Tue', - :command => '/bin/new', - :environment => [ - 'MAILTO=""', - 'SHELL=/bin/bash' - ], - :target => crontab_user1, - :user => crontab_user1 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'new entry': + ensure => present, + minute => '12', + weekday => 'Tue', + command => '/bin/new', + environment => [ + 'MAILTO=""', + 'SHELL=/bin/bash' + ], + target => '#{crontab_user1}', + } + MANIFEST expect_output('create_normal_entry') end it "should add a new special entry if currently absent" do - resource = Puppet::Type.type(:cron).new( - :name => 'new special entry', - :ensure => :present, - :special => 'reboot', - :command => 'echo "Booted" 1>&2', - :environment => 'MAILTO=bob@company.com', - :target => crontab_user1, - :user => crontab_user1 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'new special entry': + ensure => present, + special => 'reboot', + command => 'echo "Booted" 1>&2', + environment => 'MAILTO=bob@company.com', + target => '#{crontab_user1}', + } + MANIFEST expect_output('create_special_entry') end it "should change existing entry if out of sync" do - resource = Puppet::Type.type(:cron).new( - :name => 'Monthly job', - :ensure => :present, - :special => 'monthly', -# :minute => ['22'], - :command => '/usr/bin/monthly', - :environment => [], - :target => crontab_user1, - :user => crontab_user1 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'Monthly job': + ensure => present, + special => 'monthly', + #minute => ['22'], + command => '/usr/bin/monthly', + environment => [], + target => '#{crontab_user1}', + } + MANIFEST expect_output('modify_entry') end it "should change a special schedule to numeric if requested" do - resource = Puppet::Type.type(:cron).new( - :name => 'My daily failure', - :special => 'absent', - :command => '/bin/false', - :target => crontab_user1, - :user => crontab_user1 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'My daily failure': + special => 'absent', + command => '/bin/false', + target => '#{crontab_user1}', + } + MANIFEST expect_output('unspecialized') end it "should not try to move an entry from one file to another" do # force the parsedfile provider to also parse user1's crontab - random_resource = Puppet::Type.type(:cron).new( - :name => 'foo', - :ensure => :absent, - :target => crontab_user1, - :user => crontab_user1 - ) - resource = Puppet::Type.type(:cron).new( - :name => 'My daily failure', - :special => 'daily', - :command => "/bin/false", - :target => crontab_user2, - :user => crontab_user2 - ) - run_in_catalog(resource) + apply_with_error_check(<<-MANIFEST) + cron { + 'foo': + ensure => absent, + target => '#{crontab_user1}'; + 'My daily failure': + special => 'daily', + command => "/bin/false", + target => '#{crontab_user2}', + } + MANIFEST File.read(crontab_user1).should == File.read(my_fixture('moved_cronjob_input1')) File.read(crontab_user2).should == File.read(my_fixture('moved_cronjob_input2')) end end end end diff --git a/spec/lib/puppet_spec/compiler.rb b/spec/lib/puppet_spec/compiler.rb index cf4851807..02c448d1f 100644 --- a/spec/lib/puppet_spec/compiler.rb +++ b/spec/lib/puppet_spec/compiler.rb @@ -1,36 +1,46 @@ module PuppetSpec::Compiler def compile_to_catalog(string, node = Puppet::Node.new('foonode')) Puppet[:code] = string Puppet::Parser::Compiler.compile(node) end def compile_to_ral(manifest) catalog = compile_to_catalog(manifest) ral = catalog.to_ral ral.finalize ral end def compile_to_relationship_graph(manifest, prioritizer = Puppet::Graph::SequentialPrioritizer.new) ral = compile_to_ral(manifest) graph = Puppet::Graph::RelationshipGraph.new(prioritizer) graph.populate_from(ral) graph end def apply_compiled_manifest(manifest, prioritizer = Puppet::Graph::SequentialPrioritizer.new) - transaction = Puppet::Transaction.new(compile_to_ral(manifest), + catalog = compile_to_ral(manifest) + if block_given? + catalog.resources.each { |res| yield res } + end + transaction = Puppet::Transaction.new(catalog, Puppet::Transaction::Report.new("apply"), prioritizer) transaction.evaluate transaction.report.finalize_report transaction end + def apply_with_error_check(manifest) + apply_compiled_manifest(manifest) do |res| + res.expects(:err).never + end + end + def order_resources_traversed_in(relationships) order_seen = [] relationships.traverse { |resource| order_seen << resource.ref } order_seen end end