diff options
-rw-r--r-- | lib/chef/application/exit_code.rb | 83 | ||||
-rw-r--r-- | lib/chef/exceptions.rb | 2 | ||||
-rw-r--r-- | lib/chef/platform/rebooter.rb | 3 | ||||
-rw-r--r-- | spec/functional/rebooter_spec.rb | 1 | ||||
-rw-r--r-- | spec/integration/client/exit_code_spec.rb | 106 | ||||
-rw-r--r-- | spec/unit/application/exit_code_spec.rb | 89 | ||||
-rw-r--r-- | spec/unit/application_spec.rb | 13 |
7 files changed, 28 insertions, 269 deletions
diff --git a/lib/chef/application/exit_code.rb b/lib/chef/application/exit_code.rb index 610a356a7c..246c95380b 100644 --- a/lib/chef/application/exit_code.rb +++ b/lib/chef/application/exit_code.rb @@ -45,47 +45,17 @@ class Chef class << self def normalize_exit_code(exit_code = nil) - if normalization_not_configured? - normalize_legacy_exit_code_with_warning(exit_code) - elsif normalization_disabled? - normalize_legacy_exit_code(exit_code) + normalized_exit_code = normalize_legacy_exit_code(exit_code) + if valid_exit_codes.include? normalized_exit_code + normalized_exit_code else - normalize_exit_code_to_rfc(exit_code) + Chef::Log.warn(non_standard_exit_code_warning(normalized_exit_code)) + VALID_RFC_062_EXIT_CODES[:GENERIC_FAILURE] end end - def enforce_rfc_062_exit_codes? - !normalization_disabled? && !normalization_not_configured? - end - - def notify_reboot_exit_code_deprecation - return if normalization_disabled? - notify_on_deprecation(reboot_deprecation_warning) - end - - def notify_deprecated_exit_code - return if normalization_disabled? - notify_on_deprecation(deprecation_warning) - end - private - def normalization_disabled? - Chef::Config[:exit_status] == :disabled - end - - def normalization_not_configured? - Chef::Config[:exit_status].nil? - end - - def normalize_legacy_exit_code_with_warning(exit_code) - normalized_exit_code = normalize_legacy_exit_code(exit_code) - unless valid_exit_codes.include? normalized_exit_code - notify_on_deprecation(deprecation_warning) - end - normalized_exit_code - end - def normalize_legacy_exit_code(exit_code) case exit_code when Integer @@ -93,15 +63,6 @@ class Chef when Exception lookup_exit_code_by_exception(exit_code) else - default_exit_code - end - end - - def normalize_exit_code_to_rfc(exit_code) - normalized_exit_code = normalize_legacy_exit_code_with_warning(exit_code) - if valid_exit_codes.include? normalized_exit_code - normalized_exit_code - else VALID_RFC_062_EXIT_CODES[:GENERIC_FAILURE] end end @@ -111,15 +72,8 @@ class Chef VALID_RFC_062_EXIT_CODES[:SIGINT_RECEIVED] elsif sigterm_received?(exception) VALID_RFC_062_EXIT_CODES[:SIGTERM_RECEIVED] - elsif normalization_disabled? || normalization_not_configured? - if legacy_exit_code?(exception) - # We have lots of "Chef::Application.fatal!('', 2) - # This maintains that behavior at initial introduction - # and when the RFC exit_status compliance is disabled. - VALID_RFC_062_EXIT_CODES[:SIGINT_RECEIVED] - else - VALID_RFC_062_EXIT_CODES[:GENERIC_FAILURE] - end + elsif legacy_exit_code?(exception) + VALID_RFC_062_EXIT_CODES[:GENERIC_FAILURE] elsif reboot_scheduled?(exception) VALID_RFC_062_EXIT_CODES[:REBOOT_SCHEDULED] elsif reboot_needed?(exception) @@ -204,26 +158,11 @@ class Chef # the current exit code assignment. end - def deprecation_warning - "Chef RFC 062 (https://github.com/chef/chef-rfc/blob/master/rfc062-exit-status.md) defines the" \ + def non_standard_exit_code_warning(exit_code) + "Chef attempted to exit with a non-standard exit code of #{exit_code}." \ + " Chef RFC 062 (https://github.com/chef/chef-rfc/blob/master/rfc062-exit-status.md) defines the" \ " exit codes that should be used with Chef. Chef::Application::ExitCode defines valid exit codes" \ - " In a future release, non-standard exit codes will be redefined as" \ - " GENERIC_FAILURE unless `exit_status` is set to `:disabled` in your client.rb." - end - - def reboot_deprecation_warning - "Per RFC 062 (https://github.com/chef/chef-rfc/blob/master/rfc062-exit-status.md)" \ - ", when a reboot is requested Chef Client will exit with an exit code of 35, REBOOT_SCHEDULED." \ - " To maintain the current behavior (an exit code of 0), you will need to set `exit_status` to" \ - " `:disabled` in your client.rb" - end - - def default_exit_code - if normalization_disabled? || normalization_not_configured? - DEPRECATED_RFC_062_EXIT_CODES[:DEPRECATED_FAILURE] - else - VALID_RFC_062_EXIT_CODES[:GENERIC_FAILURE] - end + " Non-standard exit codes are redefined as GENERIC_FAILURE." end end diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb index 78bdf0cf4a..be46f262a4 100644 --- a/lib/chef/exceptions.rb +++ b/lib/chef/exceptions.rb @@ -62,8 +62,6 @@ class Chef class DeprecatedExitCode < RuntimeError def initalize super "Exiting with a non RFC 062 Exit Code." - require "chef/application/exit_code" - Chef::Application::ExitCode.notify_deprecated_exit_code end end diff --git a/lib/chef/platform/rebooter.rb b/lib/chef/platform/rebooter.rb index 6829b66539..33a6e24be2 100644 --- a/lib/chef/platform/rebooter.rb +++ b/lib/chef/platform/rebooter.rb @@ -51,8 +51,7 @@ class Chef raise Chef::Exceptions::RebootFailed.new(e.message) end - raise Chef::Exceptions::Reboot.new(msg) if Chef::Application::ExitCode.enforce_rfc_062_exit_codes? - Chef::Application::ExitCode.notify_reboot_exit_code_deprecation + raise Chef::Exceptions::Reboot.new(msg) end # this is a wrapper function so Chef::Client only needs a single line of code. diff --git a/spec/functional/rebooter_spec.rb b/spec/functional/rebooter_spec.rb index 1b6e95b39c..a28491cc0b 100644 --- a/spec/functional/rebooter_spec.rb +++ b/spec/functional/rebooter_spec.rb @@ -72,6 +72,7 @@ describe Chef::Platform::Rebooter do def test_rebooter_method(method_sym, is_windows, expected_reboot_str) allow(ChefConfig).to receive(:windows?).and_return(is_windows) expect(rebooter).to receive(:shell_out!).once.with(expected_reboot_str) + expect(rebooter).to receive(:raise).with(Chef::Exceptions::Reboot) expect(rebooter).to receive(method_sym).once.and_call_original rebooter.send(method_sym, run_context.node) end diff --git a/spec/integration/client/exit_code_spec.rb b/spec/integration/client/exit_code_spec.rb index 30020f6a3f..4397426723 100644 --- a/spec/integration/client/exit_code_spec.rb +++ b/spec/integration/client/exit_code_spec.rb @@ -25,7 +25,7 @@ describe "chef-client" do let(:critical_env_vars) { %w{PATH RUBYOPT BUNDLE_GEMFILE GEM_PATH}.map { |o| "#{o}=#{ENV[o]}" } .join(" ") } - when_the_repository "does not have exit_status configured" do + when_the_repository "uses RFC 062 defined exit codes" do def setup_client_rb file "config/client.rb", <<EOM @@ -43,110 +43,6 @@ EOM end def run_chef_client_and_expect_exit_code(exit_code) - shell_out!( - "#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default'", - :cwd => chef_dir, - :returns => [exit_code]) - end - - context "has a cookbook" do - context "with a library" do - context "which cannot be loaded" do - before do - file "cookbooks/x/recipes/default.rb", "" - file "cookbooks/x/libraries/error.rb", "require 'does/not/exist'" - end - - it "exits with GENERIC_FAILURE, 1" do - setup_client_rb - run_chef_client_and_expect_exit_code 1 - end - end - end - - context "with an audit recipe" do - context "which fails" do - before do - file "cookbooks/x/recipes/default.rb", <<-RECIPE -control_group "control group without top level control" do - it "should fail" do - expect(2 - 2).to eq(1) - end -end -RECIPE - end - - it "exits with GENERIC_FAILURE, 1" do - setup_client_rb_with_audit_mode - run_chef_client_and_expect_exit_code 1 - end - end - end - - context "with a recipe" do - context "which throws an error" do - before { file "cookbooks/x/recipes/default.rb", "raise 'BOOM'" } - - it "exits with GENERIC_FAILURE, 1" do - setup_client_rb - run_chef_client_and_expect_exit_code 1 - end - end - - context "with a recipe which calls Chef::Application.fatal with a non-RFC exit code" do - before { file "cookbooks/x/recipes/default.rb", "Chef::Application.fatal!('BOOM', 123)" } - - it "exits with the specified exit code" do - setup_client_rb - run_chef_client_and_expect_exit_code 123 - end - end - - context "with a recipe which calls Chef::Application.exit with a non-RFC exit code" do - before { file "cookbooks/x/recipes/default.rb", "Chef::Application.exit!('BOOM', 231)" } - - it "exits with the specified exit code" do - setup_client_rb - run_chef_client_and_expect_exit_code 231 - end - end - end - - context "when an attempt to reboot fails (like from the reboot resource)" do - before do - file "cookbooks/x/recipes/default.rb", <<EOM -raise Chef::Exceptions::RebootFailed.new -EOM - end - - it "exits with GENERIC_FAILURE, 1" do - setup_client_rb - run_chef_client_and_expect_exit_code 1 - end - end - end - end - - when_the_repository "does has exit_status enabled" do - - def setup_client_rb - file "config/client.rb", <<EOM -local_mode true -cookbook_path "#{path_to('cookbooks')}" -exit_status :enabled -EOM - end - - def setup_client_rb_with_audit_mode - file "config/client.rb", <<EOM -local_mode true -cookbook_path "#{path_to('cookbooks')}" -exit_status :enabled -audit_mode :audit_only -EOM - end - - def run_chef_client_and_expect_exit_code(exit_code) shell_out!("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default'", :cwd => chef_dir, :returns => [exit_code]) diff --git a/spec/unit/application/exit_code_spec.rb b/spec/unit/application/exit_code_spec.rb index 5abf19fc02..a3e5855f8a 100644 --- a/spec/unit/application/exit_code_spec.rb +++ b/spec/unit/application/exit_code_spec.rb @@ -70,92 +70,11 @@ describe Chef::Application::ExitCode do end end - context "when Chef::Config :exit_status is not configured" do - before do - allow(Chef::Config).to receive(:[]).with(:exit_status).and_return(nil) - allow(Chef::Config).to receive(:[]).with(:treat_deprecation_warnings_as_errors).and_return(false) - end - - it "writes a deprecation warning" do - expect(Chef).to receive(:deprecated).with(:exit_code, /^Chef RFC 062/) - expect(exit_codes.normalize_exit_code(151)).to eq(151) - end - - it "does not modify non-RFC exit codes" do - expect(exit_codes.normalize_exit_code(151)).to eq(151) - end - - it "returns DEPRECATED_FAILURE when no exit code is specified" do - expect(exit_codes.normalize_exit_code()).to eq(-1) - end - - it "returns SIGINT_RECEIVED when a SIGINT is received" do - expect(exit_codes.normalize_exit_code(Chef::Exceptions::SigInt.new("BOOM"))).to eq(2) - end - - it "returns SIGTERM_RECEIVED when a SIGTERM is received" do - expect(exit_codes.normalize_exit_code(Chef::Exceptions::SigTerm.new("BOOM"))).to eq(3) - end - - it "returns SIGINT_RECEIVED when a deprecated exit code error is received" do - expect(exit_codes.normalize_exit_code(Chef::Exceptions::DeprecatedExitCode.new("BOOM"))).to eq(2) - end - - it "returns GENERIC_FAILURE when an exception is specified" do - expect(exit_codes.normalize_exit_code(Exception.new("BOOM"))).to eq(1) - end - - end - - context "when Chef::Config :exit_status is configured to not validate exit codes" do - before do - allow(Chef::Config).to receive(:[]).with(:exit_status).and_return(:disabled) - allow(Chef::Config).to receive(:[]).with(:treat_deprecation_warnings_as_errors).and_return(false) - end - - it "does not write a deprecation warning" do - expect(Chef).not_to receive(:deprecated).with(:exit_code, /^Chef RFC 062/) - expect(exit_codes.normalize_exit_code(151)).to eq(151) - end - - it "does not modify non-RFC exit codes" do - expect(exit_codes.normalize_exit_code(151)).to eq(151) - end - - it "returns DEPRECATED_FAILURE when no exit code is specified" do - expect(exit_codes.normalize_exit_code()).to eq(-1) - end - - it "returns GENERIC_FAILURE when an exception is specified" do - expect(exit_codes.normalize_exit_code(Exception.new("BOOM"))).to eq(1) - end - - it "returns SUCCESS when a reboot is pending" do - allow(Chef::DSL::RebootPending).to receive(:reboot_pending?).and_return(true) - expect(exit_codes.normalize_exit_code(0)).to eq(0) - end - - it "returns SIGINT_RECEIVED when a SIGINT is received" do - expect(exit_codes.normalize_exit_code(Chef::Exceptions::SigInt.new("BOOM"))).to eq(2) - end - - it "returns SIGTERM_RECEIVED when a SIGTERM is received" do - expect(exit_codes.normalize_exit_code(Chef::Exceptions::SigTerm.new("BOOM"))).to eq(3) - end - - it "returns SIGINT_RECEIVED when a deprecated exit code error is received" do - expect(exit_codes.normalize_exit_code(Chef::Exceptions::DeprecatedExitCode.new("BOOM"))).to eq(2) - end - end - - context "when Chef::Config :exit_status is configured to validate exit codes" do - before do - allow(Chef::Config).to receive(:[]).with(:exit_status).and_return(:enabled) - allow(Chef::Config).to receive(:[]).with(:treat_deprecation_warnings_as_errors).and_return(false) - end + context "when Chef validates exit codes" do - it "does write a deprecation warning" do - expect(Chef).to receive(:deprecated).with(:exit_code, /^Chef RFC 062/) + it "does write a warning on non-standard exit codes" do + expect(Chef::Log).to receive(:warn).with( + /^Chef attempted to exit with a non-standard exit code of 151/) expect(exit_codes.normalize_exit_code(151)).to eq(1) end diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb index 867cd3f9c2..a12935fa78 100644 --- a/spec/unit/application_spec.rb +++ b/spec/unit/application_spec.rb @@ -299,16 +299,23 @@ describe Chef::Application do Chef::Application.fatal! "blah" end - describe "when an exit code is supplied" do + describe "when a standard exit code is supplied" do it "should exit with the given exit code" do - expect(Process).to receive(:exit).with(-100).and_return(true) + expect(Process).to receive(:exit).with(42).and_return(true) + Chef::Application.fatal! "blah", 42 + end + end + + describe "when a non-standard exit code is supplied" do + it "should exit with the default exit code" do + expect(Process).to receive(:exit).with(1).and_return(true) Chef::Application.fatal! "blah", -100 end end describe "when an exit code is not supplied" do it "should exit with the default exit code" do - expect(Process).to receive(:exit).with(-1).and_return(true) + expect(Process).to receive(:exit).with(1).and_return(true) Chef::Application.fatal! "blah" end end |