diff options
author | Steven Murawski <steven.murawski@gmail.com> | 2016-02-18 14:58:32 -0600 |
---|---|---|
committer | Steven Murawski <steven.murawski@gmail.com> | 2016-05-23 13:32:49 -0500 |
commit | e24b8e2cd67aef572fde184e8b07d48333184b29 (patch) | |
tree | 2b1f6507104149182791436be30561be3be1aef2 /spec/integration | |
parent | e4bca443a3ddca6381275a1a252de04f5e4883c4 (diff) | |
download | chef-e24b8e2cd67aef572fde184e8b07d48333184b29.tar.gz |
* define exit codes
* exit code functional specs
* audit exit codes
* reboot now/reboot failed/reboot pending exit codes
* Deal with forked and unforked process and get the right exit code
* Reboot Now should really be reboot scheduled
* pass exception rather than exit code
* updated with sigint and sigterm
* support legacy fatal!("", 2) behavior
* fixup all fatal! and exit! calls
Diffstat (limited to 'spec/integration')
-rw-r--r-- | spec/integration/client/exit_code_spec.rb | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/spec/integration/client/exit_code_spec.rb b/spec/integration/client/exit_code_spec.rb new file mode 100644 index 0000000000..30020f6a3f --- /dev/null +++ b/spec/integration/client/exit_code_spec.rb @@ -0,0 +1,245 @@ + +require "support/shared/integration/integration_helper" +require "chef/mixin/shell_out" +require "tiny_server" +require "tmpdir" +require "chef/platform" + +describe "chef-client" do + + include IntegrationSupport + include Chef::Mixin::ShellOut + + let(:chef_dir) { File.join(File.dirname(__FILE__), "..", "..", "..", "bin") } + + # Invoke `chef-client` as `ruby PATH/TO/chef-client`. This ensures the + # following constraints are satisfied: + # * Windows: windows can only run batch scripts as bare executables. Rubygems + # creates batch wrappers for installed gems, but we don't have batch wrappers + # in the source tree. + # * Other `chef-client` in PATH: A common case is running the tests on a + # machine that has omnibus chef installed. In that case we need to ensure + # we're running `chef-client` from the source tree and not the external one. + # cf. CHEF-4914 + let(:chef_client) { "ruby '#{chef_dir}/chef-client' --no-fork --minimal-ohai" } + + 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 + + def setup_client_rb + file "config/client.rb", <<EOM +local_mode true +cookbook_path "#{path_to('cookbooks')}" +EOM + end + + def setup_client_rb_with_audit_mode + file "config/client.rb", <<EOM +local_mode true +cookbook_path "#{path_to('cookbooks')}" +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]) + 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]) + 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(4 - 4).to eq(1) + end +end +RECIPE + end + + it "exits with AUDIT_MODE_FAILURE, 42" do + setup_client_rb_with_audit_mode + run_chef_client_and_expect_exit_code 42 + 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 GENERIC_FAILURE exit code, 1" do + setup_client_rb + run_chef_client_and_expect_exit_code 1 + 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 GENERIC_FAILURE exit code, 1" do + setup_client_rb + run_chef_client_and_expect_exit_code 1 + end + end + + context "when a reboot exception is raised (like from the reboot resource)" do + before do + file "cookbooks/x/recipes/default.rb", <<EOM +raise Chef::Exceptions::Reboot.new +EOM + end + + it "exits with REBOOT_SCHEDULED, 35" do + setup_client_rb + run_chef_client_and_expect_exit_code 35 + 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 REBOOT_FAILED, 41" do + setup_client_rb + run_chef_client_and_expect_exit_code 41 + end + end + end + end + end +end |