summaryrefslogtreecommitdiff
path: root/spec/integration
diff options
context:
space:
mode:
authorSteven Murawski <steven.murawski@gmail.com>2016-02-18 14:58:32 -0600
committerSteven Murawski <steven.murawski@gmail.com>2016-05-23 13:32:49 -0500
commite24b8e2cd67aef572fde184e8b07d48333184b29 (patch)
tree2b1f6507104149182791436be30561be3be1aef2 /spec/integration
parente4bca443a3ddca6381275a1a252de04f5e4883c4 (diff)
downloadchef-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.rb245
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