diff options
author | Claire McQuin <claire@getchef.com> | 2015-05-08 17:31:42 -0700 |
---|---|---|
committer | Bryan McLellan <btm@loftninjas.org> | 2015-05-27 14:16:22 -0400 |
commit | 67b9fdc307fd0a7480cc4f11c18540763ec43b09 (patch) | |
tree | a08e020a19158bef3fe6ae2166d932ed2865eb87 /spec/unit/client_spec.rb | |
parent | 49d25cdb67ebef05aa62df3662c3c79466abace7 (diff) | |
download | chef-67b9fdc307fd0a7480cc4f11c18540763ec43b09.tar.gz |
Mark run failed on failed audits unless configured to audit as warning.
Remove unnecessary newline from RunFailedWrappingError backtrace
Diffstat (limited to 'spec/unit/client_spec.rb')
-rw-r--r-- | spec/unit/client_spec.rb | 300 |
1 files changed, 179 insertions, 121 deletions
diff --git a/spec/unit/client_spec.rb b/spec/unit/client_spec.rb index d8c4ede796..2f03b23e32 100644 --- a/spec/unit/client_spec.rb +++ b/spec/unit/client_spec.rb @@ -407,13 +407,18 @@ describe Chef::Client do end end - describe "when converge fails" do + context "when converge errors" do include_context "a client run" do - let(:e) { Exception.new } + + let(:converge_error) do + err = Chef::Exceptions::UnsupportedAction.new("Action unsupported") + err.set_backtrace([ "/path/recipe.rb:15", "/path/recipe.rb:12" ]) + err + end + def stub_for_converge expect(Chef::Runner).to receive(:new).and_return(runner) - expect(runner).to receive(:converge).and_raise(e) - expect(Chef::Application).to receive(:debug_stacktrace).with an_instance_of(Chef::Exceptions::RunFailedWrappingError) + expect(runner).to receive(:converge).and_raise(converge_error) end def stub_for_node_save @@ -432,179 +437,232 @@ describe Chef::Client do expect_any_instance_of(Chef::ResourceReporter).to receive(:run_failed) expect_any_instance_of(Chef::Audit::AuditReporter).to receive(:run_failed) end - end - it "runs the audits and raises the error" do - expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error| - expect(error.wrapped_errors.size).to eq(1) - expect(error.wrapped_errors[0]).to eq(e) + before do + expect(Chef::Application).to receive(:debug_stacktrace).with an_instance_of(Chef::Exceptions::RunFailedWrappingError) end - end - end - - describe "when the audit phase fails" do - context "with an exception" do - context "when audit mode is enabled" do - include_context "a client run" do - let(:e) { Exception.new } - def stub_for_audit - expect(Chef::Audit::Runner).to receive(:new).and_return(audit_runner) - expect(audit_runner).to receive(:run).and_raise(e) - expect(Chef::Application).to receive(:debug_stacktrace).with an_instance_of(Chef::Exceptions::RunFailedWrappingError) - end - - def stub_for_run - expect_any_instance_of(Chef::RunLock).to receive(:acquire) - expect_any_instance_of(Chef::RunLock).to receive(:save_pid) - expect_any_instance_of(Chef::RunLock).to receive(:release) - - # Post conditions: check that node has been filled in correctly - expect(client).to receive(:run_started) - expect(client).to receive(:run_failed) - expect_any_instance_of(Chef::ResourceReporter).to receive(:run_failed) - expect_any_instance_of(Chef::Audit::AuditReporter).to receive(:run_failed) - end - end - - it "should save the node after converge and raise exception" do + context "without audit phase errors" do + it "skips node save and raises the converge error in a wrapping error" do expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error| expect(error.wrapped_errors.size).to eq(1) - expect(error.wrapped_errors[0]).to eq(e) + expect(error.wrapped_errors).to include(converge_error) + expect(error.backtrace).to include(*converge_error.backtrace) end end end - context "when audit mode is disabled" do - include_context "a client run" do - before do - Chef::Config[:audit_mode] = :disabled + context "when audit phase errors" do + context "with failed audits" do + + let(:audit_error) do + err = Chef::Exceptions::AuditsFailed.new(num_failed, num_total) + err.set_backtrace([ "/path/recipe.rb:57", "/path/recipe.rb:55" ]) + err end - let(:e) { FooError.new } + let(:num_failed) { 1 } + + let(:num_total) { 5 } def stub_for_audit - expect(Chef::Audit::Runner).to_not receive(:new) + expect(Chef::Audit::Runner).to receive(:new).and_return(audit_runner) + expect(audit_runner).to receive(:run) + expect(audit_runner).to receive(:failed?).and_return(true) + expect(Chef::Exceptions::AuditsFailed).to receive(:new).with(num_failed, num_total).and_return(audit_error) + allow(audit_runner).to receive(:num_failed).and_return(num_failed) + allow(audit_runner).to receive(:num_total).and_return(num_total) end - def stub_for_converge - expect(Chef::Runner).to receive(:new).and_return(runner) - expect(runner).to receive(:converge).and_raise(e) - expect(Chef::Application).to receive(:debug_stacktrace).with an_instance_of(FooError) + context "with audit_as_warning true" do + before do + Chef::Config[:audit_as_warning] = true + end + + it "skips node save and raises the converge error in a wrapping error" do + expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error| + expect(error.wrapped_errors.size).to eq(1) + expect(error.wrapped_errors[0]).to eq(converge_error) + end + end end - def stub_for_node_save - expect(client).to_not receive(:save_updated_node) + context "with audit_as_warning false" do + + before do + Chef::Config[:audit_as_warning] = false + end + + it "skips node save and raises converge and audit errors in a wrapping error" do + expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error| + expect(error.wrapped_errors.size).to eq(2) + expect(error.wrapped_errors).to include(converge_error) + expect(error.wrapped_errors).to include(audit_error) + expect(error.backtrace).to include(*converge_error.backtrace) + expect(error.backtrace).to include(*audit_error.backtrace) + end + end end + end - def stub_for_run - expect_any_instance_of(Chef::RunLock).to receive(:acquire) - expect_any_instance_of(Chef::RunLock).to receive(:save_pid) - expect_any_instance_of(Chef::RunLock).to receive(:release) - + context "with unexpected error" do - # Post conditions: check that node has been filled in correctly - expect(client).to receive(:run_started) - expect(client).to receive(:run_failed) + let(:audit_error) do + err = RuntimeError.new("Unexpected audit error") + err.set_backtrace([ "/path/recipe.rb:57", "/path/recipe.rb:55" ]) + err + end - expect_any_instance_of(Chef::ResourceReporter).to receive(:run_failed) + def stub_for_audit + expect(Chef::Audit::Runner).to receive(:new).and_return(audit_runner) + expect(audit_runner).to receive(:run).and_raise(audit_error) + end + context "with audit_as_warning true" do + it "skips node save and raises converge and audit errors in a wrapping error" do + expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error| + expect(error.wrapped_errors.size).to eq(2) + expect(error.wrapped_errors).to include(converge_error) + expect(error.wrapped_errors).to include(audit_error) + expect(error.backtrace).to include(*converge_error.backtrace) + expect(error.backtrace).to include(*audit_error.backtrace) + end + end end - it "re-raises an unwrapped exception" do - expect { client.run }.to raise_error(FooError) + context "with audit_as_warning false" do + it "skips node save and raises converge and audit errors in a wrapping error" do + expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error| + expect(error.wrapped_errors.size).to eq(2) + expect(error.wrapped_errors).to include(converge_error) + expect(error.wrapped_errors).to include(audit_error) + expect(error.backtrace).to include(*converge_error.backtrace) + expect(error.backtrace).to include(*audit_error.backtrace) + end + end end end end + end + end + context "when audit phase errors" do + include_context "a client run" do - end + def stub_for_run + expect_any_instance_of(Chef::RunLock).to receive(:acquire) + expect_any_instance_of(Chef::RunLock).to receive(:save_pid) + expect_any_instance_of(Chef::RunLock).to receive(:release) + + # Post conditions: check that node has been filled in correctly + expect(client).to receive(:run_started) + end + + context "with failed audits" do - context "with failed audits" do - include_context "a client run" do - let(:audit_runner) do - instance_double("Chef::Audit::Runner", :run => true, :failed? => true, :num_failed => 1, :num_total => 1) + let(:audit_error) do + err = Chef::Exceptions::AuditsFailed.new(num_failed, num_total) + err.set_backtrace([ "/path/recipe.rb:57", "/path/recipe.rb:55" ]) + err end + let(:num_failed) { 1 } + + let(:num_total) { 5 } + def stub_for_audit expect(Chef::Audit::Runner).to receive(:new).and_return(audit_runner) - expect(Chef::Application).to receive(:debug_stacktrace).with an_instance_of(Chef::Exceptions::RunFailedWrappingError) + expect(audit_runner).to receive(:run) + expect(audit_runner).to receive(:failed?).and_return(true) + expect(Chef::Exceptions::AuditsFailed).to receive(:new).with(num_failed, num_total).and_return(audit_error) + allow(audit_runner).to receive(:num_failed).and_return(num_failed) + allow(audit_runner).to receive(:num_total).and_return(num_total) end - def stub_for_run - expect_any_instance_of(Chef::RunLock).to receive(:acquire) - expect_any_instance_of(Chef::RunLock).to receive(:save_pid) - expect_any_instance_of(Chef::RunLock).to receive(:release) - - # Post conditions: check that node has been filled in correctly - expect(client).to receive(:run_started) - expect(client).to receive(:run_failed) + context "with audit_as_warning true" do + before do + Chef::Config[:audit_as_warning] = true + end - expect_any_instance_of(Chef::ResourceReporter).to receive(:run_failed) - expect_any_instance_of(Chef::Audit::AuditReporter).to receive(:run_failed) + it "saves the node and completes the run successfully" do + expect(client).to receive(:run_completed_successfully) + expect_any_instance_of(Chef::ResourceReporter).to receive(:run_completed) + expect_any_instance_of(Chef::Audit::AuditReporter).to receive(:run_completed) + client.run + end end - end - it "should save the node after converge and raise exception" do - expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error| - expect(error.wrapped_errors.size).to eq(1) - expect(error.wrapped_errors[0]).to be_instance_of(Chef::Exceptions::AuditsFailed) - end - end - end - end + context "with audit_as_warning false" do - describe "when why_run mode is enabled" do - include_context "a client run" do + before do + Chef::Config[:audit_as_warning] = false + expect(Chef::Application).to receive(:debug_stacktrace).with an_instance_of(Chef::Exceptions::RunFailedWrappingError) + end - before do - Chef::Config[:why_run] = true - end + it "saves the node and raises audit error in a wrapping error" do + expect(client).to receive(:run_failed) + expect_any_instance_of(Chef::ResourceReporter).to receive(:run_failed) + expect_any_instance_of(Chef::Audit::AuditReporter).to receive(:run_failed) - def stub_for_audit - expect(Chef::Audit::Runner).to_not receive(:new) + expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error| + expect(error.wrapped_errors.size).to eq(1) + expect(error.wrapped_errors).to include(audit_error) + expect(error.backtrace).to include(*audit_error.backtrace) + end + end + end end - def stub_for_node_save - # This is how we should be mocking external calls - not letting it fall all the way through to the - # REST call - expect(node).to receive(:save) - end + context "with unexpected error" do - it "runs successfully without enabling the audit runner" do - client.run + let(:audit_error) do + err = RuntimeError.new("Unexpected audit error") + err.set_backtrace([ "/path/recipe.rb:57", "/path/recipe.rb:55" ]) + err + end - # fork is stubbed, so we can see the outcome of the run - expect(node.automatic_attrs[:platform]).to eq("example-platform") - expect(node.automatic_attrs[:platform_version]).to eq("example-platform-1.0") - end - end - end + def stub_for_audit + expect(Chef::Audit::Runner).to receive(:new).and_return(audit_runner) + expect(audit_runner).to receive(:run).and_raise(audit_error) + end - describe "when audits are disabled" do - include_context "a client run" do + before do + expect(Chef::Application).to receive(:debug_stacktrace).with an_instance_of(Chef::Exceptions::RunFailedWrappingError) + end - before do - Chef::Config[:audit_mode] = :disabled - end + context "with audit_as_warning true" do + it "saves the node and raises audit error in a wrapping error" do + expect(client).to receive(:run_failed) + expect_any_instance_of(Chef::ResourceReporter).to receive(:run_failed) + expect_any_instance_of(Chef::Audit::AuditReporter).to receive(:run_failed) - def stub_for_audit - expect(Chef::Audit::Runner).to_not receive(:new) - end + expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error| + expect(error.wrapped_errors.size).to eq(1) + expect(error.wrapped_errors).to include(audit_error) + expect(error.backtrace).to include(*audit_error.backtrace) + end + end + end - it "runs successfully without enabling the audit runner" do - client.run + context "with audit_as_warning false" do + it "skips node save and raises converge and audit errors in a wrapping error" do + expect(client).to receive(:run_failed) + expect_any_instance_of(Chef::ResourceReporter).to receive(:run_failed) + expect_any_instance_of(Chef::Audit::AuditReporter).to receive(:run_failed) - # fork is stubbed, so we can see the outcome of the run - expect(node.automatic_attrs[:platform]).to eq("example-platform") - expect(node.automatic_attrs[:platform_version]).to eq("example-platform-1.0") + expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error| + expect(error.wrapped_errors.size).to eq(1) + expect(error.wrapped_errors).to include(audit_error) + expect(error.backtrace).to include(*audit_error.backtrace) + end + end + end end end - end + end end - describe "when handling run failures" do it "should remove the run_lock on failure of #load_node" do |